从网站上抓取数据的最佳方法是什么?

时间:2014-03-04 10:11:17

标签: api web-scraping screen-scraping

我需要从网站提取内容,但应用程序不提供任何应用程序编程接口或其他机制来以编程方式访问该数据。

我找到了一个名为Import.io的有用的第三方工具,它提供了抓取网页和构建数据集的点击操作功能,唯一的一件事是我想在本地保存我的数据而我不想订阅任何订阅计划。

该公司使用什么技术来抓取网页并构建数据集?我找到了一些网络抓取框架pjscrape& Scrapy他们可以提供这样的功能

2 个答案:

答案 0 :(得分:265)

您肯定希望从一个良好的网络抓取框架开始。稍后您可能会认为它们太限制了,您可以将自己的堆栈放在一起但没有大量的刮擦经验,您的设计将比pjscrape或scrapy更糟糕。

注意:我在这里使用基本可互换的术语爬行和抓取。这是我对Quora问题的回答的副本,它很长。

工具

根据您首选的浏览器,熟悉Firebug或Chrome开发工具。当您浏览从中提取数据的网站并确定哪些网址包含您要查找的数据以及构成响应的数据格式时,这将是绝对必要的。

您需要具备HTTP和HTML的良好工作知识,并且可能希望在中间代理软件中找到一个体面的人。您需要能够检查HTTP请求和响应,并了解如何传递cookie和会话信息以及查询参数。 Fiddler(http://www.telerik.com/fiddler)和Charles Proxy(http://www.charlesproxy.com/)是流行的工具。我使用mitmproxy(http://mitmproxy.org/)很多,因为我更像是键盘人而非鼠标人。

某种类型的控制台/ shell / REPL类型环境,您可以通过即时反馈尝试各种代码,这将是非常宝贵的。像这样的逆向工程任务需要大量的试验和错误,因此您需要一个简化工作流程的工作流程。

<强>语言

PHP基本上没有用,它不适合这项任务,而且这个领域的库/框架支持很差。 Python(Scrapy是一个很好的起点)和Clojure / Clojurescript(令人难以置信的强大和高效但很大的学习曲线)是这个问题的优秀语言。既然你不想学习一门新语言而且你已经知道Javascript我肯定会建议坚持使用JS。我没有使用过pjscrape,但从快速阅读他们的文档看起来相当不错。它非常适合并实现了我在下面描述的问题的出色解决方案。

关于正则表达式的说明: 不要将常规表达式用于PARSE HTML。 许多初学者都这样做是因为他们已经熟悉了正则表达式。这是一个巨大的错误,使用xpath或css选择器来导航html并且仅使用正则表达式从html节点内的实际文本中提取数据。这对你来说可能已经很明显了,如果你尝试的话很快就会很明显,但很多人因为某种原因浪费了很多时间。不要害怕xpath或css选择器,它们比正则表达式更容易学习,它们旨在解决这个问题。

Javascript-heavy sites

在过去,你只需要发出一个http请求并解析HTML响应。现在,您几乎肯定必须处理混合标准HTML HTTP请求/响应和目标站点的javascript部分进行的异步HTTP调用的站点。这是您的代理软件和firebug / devtools的网络选项卡非常方便的地方。对这些的回复可能是html或者它们可能是json,在极少数情况下它们将是xml或其他。

这个问题有两种方法:

低级方法:

您可以弄清楚网站javascript正在调用的ajax网址以及这些响应的外观并自行提出相同的请求。因此,您可以从http://example.com/foobar中提取html并提取一段数据,然后必须从http://example.com/api/baz?foo=b ...中提取json响应以获取另一段数据。您需要知道传递正确的cookie或会话参数。这是非常罕见的,但偶尔ajax调用所需的一些参数将是在网站的javascript中进行一些疯狂计算的结果,逆向工程这可能很烦人。

嵌入式浏览器方法:

为什么你需要计算html中的数据以及ajax调用中的数据?管理所有会话和cookie数据?当您浏览网站,浏览器和网站javascript时,您不必这样做。这就是重点。

如果您只是将页面加载到像phantomjs这样的无头浏览器引擎中,它将加载页面,运行javascript并告诉您所有ajax调用何时完成。如有必要,您可以注入自己的javascript来触发相应的点击或触发网站javascript加载相应数据所需的任何内容。

你现在有两个选项,让它吐出完成的html并解析它或者在你的解析和数据格式化的页面中注入一些javascript并将数据吐出(可能是json格式)。你也可以自由地混合这两个选项。

哪种方法最好?

这取决于您,您需要熟悉并熟悉低级别方法。嵌入式浏览器方法适用于任何事情,它将更容易实现,并将使一些最棘手的刮取问题消失。它也是一个非常复杂的机器,你需要了解它。它不仅包括HTTP请求和响应,它的请求,嵌入式浏览器呈现,站点javascript,注入的javascript,您自己的代码以及与嵌入式浏览器进程的双向交互。

由于渲染开销,嵌入式浏览器的规模也大得多,但除非你正在抓取很多不同的域,否则几乎肯定无关紧要。在单个域的情况下,您需要对请求进行速率限制将使渲染时间完全忽略不计。

速率限制/机器人行为

你需要非常清楚这一点。您需要以合理的价格向目标域提出请求。在抓取网站时,您需要编写一个表现良好的机器人,这意味着尊重robots.txt,而不是通过请求锤击服务器。这里的错误或疏忽是非常不道德的,因为这可以被视为拒绝服务攻击。可接受的费率取决于您询问的对象,1req / s是Google抓取工具运行的最大值,但您不是Google,而且您可能不像Google那样受欢迎。保持尽可能慢。我建议在每个页面请求之间间隔2-5秒。

使用标识您的机器人的用户代理字符串识别您的请求,并为您的机器人设置一个网页,说明其目的。此URL位于代理字符串中。

如果网站想阻止您,您将很容易阻止。一个聪明的工程师可以很容易地识别机器人,他们最后几分钟的工作可能会导致数周的工作改变你的刮擦代码,或者只是让它变得不可能。如果这种关系具有敌意,那么目标站点的智能工程师就可以完全阻止编写爬虫的天才工程师。刮痧代码本身就很脆弱,很容易被利用。无论如何,引起这种反应的东西几乎肯定是不道德的,所以写一个表现良好的机器人并不担心这个。

<强>测试

不是单位/整合测试人员?太糟糕了。你现在必须成为一个。网站经常更改,您将经常更改代码。这是挑战的很大一部分。

在抓取现代网站时涉及很多活动部分,良好的测试实践将有很大帮助。编写此类代码时遇到的许多错误都是以静默方式返回损坏数据的类型。如果没有良好的测试来检查回归,您会发现您已经将无用的损坏数据保存到您的数据库一段时间而没有注意到。这个项目将使您非常熟悉数据验证(找到一些好的库)和测试。没有太多其他问题需要综合测试并且很难测试。

测试的第二部分涉及缓存和更改检测。在编写代码时,您不希望无缘无故地反复敲击同一页面的服务器。在运行单元测试时,您想知道您的测试是否因为您的代码损坏或者网站已经过重新设计而失败。针对所涉及的URL的缓存副本运行单元测试。缓存代理在这里非常有用,但配置和使用起来很棘手。

您还想知道该网站是否已更改。如果他们重新设计了网站并且您的抓取工具损坏了,那么您的单元测试仍会通过,因为它们是针对缓存副本运行的!您将需要另一个较小的集成测试集,这些集合测试不常在实时站点上运行,或者需要在爬网代码中进行良好的日志记录和错误检测,以记录确切的问题,提醒您解决问题并停止爬网。现在,您可以更新缓存,运行单元测试并查看需要更改的内容。

法律问题

如果你做了愚蠢的事情,这里的法律可能会有点危险。如果涉及到法律,那么您正在与那些经常将wget和curl称为&#34; hacking tools&#34;的人打交道。你不想要这个。

情况的道德现实是,使用浏览器软件请求网址并查看某些数据并使用您自己的软件请求网址并查看某些数据之间没有区别。谷歌是世界上最大的刮刮公司,他们深受喜爱。在用户代理中识别您的机器人名称并对您的网络抓取工具的目标和意图保持开放将有助于此,因为法律了解Google的用途。如果您正在做任何不好的事情,比如创建虚假的用户帐户或访问您不应该(通过robots.txt阻止&#34;或者由于某种授权漏洞利用)的网站区域,那么意识到你正在做一些不道德的事情,法律对技术的无知在这里会非常危险。这是一个荒谬的情况,但它是一个真实的情况。

尝试建立一个新的搜索引擎作为一个正直的公民,犯错误或在你的软件中有一个错误并被视为黑客,这几乎是可能的。考虑到当前的政治现实,不是你想要的东西。

无论如何,我是谁来写这个巨大的文字墙?

我在生活中写过很多网络抓取相关代码。作为顾问,员工和创业公司创始人,我作为网络相关的软件开发已经做了十多年。早期的时候是写perl crawlers / scraper和php网站。当我们嵌入隐藏的iframe时,在Jesse James Garrett将其命名为ajax之前,将csv数据加载到网页中以执行ajax,之后XMLHTTPRequest就是一个想法。在jQuery之前,在json之前。我在30岁左右,显然对这项业务来说是古老的。

我已经两次编写了大规模的抓取/抓取系统,一次是针对媒体公司的大型团队(在Perl中),最近是一个小团队作为搜索引擎启动的CTO(在Python / Javascript中) 。我目前担任顾问,主要编写Clojure / Clojurescript(一般来说是一种很棒的专家语言,并且有一些库让爬虫/刮刀问题变得很愉快)

我也写过成功的反爬行软件系统。如果你想要识别和破坏你不喜欢的机器人,那么编写难以攻陷的网站非常容易。

我比任何其他类型的软件更喜欢编写爬虫,抓取器和解析器。它具有挑战性,有趣,可以用来创造惊人的东西。

答案 1 :(得分:21)

是的,你可以自己做。这只是抓住页面的来源并按照您想要的方式解析它们的问题。

有各种可能性。一个好的组合是使用python-requests(建立在urllib2之上,在Python3中是urllib.request)和BeautifulSoup4,它有自己的方法来选择元素并允许CSS selectors

import requests
from BeautifulSoup4 import BeautifulSoup as bs
request = requests.get("http://foo.bar")
soup = bs(request.text) 
some_elements = soup.find_all("div", class_="myCssClass")

有些人更喜欢xpath解析或类似jquery的pyquery,lxml or something else

当您想要的数据由某些 JavaScript 生成时,上述内容将无效。你需要python-ghost或Selenium。我更喜欢后者combined with PhantomJS,更轻松,更简单,易于使用:

from selenium import webdriver
client = webdriver.PhantomJS()
client.get("http://foo")
soup = bs(client.page_source)

我建议你开始自己的解决方案。你会理解Scrapy的好处。

ps:看看scrapely:https://github.com/scrapy/scrapely

pps:看看Portia,开始直观地提取信息,而无需编程知识:https://github.com/scrapinghub/portia