爬虫 >>> BeautifulSoup 模块

Beautiful Soup 解析库

  简称BS4;是一个可以从 HTML 或 XML 文件中提取数据的 python 库。

中文文档

  https://www.crummy.com/software/BeautifulSoup/bs4/doc/index.zh.html

安装

  pip3 install beautifulsoup4

安装解析器

# 官网推荐使用。因为效率更高(速度快, 文档容错能力强)
# 容错处理,文档的容错能力指的是在 html 代码不完整的情况下,使用该模块可以识别该错误
# 并能按照标准的缩进格式的结构输出
pip3 install lxml  

 基本使用

  遍历文档树

    直接通过标签名字选择:速度快,存在多个相同的标签则只返回第一个

from bs4 import BeautifulSoup

soup = BeautifulSoup('要解析的内容', '解析器(一般使用"lxml")')

# 1:美化作用(帮助我们处理好缩进,结构化显示)
soup = soup.prettufy()  

# 2:获取标签
soup.p  # ---> soup 内的 p 标签;存在多个相同的标签则只返回第一个
soup.a  # ---> soup 内的 a 标签;存在多个相同的标签则只返回第一个

# 2:获取标签名称
soup.p.name  # ---> 结果为 p 

# 3:获取标签内的属性
soup.p.attrs  # ---> p 标签内有多少属性都会以字典的形式返回(包括自定义属性)

# 4:获取标签内容
soup.p.string   # ---> p 标签下面文本只有一个时候可以取到,否则为 None
soup.p.strings  # ---> 拿到一个生成器对象 generater, 取到 p 下的而所有文本内容
soup.p.text  # ---> 取到 p 下所有的文本内容
for line in soup.stripped_strings:  # 去掉空白
    print(line)
    
# 5:嵌套选择
soup.head.title.string  # ---> head 标签下 title 标签内的内容

# 6:子节点、子孙节点
soup.p.contents  # ---> p 下所有子节点
soup.p.children  # ---> 得到一个迭代器,包含 p 下面所有的子节点
soup.p.descendants  # ---> 获取子孙节点,p 下所有的标签都会被选择出来

# 7:父节点、祖父节点
soup.a.parent  # 获取 a 标签的父节点
soup.a.parents  # 找到 a 标签所有的祖父节点,父亲的父亲...

# 8:兄弟节点
soup.a.next_sibling  # 下一个兄弟
soup.a.next_siblings  # 下面的兄弟们(生成器对象)
soup.a.previous_sibling  # 上一个兄弟
soup.a.previous_siblings  # 上面的兄弟们(生成器对象)

   搜索文档树

# find 与 find_all
'''
区别是 find_all() 方法的返回结果是值包含一个元素的列表
而 find() 方法直接返回结果

find_all() 方法没有找到目标是返回空列表
find() 方法找不到目标时,返回 None 
'''


from bs4 import BeautifulSoup

soup = BeautifulSoup('文档内容', 'lxml')

# 1:五中过滤器 ---> 字符串、正则表达式、列表、布尔值、方法
# 1.1:字符串(字符串代表标签名)
soup.find_all('b')  # 搜索所有的 b 标签

# 1.2:正则表达式
import re
soup.find_all(re.compile('^b'))  # 找出所有 b 开头的标签;如 body, b 标签

# 1.3:列表
soup.find_all(['a', 'b'])  # 与列表中任一元素匹配的内容返回

# 1.4:布尔值
soup.find_all(True)  # 可以匹配任何值,查找到所有的tag, 但是不会返回字符串节点

# 1.5:方法
    # 先定义一个方法:方法只接受一个元素参数。
    # 如果这个方法返回 True 表示当前元素匹配并且被找到,如果不是则反回 False
def has_class_but_no_id(tag):  
    return tag.has_attr('class') and not tag.has_attr('id')

soup.find_all(has_class_but_no_id)  # 传入方法名




