使用Python进行刮擦和解析 - 带有长Xpath的lxml

时间:2015-10-16 19:35:14

标签: python lxml

我正在加载和滚动动态加载页面。一个例子是Facebook“墙”,只有在你滚动到底部附近的某个地方时才会加载下一个项目。

我滚动直到页面长度很长,然后我复制源代码,将其保存为文本文件并继续解析。

我想提取网页的某些部分。我一直在python中使用lxml module,但成功有限。在那里的网站上,他们只展示了很短的Xpaths的例子。

下面是一个函数示例和一个获取页面上包含的用户名的路径。

usersID = elTree.xpath('//a[@class="account-group js-account-group js-action-profile js-user-profile-link js-nav"]')

这很有效,但是我得到了一些errors(我的另一篇文章),例如:

TypeError: 'NoneType' object has no attribute 'getitem'

我一直在关注Firebug提供的Xpath。这些当然更长,更具体。以下是页面上reoccuring元素的示例:

/html/body/div[2]/div[2]/div/div[2]/div[2]/div/div[2]/div/div/div/div/div[2]/ol[1]/li[26]/ol/li/div/div[2]/p

结束li[26]的部分显示它是同一元素列表中的第26个项目,它们位于HTML树的同一级别。

我想知道如何在lxml库中使用这样的firebug-Xpaths,或者有人知道一般使用Xpath的更好方法吗?

使用示例HTML代码和工具like this进行测试,Firebug中的Xpath根本不起作用。这条道路在人们的经历中是否荒谬?

源代码是非常具体的吗?是否有其他工具如Firebug可以生成更可靠的输出以用于lxml?

2 个答案:

答案 0 :(得分:1)

FireBug实际上会生成非常差的xpath。它们冗长而脆弱,因为它们在层次结构之外非常具体。 今天的页面非常有活力。

在动态页面上使用xpath的最佳方法是将公共元素定位为钩子,并从那些作为路径根目录执行xpath操作。 我在这里所说的共同元素是稳定的结构元素,很可能或保证存在。根据包含层次结构选择最接近目标的那个。较短的路径更快更清晰。

从那里你需要创建路径,在目标元素上找到一些特定的唯一属性或属性值。 有时候这是不可能的,所以另一个策略是定位最接近的唯一可识别容器元素,然后获得与此类似的所有元素,并迭代它们寻找你的目标。

高度动态的页面需要复杂而动态的方法。

Facebook变化很大,需要经常进行脚本维护。

答案 1 :(得分:0)

我找到了两件对我来说非常好的事情。

第一件事:

lxml包允许将一些函数与Xpath结合使用。我使用了starts-with函数,如下所示:

tweetID = elTree.xpath("//div[starts-with(@class, 'the-non-varying-part-of-a-very-long-class-name')]")

使用Firebug / Firepath等工具探索HTML代码(树)时,所有内容都显示得非常整齐 - 例如:

*

Xpath and class name in Firebug

*

当我使用突出显示的路径(即tweet original-tweet js-original-tweet js-stream-tweet js-actionable-tweet js-profile-popup-actionable has-cards has-native-media with-media-forward media-forward cards-forward)在上面的代码中搜索我的elTree时,找不到任何内容。

看一下我试图解析的实际HTML文件,我看到它真的分布在很多行 - 就像这样:

Actual HTML code

这解释了为什么lxml包没有根据我的搜索找到它。

第二件事:

我知道通常不建议将其作为一种解决方法,但Python方法更容易要求宽恕而不是许可"在我的情况下应用 - 我接下来要做的就是在TypeError上使用python try / except,我一直看到代码的任意行

这可能是我的代码所特有的,但在检查了很多情况下的输出后,似乎它对我来说效果很好。