爬虫利器之BeautifulSoup4

Beautiful Soup是python的一个库,最主要的功能是从网页抓取数据。官方解释如下:

1
2
3
Beautiful Soup提供一些简单的、python式的函数用来处理导航、搜索、修改分析树等功能。它是一个工具箱,通过解析文档为用户提供需要抓取的数据,因为简单,所以不需要多少代码就可以写出一个完整的应用程序。
Beautiful Soup自动将输入文档转换为Unicode编码,输出文档转换为utf-8编码。你不需要考虑编码方式,除非文档没有指定一个编码方式,这时,Beautiful Soup就不能自动识别编码方式了。然后,你仅仅需要说明一下原始编码方式就可以了。
Beautiful Soup已成为和lxml、html6lib一样出色的python解释器,为用户灵活地提供不同的解析策略或强劲的速度。

语法:

  • | Python标准库 | BeautifulSoup(markup, “html.parser”)| Python的内置标准库;执行速度适中;文档容错能力强 | Python 2.7.3 or 3.2.2)前 的版本中文档容错能力差
  • | lxml HTML 解析器 | BeautifulSoup(markup, “lxml”) | 速度快;文档容错能力强 | 需要安装C语言库
  • | lxml XML 解析器 | BeautifulSoup(markup, [“lxml”, “xml”])BeautifulSoup(markup, “xml”) | 速度快;唯一支持XML的解析器 | 需要安装C语言库
  • | html5lib | BeautifulSoup(markup, “html5lib”) | 最好的容错性;以浏览器的方式解析文档;生成HTML5格式的文档 | 速度慢;不依赖外部扩展 |

soup.select ( ) 选择标签问题

代码原型是这样的:

1
2
3
4
5
6
7
import requests
from bs4 import BeautifulSoup

web_data = requests.get('url')
soup = BeautifulSoup(web_data.text,'lxml')
data = soup.select('选择内容')
print (data)

url: http://www.meihua.info/

  • 要截取一篇文章的以下字段:
  • 日期(今天)
  • 阅读量(阅读65)
  • 类型(业界)
  • 文章标签(微信,阅读量)

那么在浏览器中鼠标右键点击审查 -> 找到字段的具体代码 -> 右键选择Copy -> Copy selector,复制的内容如下:

1
body > div.main-frame > div.news-list-list > ul > li:nth-child(1) > div.time > span > span:nth-child(1)

如果直接那这个作为select ( )的参数是不行的,li:nth-child(1)要去掉,这是CSS的高级选择器,而且select ( )不支持这种类型,去掉就行。然后还要查看html结构的层级(span)。

以下是我修改的select ( )参数内容:

1
body > div.main-frame > div.news-list-list > ul.list.news-list > li > div.time > span.desc-font.date > span

运行代码试一下:

1
2
3
4
5
6
7
8
9
10
11
12
import requests
from bs4 import BeautifulSoup as bs

web_data = requests.get('http://www.meihua.info/?page=1')

soup = bs(web_data.text,'lxml')
post_date = soup.select('body > div.main-frame > div.news-list-list > ul.list.news-list > li > div.time > span.desc-font.date > span')[0]

print (post_date.get_text())

--输出结果--
今天

编码输出问题

在抓取这个网页 http://www.ikanchai.com/ 的时候,出现乱码,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import requests
from bs4 import BeautifulSoup as bs

web_data = requests.get('http://www.ikanchai.com/')
soup = bs(web_data.text,'lxml')
dates = soup.select('div.sort.channel.clearfix > ul > li > a')

for data in dates:
print (data)
-----输出结果-----
<a href="http://www.ikanchai.com/view/">观点</a>
<a href="http://www.ikanchai.com/start/">创投</a>
<a href="http://www.ikanchai.com/evaluation/">评测</a>
<a href="http://www.ikanchai.com/vr/">VR</a>
<a href="http://www.ikanchai.com/push/">ä¸“æ </a>
<a href="http://app.ikanchai.com/roll.php">动态</a>

编码问题,加一句web_data.encoding = ‘utf-8’即可以了,具体的编码选择在html文档开头有说明。

get_text和get()的使用

  • get_text(),是返回选择的标签文本,具体可以参考文档:http://beautifulsoup.readthedocs.io/zh_CN/latest/#get-text

  • get(‘’),这是选择标签中的属性(也就是里面有=符号的左边),比如

    1
    <li><a class="reference internal" href="#next-siblings-previous-siblings">

中,选择li > a这个标签之后,则可以用get(‘href’)获取其中的链接。

findall()和select()的区别

待续