目录
活动地址:CSDN21天学习挑战赛
**
学习日记 Day16
**
一、爬虫提取网页数据的流程
获取到html字符串,经过lxml库解析,变成HTML页面,再通过xpath的提取可以获取到需要的数据。
二、 lxml库介绍
lxml看是xml和html的解析器,主要功能是解析xml和html中的数据;lxml是一款高性能的python html、xml解析器,也可以利用xpath语法,来定位特定的元素即节点信息。
2.1 下载安装lxml库
使用命令 【pip install lxml】下载安装lxml库。
2.2 解析HTML网页
解析HTML网页用到了lxml库中的etree类。
示例1:解析HTML字符串
from lxml import etree
text = '''
<html><body>
<div class="key">
<div class="Website">CSDN</div>
<div class="Lang">python</div>
<div class="Content">lxml解析HTML</div>
</div>
</body></html>
'''
# 初始化,传入一个html形式的字符串
html = etree.HTML(text)
print(html)
print(type(html))
# 将字符串序列化为html字符串
result = etree.tostring(html).decode('utf-8')
print(result)
print(type(result))
输出结果:
<Element html at 0x1c9ba29e880>
<class 'lxml.etree._Element'>
<html><body>
<div class="key">
<div class="Websit">CSDN</div>
<div class="Lang">python</div>
<div class="Content">lxml解析HTML</div>
</div>
</body></html>
<class 'str'>
示例2:读取并解析HTML文件
from lxml import etree
# 初始化,传入一个html形式的字符串
html = etree.parse('test.html')
# 将字符串序列化为html字符串
result = etree.tostring(html).decode('utf-8')
print(result)
print(type(result))
html=etree.HTML(result)
print(html)
print(type)
显示结果:
<html><body>
<div class="key">
<div class="Website">CSDN</div>
<div class="Lang">python</div>
<div class="Content">lxml解析HTML</div>
</div>
</body></html>
<class 'str'>
<Element html at 0x19f271bf4c0>
<class 'type'>
总结:
如果有一个html的字符串,可以使用etree.HTML(html_str)函数初始化为html,然后使用etree.tostring(html).decode('utf-8')序列化为html字符串;
如果html内容被存储到文件中,那么可以使用etree.parse(filename)解析文件,然后使用etree.tostring(html).decode('utf-8')序列化为html字符串。
三、xpath介绍
xpath是在xml文档中查找信息的语言,可用来在xml文档中对元素和属性进行遍历。
1. 选取节点
常用的路径表达式有:
表达式 | 说明 |
nodename | 选取此节点的所有子节点 |
/ | 从根节点选取 |
// | 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置 |
. | 选取当前节点 |
.. | 选取当前节点的父节点 |
@ | 选取属性 |
示例:
表达式 | 说明 |
bookstore | 选取bookstore元素的所有子节点 |
/bookstore | 选取根元素bookstore。注释:假如路径起始于正斜杠/,此路径始终代表到某元素的绝对路径! |
bookstore/book | 选取属于bookstore的子元素的所有book元素 |
//book | 选取所有book子元素,不管它们在文档中的位置 |
bookstore//book | 选择属于bookstore元素的后代的所有book元素,不管它们位于bookstore之下的什么位置 |
//@lang | 选取名为lang的所有属性 |
2. 谓语
谓语用来查找某个特定的节点或者包含某个指定的值的节点,被嵌在方括号中。
路径表达式 | 说明 |
/bookstore/bok[1] | 选取属于bookstore子元素的第一个book元素 |
/bookstore/book[last()] | 选取属于bookstore子元素的最后一个book元素 |
/bookstore/book[last()-1] | 选取属于bookstore子元素的倒数第二个book元素 |
/bookstore/book[position()<3] | 选取属于bookstore子元素的最前面的两个book元素 |
//title[@lang] | 选取所有拥有名为lang的属性的title元素 |
//title[@lang='eng'] | 选取所有title元素,且这些元素拥有值为eng的lang属性 |
/bookstore/book[price>35.00] | 选取bookstore元素的所有book元素,且其中的price元素的值必须大于35.00 |
/bookstore/book[price>35.00]/title | 选取bookstore元素中的book元素的所有title元素,且其中的price元素的值须大于35.00 |
3. 选取未知节点
xpath通配符可以用来选取未知的xml元素。
通配符 | 说明 |
* | 匹配任何元素节点 |
@* | 匹配任何属性节点 |
node() | 匹配任何类型的节点 |
示例:
路径表达式 | 说明 |
/bookstore/* | 读取bookstore元素的所有子元素 |
//* | 选取文档中的所有元素 |
html/node()/meta/@* | 选取html下面任意节点下的meta节点的所有属性 |
//title[@*] | 选取所有带有属性的title元素 |
4. 选取若干路径
通过在路径表达式中使用|运算符,可以选取若干个路径。
示例:
路径表达式 | 结果 |
//book/title | //book/price | 选取book元素的所有title和price元素 |
//title | //price | 选取文档中的所有title和price元素 |
/bookstore/book/title | //price | 选取属于bookstore元素的book元素的所有title元素,以及文档中所有的price元素 |
xpath使用示例:
新建test.html文件:
<!-- hello.html -->
<div>
<ul>
<li class="item-0"><a href="link1.html">first item</a></li>
<li class="item-1"><a href="link2.html">second item</a></li>
<li class="item-inactive"><a href="link3.html"><span class="bold">third item</span></a></li>
<li class="item-1"><a href="link4.html">fourth item</a></li>
<li class="item-0"><a href="link5.html">fifth item</a></li>
</ul>
</div>
⚪ 获取所有的<li>标签
# 获取所有的<li>标签
from lxml import etree
html = etree.parse('test.html')
print(type(html))
result = html.xpath('//li')
print(result)
print(len(result))
print(type(result))
print(type(result[0]))
显示结果:
<class 'lxml.etree._ElementTree'>
[<Element li at 0x21eca60ad80>, <Element li at 0x21eca60ae40>, <Element li at 0x21eca60ae80>, <Element li at 0x21eca60aec0>, <Element li at 0x21eca60af00>]
5
<class 'list'>
<class 'lxml.etree._Element'>
⚪ 获取<li>标签的所有class属性
# 获取<li>标签的所有class属性
from lxml import etree
html = etree.parse('test.html')
result = html.xpath('//li/@class')
print(result)
print(len(result))
print(type(result))
print(type(result[0]))
显示结果:
['item-0', 'item-1', 'item-inactive', 'item-1', 'item-0']
5
<class 'list'>
<class 'lxml.etree._ElementUnicodeResult'>
⚪ 获取<li>标签下href为link1.html的<a>标签
# 获取<li>标签的所有class属性
from lxml import etree
html = etree.parse('test.html')
result = html.xpath('//li/a[@href="link1.html"]')
print(result)
print(len(result))
print(type(result))
print(type(result[0]))
显示结果
[<Element a at 0x141b529f380>]
1
<class 'list'>
<class 'lxml.etree._Element'>
⚪ 获取<li>标签下的所有<span>标签
# 获取<li>标签的所有class属性
from lxml import etree
html = etree.parse('test.html')
result = html.xpath('//li//span')
print(result)
显示结果:
[<Element span at 0x1da409cf480>]
1
⚪ 获取<li>标签下的<a>标签里的所有class
# 获取<li>标签的所有class属性
from lxml import etree
html = etree.parse('test.html')
result = html.xpath('//li/a//@class')
print(result)
print(len(result))
显示结果:
['bold']
1
⚪ 获取最后一个<li>的<a>的href
# 获取<li>标签的所有class属性
from lxml import etree
html = etree.parse('test.html')
result = html.xpath('//li[last()]/a/@href')
print(result)
print(len(result))
显示结果:
['link5.html']
1
⚪ 获取倒数第二个元素的内容
# 获取<li>标签的所有class属性
from lxml import etree
html = etree.parse('test.html')
result = html.xpath('//li[last()-1]/a')
print(result)
print(result[0].text)
print(len(result))
显示结果:
[<Element a at 0x19937dbf300>]
fourth item
1
⚪ 获取class值为bold的标签名
# 获取<li>标签的所有class属性
from lxml import etree
html = etree.parse('test.html')
result = html.xpath('//*[@class="bold"]')
print(result)
print(result[0].tag)
print(len(result))
显示结果:
[<Element span at 0x1ecc377f2c0>]
span
1
全文参考: