HTML解析—正则、BeautifulSoup库与XPath方法
我们可以使用requests模拟请求,拿到网页的源代码html格式的字符串,但需要进行解析,找到指定内容,可以使用python中有自带的find方法,但功能有限,这里介绍三种解析html的方法。
html = '<html><body><h1>标题</h1></body></html>'
start_index = html.find('<h1>')
end_index = html.find('</h1>')
print(html[start_index:end_index])
解析方法一:正则regex
正则是专门对字符串处理的语法,利用事先定义好的一些特定字符以及它们的组合组成一个“规则”,检查一个字符串是否与这种规则匹配来实现对字符的过滤或匹配。字符处理能力强大,但语法规则多,难写。具体规则可以参考:正则手册,常用正则,这是另一篇关于正则表达式的文章 简答的正则实例:
import re
text1 = 'javapythongophpjssldjfsjdk'
pattern1 = re.compile(r'python')
matcher1 = re.search(pattern1,text1)
print(matcher1)
print(matcher1[0])
运行结果:
text6 = """aaahelloaabbb
</h1>
world
aaa
</html>
"""
pattern6 = re.compile(r'hello(.*?)</h1>',re.S)
print(pattern6.findall(text6))
运行结果:
解析方法二:BeautifulSoup库
BeautifulSoup是一个可以从HTML或XML文件中提取数据的python库,目前最新版本为BeautifulSoup4,简称bs4。bs4是一个包,其中包含了BeautifulSoup、EntitySubstitution、builder等类。在这些类中,BeautifulSoup使用的最多,因此很多人认为BeautifulSoup和bs4是一样的,其实则不然。
BeautifulSoup将html文件转换成一个树形结构。一些简单的用法如下代码:
from bs4 import BeautifulSoup #坑:代码包和名字包含的元素名字不一致
html = '''
<html>
<body>
<a id="aaa" href="https://www.baidu.com">百度一下</a>
<a></a>
<h1>hello</h1>
</body>
</html>
'''
#先把字符串解析成html结构,内置库 三方库lxml
bs = BeautifulSoup(html,'html.parser')
print(bs.a)
print(bs.find_all('a'))
print(bs.a['href'])
运行结果:
解析方法三:XPath
xlml库中包含的主要模块有etree,html,cssselect等,在程序设计时主要有三个步骤:首先利用etree提供的方法读取html内容,获得Element类型的节点或者ElementTree类型的对象。接下来利用解析得到的Elenment或ElementTree的xpath、cssselect、find、findall等方法来定位要提取信息的节点。最后从节点提取出信息。
这里介绍XPath方法,完整的介绍方法可以参考官方网站
基本路径符号:
表达式 | 描述 |
nodename | 表示某个具体的节点 |
/ | 根节点 |
// | 所有节点而不考虑他们的位置 |
. | 当前节点 |
… | 当前节点的父节点 |
谓语:
last()、text()、contains()、not()、starts-with()等
特殊符号:
- @:表示选取属性
- *:表示匹配任何元素节点
下面是一个简单的实例:
from lxml import etree
html = """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>lxml中xpath的用法</title>
</head>
<body>
<ul>
<li><a href="https://www.baidu.com" class="first_a">百度一下</a></li>
<li><a href="https://mail.qq.com" id="second_a">QQ邮箱</a></li>
<li><a href="https://www.taobao.com">淘宝网</a></li>
<li>
<a href="https://pypi.python.org" class="first_a">Python官网</a>
<a href="https://pypi.python.org" class="second_a">Python</a>
</li>
</ul>
<p class="one">first_p_tag</p>
<p id="second">second_p_tag</p>
<div class="one">
first_div_tag
<p class="first second third">11111111</p>
<a href="#">22222222</a>
</div>
</body>
</html>
"""
dom = etree.HTML(html)
print(dom)
print(dom.xpath('//a'))
print(dom.xpath('//ul/li/a'))
print(dom.xpath('//a/text()'))
#属性过滤
print(dom.xpath('//a[@id = "second_a"]/text()')[0])
运行结果:
三种方法的比较
\ | 正则 | BeautifulSoup | XPath |
难度 | 难 | 简单 | 中 |
代码量 | 少 | 多 | 少 |