1. BeautifulSoup4
1.1 BeautifulSoup4简介
BeautifulSoup4和 lxml 一样,Beautiful Soup 也是一个HTML/XML的解析器,主要的功能也是如何解析和提取 HTML/XML 数据。
lxml 只会局部遍历,而Beautiful Soup 是基于HTML DOM的,会载入整个文档,解析整个DOM树,因此时间和内存开销都会大很多,所以性能要低于lxml。
1.2 四大对象种类
from bs4 import BeautifulSoup html = """ <html><head><title>The Dormouse's story</title></head> <body> <p class="title" name="dromouse"><b>The Dormouse's story</b></p> <p class="story">Once upon a time there were three little sisters; and their names were <a href="http://example.com/elsie" class="sister" id="link1"><!-- Elsie --></a>, <a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and <a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>; and they lived at the bottom of a well.</p> <p class="story">...</p> """ soup = BeautifulSoup(html, 'lxml') # Tag 通俗点讲就是 HTML 中的一个个标签,例如: print(soup.html) # 字符串输出html print(soup.prettify()) # 美化的字符串输出html print(soup.p) # html的第一个p标签 print(type(soup.p)) # <class 'bs4.element.Tag'> print(soup.p.name) # html的第一个p标签的标签名 print(soup.p.b.name) # html的第一个p标签的第一个b标签的标签名 print(soup.head.name) # 标签名 head print(soup.p.attrs) # p标签的属性值 {'class': ['title'], 'name': 'dromouse'} print(soup.p.attrs['class']) # p标签的属性 class的值 print(soup.p['class']) # p标签的属性 class的值 print(soup.p.get('class')) # p标签的属性 class的值 soup.p['class'] = 'haha' # 修改p标签的属性 del soup.p['class'] # 删除P标签的属性class # NavigableString 标签的内容 .string print(soup.p.string) # p标签的文本 print(type(soup.p.string)) # <class 'bs4.element.NavigableString'> p_list = soup.find_all('p') # 找到所有p标签 for p in p_list: print(p.string) # 所有p标签的文本 <class 'bs4.element.NavigableString'> a_list = soup.find_all(name='a') # 找到所有a标签 for a in a_list: print(a.string) # 所有a标签的文本 <class 'bs4.element.NavigableString'> # BeautifulSoup 对象表示的是一个文档的内容。大部分时候,可以把它当作 Tag 对象,是一个特殊的 Tag,我们可以分别获取它的类型,名称,以及属性来感受一下 print(type(soup)) # <class 'bs4.BeautifulSoup'> print(type(soup.name)) # <class 'str'> print(soup.name) # [document] print(soup.attrs) # 文档本身的属性为空{} # Comment 对象是一个特殊类型的 NavigableString 对象,其输出的内容不包括注释符号。 print(soup.a.string) # Elsie print(type(soup.a.string)) # <class 'bs4.element.Comment'> # a 标签里的内容实际上是注释,但是如果我们利用 .string 来输出它的内容时,注释符号已经去掉了。
1.3遍历文档树
contents
tag 的 .contents 属性可以将tag的子节点以列表的方式输出
包括标签 <class 'bs4.element.Tag'> 空白文本节点 <class 'bs4.element.NavigableString'>
children
它返回的不是一个 list,不过我们可以通过遍历获取所有子节点。
可以发现它是一个list 生成器对象
1.4搜索文档树
find_all 得到的都为列表
a_list = soup.find_all(name='a') #找到所有标签名为a的标签 for a in a_list: print(a.string) a_list = soup.find_all(href=re.compile(r'http://example.com/')) #找到所有的href属性值能匹配正则的标签 for a in a_list: print(a['href']) print(soup.find_all(text=re.compile("Dormouse"))) #找到所有的文本内容能匹配正则的标签 print(soup.find_all(id='link2')) #找到id为link2的标签
1.5 select 选择器查找遍历
p_list = soup.select('p') #标签选择器 for p in p_list: print(type(p)) print(p.get_text()) # 取不到注释内容,可以取到嵌套标签的所有文本内容 class_list = soup.select('.sister') # 类选择器 for a in class_list: print(a.get_text()) # 取不到注释内容,为空 tag_list = soup.select('#link1') # id选择器 tag_list = soup.select('p .sister') # 后代选择器 tag_list = soup.select('body > a') # 子代选择器 for tag in tag_list: print(tag.get_text()) attr_list = soup.select('a[class="sister"]') # 属性选择器 for a in attr_list: print(a.get_text()) # 取不到注释内容,为空 print(soup.select('a[href="http://example.com/elsie"]')) # 属性选择器
select 后得到的全为列表 ,select 之后的到的列表元素可以继续select ,select得不到为空列表
tag_list = soup.select('p') for tag in tag_list: print(tag.select('b'))