摄影:产品经理 

吃完海底捞散步回家

GNE[1]在对新闻进行预处理的时候,会提前移除一些显然不可能包含正文的 Dom 节点,从而增加提取的准确性。

一般来说,网页的版权信息,页尾信息,会放在一个叫做​​<div class="footer"></div>​​​的标签里面。所以,要用 XPath 找到这种版权信息,本来应该非常简单:​​//div[@class="footer"]​​​。但实际场景中,可能有两种情况:​​<div class="xxxfooteryyy"></div>​​​和​​<div class="Footer">​​。

​footer​​​前后都有字符的时候,我们可以使用 XPath 的关键词​​contains​​​:​​//div[contains(@class, "footer")]​​,运行效果如下图所示:

一日一技:XPath 匹配如何忽略大小写?_python

但如果我们想忽略大小写的时候怎么办呢?实际上,在 XPath 2.0的标准里面,有一个关键字叫做​​lower-case​​​就可以实现这个需求,XPath 写为: ​​//div[lower-case(@class)="footer"]/text()​​。我们可以在一些在线 XPath 检查的工具里面看到提取效果,如下图所示:

一日一技:XPath 匹配如何忽略大小写?_字符串_02

但坏就坏在,Python 的第三方库​​lxml​​​使用的是 XPath 1.0标准,因此没有​​lower-case​​​这个关键字。所以要实现这个需求,我们需要使用另一个关键字​​translate​​​:​​//div[translate(@class, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz")="footer"]/text()​​。

运行效果如下图所示:

一日一技:XPath 匹配如何忽略大小写?_字符串_03

这里的​​translate​​​效果就跟 Python 字符串的​​translate​​​差不多。我以前写过一篇文章:​​一日一技:在字符串中批量替换单个字符​​​介绍在 Python 里面怎么使用​​translate​​方法。

XPath 的​​translate​​​的语法为:​​translate(目标属性, 需要替换的字符, 替换成字符)​​。这样就可以把节点的目标属性值成小写再来对比。

那么,如果HTML 标签的属性值是​​xxxFooteryyy​​​怎么办呢?其实我们也可以像函数嵌套一样再套一层​​contains​​​:​​//div[contains(translate(@class, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz"), "footer")]​

运行效果如下图所示:

一日一技:XPath 匹配如何忽略大小写?_字符串_04


参考文献

[1]GNE: ​https://github.com/GeneralNewsExtractor/GeneralNewsExtractor​




一日一技:XPath 匹配如何忽略大小写?_属性值_05