BeautifulSoup4和lxml
这两个库主要是解析html/xml文档,BeautifulSoup 用来解析 HTML 比较简单,API非常人性化,支持CSS选择器、
Python标准库中的HTML解析器,也支持 lxml 的 XML解析器。关于BeautifulSoup和lxml的实例介绍如下:
一、BeautifulSoup4库:
安装:pip install beautifulsoup4 如果不写4会默认安装beautifulsoup3
数据结构、种类:Beautiful Soup将复杂HTML文档转换成一个复杂的树形结构,每个节点都是Python对象,所有对象可
以归纳为4种: Tag NavigableString BeautifulSoup Comment 。
Tag: 即我们在写网页时所使用的标签(如<a>超链接标签)
NavigableString:简单的说就是一种可以遍历的字符串
搜索文档:
使用requests库获取网页源代码:
1 import requests 2 from bs4 import BeautifulSoup 3 url = 'https://www.baidu.com/s?wd=python' 4 headers = { 5 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36',} 6 req = requests.session() 7 response = req.get(url, headers=headers, verify=False) 8 html_test = response.text
html_test就是获取的一个网页源代码,它没有爬取到JS的内容,所有可能和网页内容不完全一致!
要解析文档内容之前,先要用BeautifulSoup实例一个对象。如下,它的类型为<class 'bs4.BeautifulSoup'>
1 soup = BeautifulSoup(html_test, 'lxml') 2 print(soup, type(soup))
获取标签Tag: soup.'标签名' 就可以匹配出第一个该标签,它将会把第一次出现的该标签完整的返回。
1 print(soup.span)
获取标签属性:
1 print(type(soup.a)) 2 print(soup.a['id']) # 没有该属性会报错 3 print(soup.a.attrs) # 输出标签的属性和值 4 print(soup.a.get('id')) # 推荐使用get取属性,没有返回None 代码的运行结构:
- <class 'bs4.element.Tag'>
- result_logo
- {'href': '/', 'id': 'result_logo', 'onmousedown': "return c({'fm':'tab','tab':'logo'})"}
- None
获取文档内容:获取到标签后(或者是soup),有几种不同的方法获取标签里的内容,分别如下:
strings: 直接加 .strings 返回的是一个生成器,但是作者不能调用next()方法,查询之后使用如下
1 a = soup.div.strings 2 a.__next__()
执行之后,可以再调用a.__next__(),这样会将文本内容一条条地返回,但是大多数时候,这样做是非常麻烦的。
基于搜索方法find()和find_all()去获取文本内容:
字符串:soup.find_all('p') 获取所有的P标签,返回一个列表,soup.findl('p')只返回一个,类型为'bs4.element.Tag'
1 print(soup.find_all('p')[1]) 2 print(soup.find_all('i', class_='c-icon-lidot')) # 限制属性class
字符串里只能是标签名,不能是其他内容,否则find_all()获取的是空列表,find()获取的是None
find_all()获取的是列表元素也是类型为 'bs4.element.Tag' !
正则表达式:需要导入re,再用re.compile()根据包含的正则表达式的字符串创建模式对象。
1 import re 2 for i in soup.find_all(re.compile('span')): 3 print(i.text) # 会将span标签内的所有文本内容返回
soup.find_all(re.compile('span'))的元素仍然是'bs4.element.Tag' !
列表:find_all方法也能接受列表参数,BeautifulSoup会将与列表中任一元素匹配的内容返回。
1 print(soup.find_all(['i', 'a'])) # 获取所有的i标签和a标签
返回的数据类型为bs4.element.ResultSet,跟列表相似,可以通过索引取值且有序
方法(调用函数体):如果没有合适的过滤器,我们也可以自定义一个方法,方法只接受一个元素参数。
1 def has_class_and_no_id(tag): 2 return tag.has_attr('class') and not tag.has_attr('id') 3 for tag in soup.find_all(has_class_and_no_id): 4 print(tag) 5 # soup.find_all(has_class_and_no_id)返回的数据类型是'bs4.element.ResultSet' 6 # 同上,类似列表,可以索引取值且无序!
基于select获取:css选择器,写 CSS 时,标签名不加任何修饰,类名前加.,id名前加#;返回值是一个列表
标签名查找:soup.select('h3 a')取h3标签下的a标签;等价于soup.select('h3 > a')
1 for i in soup.select('h3 a'): 2 # text取内容时返回的是str字符串 3 result_1 = i.text 4 # get_text取内容时返回的是str字符串 5 result_2 = i.get_text() 6 # string返回的是NavigableString,没有内容,将返回None 7 result_3 = i.string 8 # strings返回的是generator 如果内容为空,将返回None 9 result_4 = i.strings 10 print(result_1, type(result_1)) 11 print(result_2, type(result_2)) 12 print(result_3, type(result_3)) 13 print(result_4, type(result_4))
类名查找或id查找: soup.select('.c-gap-left-small') soup.select('#content_bottom')
组合查找: soup.select('a .c-gap-left-small')
搜索