爬虫之BeautifulSoup4
BeautifulSoup4介绍
使用requests模块爬取网页数据时,获取到的是html(xml)内容,比较复杂,不容易获取到想要的数据。而BeautifulSoup4就是用于对html,xml进行解析(修改)。
安装:
pip install beautifulsoup4
基本语法:
BeautifulSoup('要解析的字符串', '解析方式')
Beautifulsoup4 - 刘清政 - 博客园 (cnblogs.com)
下表列出了主要的解析器,以及它们的优缺点,官网推荐使用lxml作为解析器,因为效率更高。在Python2.7.3之前的版本和Python3中3.2.2之前的版本,必须安装lxml或html5lib,因为那些Python版本的标准库中内置的HTML解析方法不够稳定。
解析器 | 使用方法 | 优势 | 劣势 |
---|---|---|---|
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格式的文档 | 速度慢 不依赖外部扩展 |
文档容错能力:可以不是标准的html,缺一些标签,也可以解析
bs4 遍历文档树
遍历文档树:即直接通过标签名字选择,特点是选择速度快,但如果存在多个相同的标签则只返回第一个。
获取html内容:
import requests
res = requests.get('https://www.cnblogs.com/')
html_doc = res.text
BeautifulSoup4使用:
from bs4 import BeautifulSoup
soup = BeautifulSoup(html_doc, 'html.parser')
# 美化html,自动缩进和补全html表标签
# print(soup.prettify())
1.获取标签
# div标签
res = soup.div
# div标签下的ul标签
res = soup.div.ul
2.取标签的名称(可以说毫无作用)
# div标签名称,即'div'
res = soup.div # 'div'
3.获取标签的属性(两种方式)
res = soup.div.ul
# ul标签的class属性
print(res['class'])
res = soup.div.ul
# ul标签的id属性
print(res.attrs['id'])
4.获取标签的内容
res = soup.div.ul
print(res.text) # text 把所有子标签的文本内容拼到一起
print(res.string) # string 没有子标签才能获取文本,有子标签返回None
print(list(res.strings)) # generator strings:把子标签的文本内容放到生成器中
5.子节点、子孙节点
# div.ul标签下的所有子节点
res = soup.div.ul.contents
print(res)
print(soup.div.ul.children) # 得到一个迭代器,包含所有子节点
# div.ul标签下的所有子节点和孙节点
print(list(soup.div.ul.descendants))
6.父节点、祖先节点
print(soup.div.parent) # 获取a标签的父节点
print(list(soup.div.parents)) # 找到a标签所有的祖先节点,父亲、父亲的父亲...
7.兄弟节点(可能存在换行符,标签外换行算一个标签)
print(soup.div.next_sibling) # 下一个兄弟
print(soup.div.previous_sibling) # 上一个兄弟
print(list(soup.div.next_siblings)) # 下面的兄弟们=>生成器对象
print(list(soup.div.previous_siblings)) # 上面的兄弟们=>生成器对象
bs4搜索文档树
获取html内容:
import requests
res = requests.get('https://www.cnblogs.com/')
html_doc = res.text
BeautifulSoup4使用:
from bs4 import BeautifulSoup
soup = BeautifulSoup(html_doc, 'html.parser')
两个方法:
- find():找最近的一个
- find_all():找所有符合的
1.字符串搜索
# 查找div标签中class属性为post-item-text
res = soup.find(name='div', class_='post-item-text')
print(res)
# 查找标签id属性为nav_dropdown_menu的标签
res = soup.find(id='nav_dropdown_menu')
print(res)
# 有符合的文本返回文本内容,没有返回None
res = soup.find(text="发现")
print(res)
2.正则表达式
import re
# 查找标签id属性为'nav'开头的的标签
res = soup.find(id=re.compile('^nav'))
print(res)
3.列表
# 查找div标签、p标签
res = soup.find(name=['div', 'p'])
print(res)
4.布尔值
# 查找id属性有值的标签
res = soup.find(id=True)
print(res)
5.方法
# 查找所有有class属性但没有id属性的表情
def has_class_but_no_id(tag):
return tag.has_attr('class') and not tag.has_attr('id')
print(soup.find_all(name=has_class_but_no_id))
find_all的其它属性
find()其实就是find_all(),只不过取了第一条。
find_all(limit=1, recursive=False, attrs={'class':True})
- limit:限制获取的条数
- recursive:是否递归查找
- attrs={'class':True}:等价于class_=True
CSS选择器
还可以使用css选择器
# res = soup.select('.abc')
# res = soup.select('#abc')
res = soup.select('#id1')[0]['class']
print(res)