BeautifulSoup与lxml操作html文件
一、概述
BeautifulSoup与lxml是两种常用的处理html文件的软件包,lxml基于C语言开发,所以lxml处理速度更快。经过实际测试,处理相同的html文件,即使BeautifulSoup使用lxml解析器,lxml速度也比BeautifulSoup速度快上数倍。
二、Beautifulsoup查找元素并获取元素属性
2.1查找元素
示例代码如下:
from bs4 import BeautifulSoup
with open(filePath, 'r', encoding = 'gbk', errors = 'replace') as f:
html_content = f.read()
#soup = BeautifulSoup(html_content, 'html.parser')#BeautifulSoup使用html解析器,速度上低于lxml解析器
soup = BeautifulSoup(html_content, 'lxml')#BeautifulSoup使用lxml解析器
div_element = soup.find('div')#查找单个div元素,找不到会返回None
a_elements = div_element.find_all('a')#在div元素内部查找所有a元素,返回一个列表
div_elements = soup.find_all('div', class_='class01')#查找所有class为class01的div元素
div_elements = soup.find_all('div', attrs={'class':'class01'})#与上一行代码功能相同
div_elements = soup.find_all('div', id='id01')#查找所有id为id01的div元素
div_elements = soup.find_all('div', attrs={'id':'id01'})#与上一行代码功能相同
div_parent_element = div_elements[0].parent#获取父元素
for child in div_elements[0].children):#获取子元素
print(child)
div_nextSib = div_elements[0].next_sibling#获取元素的下一个兄弟元素
div_preSib = div_elements[0].previous_sibling#获取元素的上一个兄弟元素
上面代码中查找全部元素使用的是find_all函数,使用findAll函数也可达到相同的查找效果。
获取兄弟元素时,如没有兄弟元素则返回None,如果html文件中标签与标签间存在空行间隔,那么返回的是一个换行字符:‘\n’,而不是元素。
2.2获取元素属性
示例代码如下:
div_attrDict = div_element.attrs#以字典格式返回元素的全部属性,包括id、class等
div_class = div_attrDict['class']#获取class属性
div_class = div_element.get('class')#与上句效果相同,获取class属性
div_text01 = div_element.string#获取div标签间的文本,文本不包括子标签的文本
div_text02 = div_element.text#获取div标签间的文本,文本还包括子标签的文本
for str in div_elements[0].strings:#逐个标签获取div标签间的文本
print(str)
三、lxml查找元素并获取元素属性
3.1查找元素
示例代码如下:
from lxml import etree
with open(filePath, 'r', encoding = 'gbk', errors = 'replace') as f:
html_content = f.read()
lxml_page = etree.HTML(html_content)
div_elements = lxml_page.xpath('//div')#查找html文件中所有div元素,返回一个列表
a_elements = div_elements[0].xpath('.//a')#在div元素内部查找所有a元素,返回一个列表
div_elements = lxml_page.xpath('//div[@class="class01"]')#查找所有class为class01的div元素
div_elements = lxml_page.xpath('//div[@id="id01"]')#查找所有id为id01的div元素
div_elements = lxml_page.xpath('//div[contains(@id,"test")]')#查找所有id包含test的div元素
a_elements = lxml_page.xpath('//div[@id="id01"]/a[@id="id02"]')#查找所有id为id01的div元素下的id为id02的a元素
a_parent_element = a_elements[0].getparent()#获取父元素
a_new_element = etree.Element("a")#创建新的a元素
a_parent_element.insert(a_parent_element.index(a_elements[0]), a_new_element)#在父元素中旧a元素前插入新a元素
a_parent_element.remove(a_elements[0])#从父元素中移除旧a元素
相较于BeautifulSoup,lxml可以直接实现嵌套元素的查找,虽然xpath编写较为麻烦,但是查找元素更为灵活。
需要注意的是,当所查找元素具有多个class时,如果直接指定查找其中一个class值,那么lxml会查找不到,而Beautifulsoup可以查找到,使用xpath的contains才可以使lxml查找到。
3.2获取元素属性
示例代码如下:
a_href = a_element.get('href')#获取a元素href属性
div_class = div_element.get('class')#获取class属性
div_text01 = div_element.text#获取div标签间的文本,文本不包括子标签的文本
div_text02 = div_element.xpath("string(.)")#获取div标签间的文本,文本还包括子标签的文本
lxml获取元素文本属性的语法与Beautifulsoup有所区别,而获取其他属性的语法是一致的。
参考文档
beautifulsoup 根据class属性查找标签的方法
beautifulsoup怎么查找子元素?与抓取活动行页面数据
爬虫(三)—— BeautifulSoup模块获取元素
【爬虫】lxml的使用(xpath选择器、获取文本内容、获取属性、string(.))