Raschietto:用于Web抓取的简单库
我经常遇到需要从没有API或RSS feed的网站获取数据的情况。 存在许多不同的Web抓取库,但我不满意,我想要具备以下功能:
- 使用CSS选择器 。 我曾经是一名全栈开发人员,所以我比XPath更喜欢使用CSS选择器。
- 几乎可以立即创建一个有效的刮板 。 大多数时候,我不需要非常复杂或高级的东西,我只需要非常快速地制作一个简单的刮板即可。
这促使我创建了一个简单的刮板库,称为Raschietto (意大利语为刮板)。 以下是其主要功能:
- CSS选择器
- 单行获取和解析HTML页面
- 简单且可扩展的方法来匹配页面中的元素
- 为常见任务(例如提取链接和图像)预先构建的匹配器
该库目前处于beta版本(但足够稳定),仅支持Python3(添加Python2支持非常简单)。
我之所以共享这个库,是因为我认为它可以加快构建简单的scraper的速度,并且因为其较小的代码库(少于170行代码)对于学习非常有用。
您可以使用以下方法安装它:
pip install raschietto
报废arXiv
作为学习如何使用raschietto并展示其功能的示例,我将指导您仔细阅读 arXiv网页。 请注意,arXiv的RSS供稿非常好,因此无需抓取即可轻松访问其数据,但出于教育目的,我们仍然会对其进行抓取。
我们将重点关注包含最新机器学习论文的页面 。
首先,我们从获取最新论文的标题开始。 由于raschietto使用CSS选择器,因此此任务非常容易。 使用Chrome,我们可以使用开发工具复制CSS选择器,该选择器将选择特定元素。 只需将鼠标放在所需的元素上(在DOM视图中)>右键单击>复制>复制选择器
我们得到以下选择器:
#dlpage> dl> dd:nth-child(2)> div> div.list-title.mathjax
该选择器特定于该标题元素,因此不会选择其他标题元素。 通过查看页面的HTML代码,我们可以对其进行修改以获得一个更简单的选择器,该选择器将选择所有所需的元素:
.meta .list-title
如果不确定选择器的正确性,可以使用控制台(在开发工具中)对其进行测试
使用raschietto获取论文标题的代码简单明了,易于说明
我们正在使用两个raschietto组件:
- Raschietto是包含该库的所有主要功能的类。 在此示例中,我们使用它来获取和解析HTML页面
- Matcher是封装匹配逻辑的类。 默认情况下,它返回匹配元素的内部文本,稍后我们将看到如何更改此行为。
现在,我们得到一个以“ Title:”开头的标题列表,以删除前7个字符,我们可以使用Matcher类的映射功能
我们所做的唯一更改是将映射参数添加到匹配器中。 该函数需要2个参数:匹配的元素和包含页面。 我们使用Raschietto函数将匹配的元素映射到其内部文本,然后使用python切片来删除前7个字符,从而获得标题的清理列表。
现在,我们希望做一些更高级的事情:我们希望使每篇论文的标题和作者名单都匹配。 为此,我们需要:
- 匹配所有“ .meta”元素
- 对于每个匹配的元素,获取包含的论文标题
- 对于每个匹配的元素,获取包含的作者列表
Matcher类的映射功能使此任务非常简单,我们只需要匹配所有“ .meta”元素并将它们映射到包含标题和作者列表的字典即可 。
仅用几行代码,我们就创建了一个不错的刮板!
当然,这对我们来说还不够:我们还希望获得本文的链接。 由于arXiv页面的结构,这似乎有问题。
标题和链接包含在不同的元素中,使用它们的第一个公共父元素是没有用的,因为它包含所有papers元素。 要获得链接,我们必须:
- 匹配“ .meta”元素
- 选择其父项(“ dd”元素)
- 选择“ dd”元素之前的元素(这样我们得到“ dt”元素)
- 匹配链接到“ https://arxiv.org/abs/<paper id>”的“ a”元素
- 从匹配的链接中提取href
我们已经完成了步骤1。要实现步骤2和3,我们可以利用以下事实:传递给映射函数的“ el”参数是lxml HtmlElement的实例,因此我们可以使用lxml方法通过选择来获取“ dt”元素el的父级的前一个元素。
dt = el.getparent().getprevious()
要完成第4步和第5步,我们可以使用预先构建的匹配器来匹配链接,从每个链接中提取href并将每个URL设置为绝对(例如,将“ /abs/1802.08246”映射到绝对URL“ https:// arxiv。 org / abs / 1802.08246”)。 抓取时匹配链接非常普遍,因此我已将此匹配器包含在raschietto库中。 这种匹配也有一个参数startswith是,specidied的时候,会告诉匹配只保留与给定字符串开始的结果。 使用此匹配器,我们的任务代码很短:
link_matcher = Matcher.link(".list-identifier > a", startswith="https://arxiv.org/abs/")
通过此更改,我们获得了arXiv刮板的最终版本
请注意,我们已将 page参数传递给link_matcher,以使其知道元素的源网址(否则无法将网址设为绝对网址)
结论
仅用15行优雅的代码(空行不计算在内),我们开发了一种有效的抓取工具,能够从网页中提取信息。 我们很容易就能对匹配的元素进行分组,克服了“没有有用的共同父代”的问题,并且无需编写大量代码即可从每个元素提取所需的信息。
我真的希望您喜欢这个小型图书馆。 如果您有任何疑问,请随时在评论中提问。 如果您想合作开发图书馆,请随时与我联系:)
您可以在我的网站https://matteo.ronchetti.xyz上找到有关我,我所有项目和我所有帖子的更多信息。
From: https://hackernoon.com/raschietto-a-simple-library-for-web-scraping-46957c6aa5b7