天域至尊 发表于 2019-8-8 10:07

[笔记]xpath表达式构建失败修复技巧,同数据多规则技巧

本帖最后由 天域至尊 于 2019-8-8 16:07 编辑

特别声明,此文偏笔记类型,不喜勿喷,谢谢哦。


我们在使用xpath表达式截取网页数据时,往往会出现浏览器复制的xpath表达式迁移到程序中不能用的问题,个人认为(未经求证,巴啦啦小魔仙,杠精避退)可能是因为网页不规范,不同浏览器修补后代码不同的原因。


处理方式有如下建议(仅对使用lxml模块):
1.截取后的对象,可以使用tostring函数完全转化为字符串,编码后打印可以看到直观的截取后代码。
2.注意事项有,表达式不应是text()等结尾,即最后表达式截取出的应该是标签页对象,而不是文本或属性,不然不易打印出来完整html代码。例如可以是/html/body/div/div/div/a这样结尾的,不应是/html/body/div/div/div/a/text(),都尼玛文本了,还回转个球。
3.往往是出现截取不到,即截取列表为空的状态,可以使用回溯的方式
例:/html/body/div/div/div/a截不到,再截/html/body/div/div/div,还截不到,再截/html/body/div/div
以此类推,等截到了,就转化出来看看截成啥样,再手工构建后面的表达式。
4.转化方法
首先,返回的是列表,没法转化,应该选择其中的一个对象,例如aaa=bbb.xpath(表达式),aaa变量是个列表变量,注意用aaa转化。
样例代码如下:
from lxml import etree
#打开文件,转为etree
report=etree.parse(文件路径,etree.HTMLParser())
#根据xpath表达式截取数据
result=report.xpath(xpath表达式)
#将数据带标签转化为字符串
ii=etree.tostring(result)
#编码输出
print(ii.decode('utf8'))


还有一种不常见的情况,即某网站页面出现多种微小差距的版本。
常见原因即网站改版,微调导致。但是这样会导致我们无法将数据准确提取出来,即上个网页还行,下个网页规则细变,头疼的紧,总不能写好几个版本吧。
解决方案:
建议,将xpath表达式用数组存储起来,而不用变量存储。例如原来是
xpathName='/html/body/div/div/div/ul/li/a'
现在可以这样写
xpathName=['/html/body/div/div/div/ul/li/a']

为什么这样写呢?在取的时候使用for循环取,提取完数据进行判断,是否取到了,取到了在循环里break掉即可,否则继续循环,而增加规则只需在数组里加就行了。
例如:
A网站有一部分名称可以用表达式“/html/body/div/div/div/ul/li/a”提取出来,另一部分名称需要用'/html/body/div/div/div/ul/li/a'提取出来,而且不知道是否还有其他变化。
那么程序可以这样写
from lxml import etree
#存储多个规则
xpathCode=['/html/body/div/div/div/ul/li/a','/html/body/div/div/div/ul/li/a']
#将html文本转化为etree对象
report=etree.parse(html文本,etree.HTMLParser())
#遍历规则进行尝试
for i in xpathCode:
#使用一个规则尝试截取数据
result=report.xpath(i)
#截取到数据则跳出循环,否则继续遍历规则
if len(result)>0:
    break

这样的话,每发现网站有一个微调的版本,增加表达式到对应的数组即可。

君月栩 发表于 2019-8-8 10:25

感谢楼主分享!
页: [1]
查看完整版本: [笔记]xpath表达式构建失败修复技巧,同数据多规则技巧