# 2、find_all( name , attrs , recursive , text , **kwargs )
# 2.1、name: 搜索name参数的值可以使任一类型的 过滤器 ,字符窜,正则表达式,列表,方法或是 True .
print(soup.find_all(name=re.compile('^t')))

# 2.2、keyword: key=value的形式,value可以是过滤器:字符串 , 正则表达式 , 列表, True .
print(soup.find_all(id=re.compile('my')))
print(soup.find_all(href=re.compile('lacie'), id=re.compile('\d')))  # 注意类要用class_
print(soup.find_all(id=True))  # 查找有id属性的标签

# 有些tag属性在搜索不能使用,比如HTML5中的 data-* 属性:
data_soup = BeautifulSoup('<div data-foo="value">foo!</div>', 'lxml')
# data_soup.find_all(data-foo="value") 
#报错:SyntaxError: keyword can't be an expression
# 但是可以通过 find_all() 方法的 attrs 参数定义一个字典参数来搜索包含特殊属性的tag:
print(data_soup.find_all(attrs={"data-foo": "value"}))
# [<div data-foo="value">foo!</div>]

# 2.3、按照类名查找,注意关键字是class_,class_=value,value可以是五种选择器之一
print(soup.find_all('a', class_='sister'))  # 查找类为sister的a标签
print(soup.find_all('a', class_='sister ssss'))  # 查找类为sister和sss的a标签,顺序错误也匹配不成功
print(soup.find_all(class_=re.compile('^sis')))  # 查找类为sister的所有标签

# 2.4、attrs
print(soup.find_all('p', attrs={'class': 'story'}))

# 2.5、text: 值可以是:字符,列表,True,正则
print(soup.find_all(text='Elsie'))
print(soup.find_all('a', text='Elsie'))

# 2.6、limit参数:如果文档树很大那么搜索会很慢.如果我们不需要全部结果,可以使用 limit 参数限制返回结果的数量.
# 效果与SQL中的limit关键字类似,当搜索到的结果数量达到 limit 的限制时,就停止搜索返回结果
print(soup.find_all('a', limit=2)) # 2.7、recursive:调用tag的 find_all() 方法时,Beautiful Soup会检索当前tag的所有子孙节点
# 如果 只想搜索tag的直接子节点,可以使用参数 recursive=False .
print(soup.html.find_all('a')) print(soup.html.find_all('a', recursive=False)) ''' 像调用 find_all() 一样调用tag find_all() 几乎是Beautiful Soup中最常用的搜索方法,所以我们定义了它的简写方法.
BeautifulSoup 对象和 tag 对象可以被当作一个方法来使用,这个方法的执行结果与调用这个对象的 find_all() 方法相同,下面两行代码是等价的: soup.find_all("a") soup("a") 这两行代码也是等价的: soup.title.find_all(text=True) soup.title(text=True)
''' # 3:CSS选择器 from bs4 import BeautifulSoup soup = BeautifulSoup('dfjeisdf,'lxml') # 3.1、选择标签 print(soup.p.select('.sister')) print(soup.select('.sister span')) print(soup.select('#link1')) print(soup.select('#link1 span')) print(soup.select('#list-2 .element.xxx')) print(soup.select('#list-2')[0].select('.element')) # 可以一直select,但其实没必要,一条select就可以了 # 3.2、获取属性 print(soup.select('#list-2 h1')[0].attrs) # 3.3、获取内容 print(soup.select('#list-2 h1')[0].get_text())

   总结

# 1、推荐使用lxml解析库

# 2、三种选择器:标签选择器,find与find_all,css选择器
'''
    1、标签选择器筛选功能弱,但是速度快
    2、建议使用 find, find_all 查询匹配单个结果或者多个结果
    3、如果对 css 选择器非常熟悉建议使用 select
'''
   
# 3、记住常用的 获取属性 attrs文本值 get_text() 的方法

 

 

 

posted @ 2019-12-05 15:31  速8赛亚人  阅读(380)  评论(0编辑  收藏  举报