使用 XPath
XPath 简介:
(1) 前面我们爬取一个网页,都是使用正则表达式来提取想要的信息,但是这种方式比较复杂,一旦有一个地方写错,就匹配不出来了,因此我们可以使用 XPath 来进行提取
(2) XPath 即 XML Path Language,XML路径语言,起初是用来在 XML 文档中提取信息的,但同样适用于在 HTML 文档中提取信息,通过 XPath 来定位一个或多个HTML节点
(3) 什么是HTML节点:https://www.cnblogs.com/pzk7788/p/10530042.html ;在 Python 中,使用 lxml 库进行信息的提取,可以使用 pip3 install lxml 进行安装
XPath 规则:
// 用于提取指定的节点,如 //p 表示提取所有 <p> 节点
/ 用于提取当前节点的子节点,如 //ul/li 表示提取 <ul> 下的 <li> 节点
.. 用于提取当前节点的父节点,如 //body/../html 表示提取 <body> 节点的上一层 <html> 节点
@ 用于提取属性,如 //a[@href] 表示提取 <a> 节点的 href 属性值
XPath 用法:
假设 index.html 内容如下,使用 XPath 提取我们想要的内容:
<div> <ul> <li class="item-1"><a href="link1.html">first item</a> </li> <li class="item-2"><a href="link2.html">second item</a> </li> <li class="item-3"><a href="link3.html">third item</a> </li> <li class="item-4"><a href="link4.html">fourth item</a> </li> <li class="item-5 id-6"><a href="link5.html">fifth item</a> </li>
</ul> </div>
from lxml import etree html = etree.parse('./index.html', etree.HTMLParser()) //etree.parse()用于加载本地文件,etree.HTMLParser() 是一个 HTML 解析器,用于解析 HTML 文件 result = html.xpath('//li') //提取所有<li>节点,结果为:[<Element li at 0x488030>, <Element li at 0x484fd0>, ...... result = html.xpath('//li/a') //提取所有 <li> 节点下的 <a> 节点,结果为:[<Element a at 0x3c28030>, <Element a at 0x3c24fd0>, ...... result = html.xpath('//li/a/text()') //提取所有 <li> 节点下的 <a> 节点的文本内容,结果为:['first item', 'second item', 'third item', 'fourth item', 'fifth item'] result = html.xpath('//li/a/@href') //提取所有 <li> 节点下的 <a> 节点的 href 属性值,结果为:['link1.html', 'link2.html', 'link3.html', 'link4.html', 'link5.html'] result = html.xpath('//li[1]/a/text()') //提取第一个出现的 <li> 节点,结果为:['first item'] result = html.xpath('//li[last()]/a/text()') //提取最后一个出现的 <li> 节点,结果为:['fifth item'] result = html.xpath('//li[last()-2]/a/text()') //提取倒数第三个出现的 <li> 节点,结果为:['third item'] result = html.xpath('//li[position()<3]/a/text()') //提取位置小于3的 <li> 节点,结果为:['first item', 'second item'] result = html.xpath('//a[@href="link4.html"]') //提取属性为 href="link4.html" 的 <a> 节点,结果为:[<Element a at 0x33b4fd0>] result = html.xpath('//a[@href="link4.html"]/../@class') //提取属性为 href="link4.html" 的 <a> 节点的父节点,然后获取父节点的 class 属性,结果为:['item-4'] result = html.xpath('//li[1]/ancestor::*') //ancestor用于提取祖先节点,也就是提取第一个<li>节点上面的所有节点,结果为:[<Element html at 0x3738058>, <Element body at 0x3734fd0>, ...... result = html.xpath('//li[1]/ancestor::div') //ancestor用于提取祖先节点,这里表示提取第一个<li>节点上面的<div>节点,结果为:[<Element div at 0x3554fd0>] result = html.xpath('//li[1]/attribute::*') //attribute用于提取节点的属性值,这里表示提取第一个<li>节点的所有属性值,结果为:['item-1'] result = html.xpath('//li[1]/child::*') //child用于提取指定节点下的所有子节点,这里表示提取第一个<li>节点下的所有子节点,结果为:[<Element a at 0xb58030>] result = html.xpath('//li[contains(@class, "item") and contains(@class, "id")]') //在上面的最后一个 <li> 节点中,class属性有两个值,我们需要使用 contains 来进行模糊匹配,表示提取属性值包含 item 和 id 的节点