爬虫之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)
posted @ 2022-08-01 21:46  Yume_Minami  阅读(176)  评论(0编辑  收藏  举报