墙纸 html 网站模板,域名弄好了网站怎么建设,青岛优化网站关键词,网站友情链接购买之前我们写了一个简单的爬虫#xff0c;在提取页面信息时我们使用正则表达式来匹配内容#xff0c;但是正则表达式的书写比较繁琐#xff0c;而且一旦错误就可能导致匹配失败。对于网页的节点来说#xff0c;它可以定义id#xff0c;class或其他的属性#xff0c;而且节点… 之前我们写了一个简单的爬虫在提取页面信息时我们使用正则表达式来匹配内容但是正则表达式的书写比较繁琐而且一旦错误就可能导致匹配失败。对于网页的节点来说它可以定义idclass或其他的属性而且节点之间还有层次关系在网页中可以通过xpath后css选择器来定位一个或多个节点。那么我们在解析页面时利用CSS和XPath选择器来定位节点再调用相关方法来获取其正文内容或属性。本文介绍XPath。1.XPath概述 XPath的选择功能十分强大提供了100多个内建函数用于字符串、数值、时间的匹配和节点、序列的处理。2.XPath常用规则nodename 选取此节点的所有子节点
/ 从当前节点选取直接子节点
// 从当前节点选取子孙节点
. 选取当前节点
.. 选取当前节点的父节点选取属性 这里就是XPath的常用匹配规则示例如下 //title[langeng] 这个就表示选择所有名称为title同时属性lang的值为eng的节点。3.准备工作 安装好lxml库。4.实例引入我们来通过实例来感受一下使用XPath来对网页进行解析的过程。from lxml import etreetext
div
ul
li classitem-0a-hreflink1.htmlfirst item/a/li
li classitem-1a-hreflink2.htmlsecond item/a/li
li classitem-inactivea-hreflink3.htmlthird item/a/li
li classitem-1a-hreflink4.htmlfourth item/a/li
li classitem-0a-hreflink5.htmlfifth item/a
/ul
/divhtml etree.HTML(text)
result etree.tostring(html)
print(result.decode(utf-8)) 这里我们先导入lxml库的etree模块然后声明一段HTML文本在调用HTML类进行初始化这样就成功构造了一个XPath解析对象。我们可以注意到HTML文本中最后一个li节点是没有闭合的但是etree模块可以自动修正HTML 文本。 我们调用tostring()方法即可输出修正后的HTML代码但是结果是bytes类型。这里利用decode()方法将其转换为str类型。 我们也可以通过直接读取文件来进行解析。from lxml import etreehtml etree.parse(./test.html, etree.HTMLParser())
result etree.tostring(html)
print(result.decode(utf-8)) 其中test.html的内容就是上面的HTML代码。5.所有节点我们一般会用//开头的XPath规则来选取所有符合要求的节点。result html.xpath(//*)
print(result) 这里使用*来匹配所有节点也就是整个HTML文本中的所有节点都会被获取返回形式是一个列表每个元素都是Element类型后面跟着节点的名称。 当然此处匹配也可以指定节点名称。如果想获取所有li节点如下result html.xpath(//li)
print(result)
print(result[0]) 如果我们要取出其中一个对象可以直接用中括号加索引如[0]。6.子节点我们通过/或//即可查找元素的子节点或子孙节点。假设我们现在想选择li节点的所有直接a节点可以这样实现result html.xpath(//li/a) 如果想获得所有子孙节点则可使用//。例如要获取ul节点下的所有子孙a节点可以这样实现result html.xpath(//ul//a) /用于获取直接子节点//用于获取子孙节点。7.父节点我们在上面讲了如何查找子节点或子孙节点那么加入我们知道了子节点怎么来查找父节点呢可以用..来实现。 比如我们选中属性为link4.html的a节点然后获取其父节点然后再获取其class属性。result html.xpath(//a[hreflink.html]/../class) 同时也可以使用parent::来获取父节点。result html.xpath(//a[hreflink.html]/parent::*/class)8.属性匹配 在选取时我们还可以使用符号进行属性过滤。比如这里如果要选取class为item-0的li节点可以这样实现result html.xpath(//li[classitem-0]) 这里我们通过加入[classitem-0]限制了节点的class属性为item-0,而HTML 文本中符合的li节点有两个所以结果应该返回两个匹配到的元素。9.文本获取 我们使用XPath中的text()方法获取节点中的文本接下来尝试获取前面li节点中的文本。result html.xpath(//li[classitem-0]/text()) 我们运行之后没有获取任何文本。这是为什么呢因为XPath中text()前面是/代表选取直接子节点很明显li节点的直接子节点都是a节点文本都是在a节点内部的所以只匹配到被修正的li节点内部的换行符。因为自动修正的li节点的尾标签换行了。即选中的是这两个节点li classitem-0a-hreflink1.htmlfirst item/a/li
li classitem-0a-hreflink5.htmlfifth item/a
/li 因此如果想获取li节点内部的文本就有两种方式:一种是先选取a节点再获取文本另一种是使用//。result html.xpath(//li[classitem-0]/a/text())运行结果为[first item, fifth item] 这里我们是逐层选取先选取了li节点又利用/选取了其直接子节点a。result html.xpath(//li[classitem-0]//text())运行结果为[first item, fifth item, n ] 这里是选取所有子孙节点的文本其中两个是li的子节点a节点内部的文本另外一个就是最后一个li节点内部的文本即换行符。10.属性获取我们使用text()方法获取文本内容我们也可以用href来获取节点的href属性。result html.xpath(//li/a/href)11.属性多值匹配有时候某些节点的某个属性有多个值例如from lxml import etreetext
li classli li-firsta hreflink.htmlfirst item/a/lihtml etree.HTML(text)
result html.xpath(//li[classli]/a/text())
print(result) 这里返回的结果是[],因为li的class属性有两个值li和li-first,此时还想用之前的属性匹配获取就无法匹配了。 这时就需要用contains()函数了代码如下result html.xpath(//li[contains(class, li)]/a/text()) 这样就会得到结果[first item]。12.多属性匹配 另外我们还会碰到另一种情况那就是依据多个属性来确定一个节点这时就需要同时匹配多个属性此时我们可以使用运算符and来连接。from lxml import etreetext
li classli li-first nameitema hreflink.htmlfirst item/a/lihtml etree.HTML(text)
result html.xpath(//li[contains(class, li) and nameitem]/a/text())
print(result) 这里的li节点又增加了一个属性name。要确定这个节点需要用时根据class和name来选择中间用and相连相连之后置于中括号内进行条件筛选。除了and之外还有其他的运算符可以使用。13.顺序选择 我们在选择的时候某些属性可能已经匹配了多个节点但是我们只想要其中的某个节点如第二个节点或者最后一个节点。from lxml import etreetext
div
ul
li classitem-0a-hreflink1.htmlfirst item/a/li
li classitem-1a-hreflink2.htmlsecond item/a/li
li classitem-inactivea-hreflink3.htmlthird item/a/li
li classitem-1a-hreflink4.htmlfourth item/a/li
li classitem-0a-hreflink5.htmlfifth item/a
/ul
/divhtml etree.HTML(text)
result html.xpath(//li[1]/a/text())
print(result)
result html.xpath(//li[last()]/a/text())
print(result)
result html.xpath(//li[position()3]/a/text())
print(result)
result html.xpath(//li[last()-2]/a/text())
print(result) 第一次选择时我们选取了第一个li节点这里在中括号中传入1就可。 第二次选择时我们选取最后一个li节点中括号中传入last即可。 第三次选择时我们选取了位置小于3的li节点运用了position()函数。 第四次选择时我们选择了都输第三个li节点中括号中传入last()-2即可。 在Xpath中提供了100多个函数包括存取、数值、字符串、逻辑、节点、序列等的处理功能。14.节点轴选择 XPath提供了许多节点轴选择方法包括获取子元素、兄弟元素、父元素、祖先元素等示例如下from lxml import etreetext
div
ul
li classitem-0a-hreflink1.htmlfirst item/a/li
li classitem-1a-hreflink2.htmlsecond item/a/li
li classitem-inactivea-hreflink3.htmlthird item/a/li
li classitem-1a-hreflink4.htmlfourth item/a/li
li classitem-0a-hreflink5.htmlfifth item/a
/ul
/divhtml etree.HTML(text)
result html.xpath(//li[1]/ancestor::*)
print(result)
result html.xpath(//li[1]/ancestor::div)
print(result)
result html.xpath(//li[1]/attribute::*)
print(result)
result html.xpath(//li[1]/child::a[hreflink1.html])
print(result)
result html.xpath(//li[1]/descendant::span)
print(result)
result html.xpath(//li[1]/following::*[2])
print(result)
result html.xpath(//li[1]/following-sibling::*)
print(result) 第一次选择时我们调用了ancestor轴可以获取所有的祖先节点。之后需要跟两个冒号然后是节点的选择器这里我们使用*表示匹配所有节点。 第二次选择时我们又加了限定条件div这时得到的结果就只有div这个祖先节点了。 第三次选择时我们调用了attribute轴可以获取所有属性值其建瓯跟的选择器还是*代表获取节点的所有属性。 第四次选择时我们调用了child轴可以获取所有直接子节点。这里我们又加入了限定条件选取href属性为link1.html的a节点。 第五次选择时我们调用了descendant轴可以获取所有的子孙节点。这里我们又加入了限制条件获取span节点。所以返回的结果只包含span节点而不包括a节点。 第六次选择时我们调用了following轴可以获取当前节点之后的所有节点。这里我们使用*匹配但又加入了索引选择所以只获取了第二个后续节点。 第七次选择时我们调用了following-sibling轴可以获取当前节点之后的所有同级节点。这里我们使用*匹配获取所有后续同级节点。参考书目《Python 3 网络爬虫开发实战》