从网站抓取数据的最佳方法是什么?[关闭]


107

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

我找到了一个有用的第三方工具Import.io,该工具提供了用于抓取网页和构建数据集的即即用功能,唯一的是我想将数据保存在本地,并且我不想订阅任何订阅计划。

该公司使用哪种技术来抓取网页并构建其数据集?我发现一些网页抓取框架pjscrapeScrapy是否可以提供这样的功能


4
PHP当然不是不可能的,显然,这显然是错误的。gist.github.com/krakjoe/b1526fcc828621e840cb
Joe Watkins

@JoeWatkins看起来真的很酷,是否需要特殊的PHP配置才能运行?与下面提供的工具/语言相比,性能如何?
0x1ad2 2014年

1
它需要PHP和pthreads的线程安全构建,请阅读github.com/krakjoe/pthreads/blob/master/README.md,如果您需要帮助,可以在聊天中找到我,我还是其他人:)
Joe Watkins

@ 0x1ad2如果要保留本地数据,则应尝试使用软件(datascraping.co)代替Web API。大多数工具使用Xpath,CSS选择器和REGEX从网站提取数据,并且Data Scraping Studio支持所有这三个功能。
维卡什·拉西

有两种方法,一种是使用免费/开源库来推出自己的库,这需要很多工作。您可以使用scrape.it从字面上为任何站点生成ajax Web 搜寻器。它是一种付费工具,但是在import.io或和服等免费工具都无法渲染时,它可以工作。
我爱Python

Answers:


271

您肯定会想从一个好的Web抓取框架开始。稍后您可能会认为它们太过局限了,可以将自己的库放在一起,但是没有大量的抓图经验,那么您的设计就会比pjscrape或scrapy糟糕得多。

注意:我在这里使用的术语“抓取和抓取”基本上可以互换。这是我对您的Quora问题的回答的副本,相当长。

工具类

根据您喜欢的浏览器来熟悉Firebug或Chrome开发者工具。当您浏览要从中提取数据的站点并确定哪些url包含要查找的数据以及响应的数据格式时,这绝对是必要的。

您将需要具备HTTP和HTML的良好工作知识,并且可能希望在中间代理软件中找到一位像样的人。您将需要能够检查HTTP请求和响应,并了解cookie,会话信息和查询参数的传递方式。Fiddler(http://www.telerik.com/fiddler)和Charles Proxy(http://www.charlesproxy.com/)是流行的工具。我经常使用mitmproxy(http://mitmproxy.org/),因为我比键盘人更像键盘人。

在某种控制台/外壳/ REPL类型的环境中,您可以尝试各种具有即时反馈的代码,这将是非常宝贵的。像这样的逆向工程任务需要大量的反复试验,因此您将需要一个使之简单的工作流程。

语言

PHP基本上已经淘汰了,它不太适合此任务,并且库/框架在该领域的支持很差。Python(Scrapy是一个很好的起点)和Clojure / Clojurescript(功能强大,高效但学习曲线很大)是解决此问题的出色语言。由于您不想学习一种新语言,并且您已经知道Java语言,因此我绝对建议您坚持使用JS。我还没有使用过pjscrape,但是从快速阅读他们的文档来看,它看起来相当不错。它非常适合并为我在下面描述的问题提供了出色的解决方案。

关于正则表达式的说明:请勿使用常规表达式来解析HTML。许多初学者这样做是因为他们已经对正则表达式很熟悉。这是一个巨大的错误,请使用xpath或CSS选择器浏览html,而仅使用正则表达式从html节点内的实际文本中提取数据。这对您可能已经很明显了,如果您尝试一下,它很快就会变得显而易见,但是很多人由于某种原因而浪费大量时间沿着这条路走。不要害怕xpath或CSS选择器,它们比正则表达式更容易学习,并且它们旨在解决这个确切的问题。

大量使用JavaScript的网站

在过去,您只需要发出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,您自己的代码以及与嵌入式浏览器进程的2向交互。

由于呈现开销,嵌入式浏览器在规模上也要慢得多,但是除非您要抓取许多不同的域,否则几乎可以肯定这无关紧要。如果需要限制请求的速率,则在单个域的情况下,渲染时间完全可以忽略不计。

速率限制/启动行为

您需要非常注意这一点。您需要以合理的速率向目标域提出请求。抓取网站时,您需要编写行为良好的bot,这意味着要尊重robots.txt,不要在服务器上处理请求。错误或疏忽在这里是非常不道德的,因为这可以被视为拒绝服务攻击。可接受的速率取决于您询问的人,1req / s是运行Google搜寻器的最高速度,但您不是Google,并且可能不如Google受欢迎。使其保持尽可能慢的速度。我建议每个页面请求之间2-5秒。

使用用户代理字符串标识您的请求,该字符串标识您的机器人并为您的机器人提供一个网页,以说明其用途。该网址在代理字符串中。

如果该网站想阻止您,您将很容易被阻止。末端的智能工程师可以轻松地识别机器人,而末端的几分钟工作可能会导致数周的工作最终更改您的抓取代码,或者使其变得不可能。如果这种关系是对立的,那么目标站点的聪明工程师可以完全阻碍编写爬虫的天才工程师。爬网代码本质上很脆弱,很容易被利用。无论如何,几乎可以肯定会引起这种反应的是不道德的,所以写一个行为良好的机器人就不用担心了。

测试中

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

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

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

您还想知道站点是否已更改。如果他们重新设计了站点,并且您的搜寻器已损坏,则由于它们针对缓存副本运行,因此单元测试仍将通过!您将需要另一套较小的,不经常在实时站点上运行的集成测试,或者需要在爬网代码中进行良好的日志记录和错误检测,以记录确切的问题,向您发出警报并停止爬网。现在,您可以更新缓存,运行单元测试并查看需要更改的内容。

法律问题

如果您做愚蠢的事情,这里的法律可能会有些危险。如果法律介入,您将与经常将wget和curl称为“黑客工具”的人打交道。你不要这个

这种情况的道德现实是,使用浏览器软件请求url和查看一些数据与使用您自己的软件请求url和查看一些数据之间没有区别。Google是世界上最大的刮板公司,因此受到了喜爱。在法律上了解Google是什么之后,在用户代理中标识您的漫游器名称并公开您的网络抓取工具的目标和意图将对您有所帮助。如果您在做任何不受欢迎的事情,例如创建虚假的用户帐户或访问不应访问的网站区域(被robots.txt“阻止”或由于某种授权利用而被阻止),那么请注意您所做的事情是不道德的法律对技术的无知在这里将极为危险。这是一个荒谬的情况,但这是真实的情况。

从字面上看,有可能尝试以一个正直的公民不断建立一个新的搜索引擎,犯错或在软件中出现错误,并被视为黑客。您不必考虑当前的政治现实。

无论如何,我要写给谁呢?

我一生中编写了许多与Web爬网相关的代码。作为顾问,员工和创业者,我从事与网络相关的软件开发已有十多年了。早期是写Perl爬虫/爬虫和php网站的。当我们嵌入隐藏的iframe并将csv数据加载到网页中进行ajax之前,Jesse James Garrett将其命名为ajax之前,而XMLHTTPRequest是一个想法。在jQuery之前,在json之前。我正处于30多岁的年龄,这显然被认为是一项古老的业务。

我已经编写了两次大型爬网/爬网系统,一次是为一家媒体公司的大型团队(在Perl中)编写的,最近一次是为一个小团队作为搜索引擎初创公司的CTO(在Python / Javascript中)编写的。我目前担任顾问,主要使用Clojure / Clojurescript(一般来说是一种出色的专家语言,并且具有使爬虫/爬虫问题令人愉悦的库)进行编码。

我也写了成功的防爬网软件系统。如果您愿意或者很难识别和破坏机器人,那么编写几乎无法捕获的站点非常容易。

我比其他任何类型的软件都更喜欢编写搜寻器,爬虫和解析器。它具有挑战性,趣味性,可以用来创造惊人的事物。


4
我曾经就PHP是一个不好的选择与您达成一致,但是使用正确的库并不太糟。正则表达式和数组/ sting操作很笨拙,但从正面看,它遍及各处都是快速的。
pguardiario 2014年

3
在一个环境中,有一些使它变得令人愉悦的库,而有许多使它变得非常简单和非常容易的库...为什么您会选择“不太差”。我同意,这在PHP(以及FORTRAN,C,VB等)中是可行的,但是除非您的问题确实非常简单,否则使用正确的工具完成工作将是一个更好的主意。再说一次,除非您有一个非常简单的问题要解决...到处都有正则表达式有什么关系?安装库比几乎每个刮刮问题都简单得多。实际上,正则表达式对于此问题通常很慢。
杰西·夏洛克

5
您可能是对的,但是我知道,在PHP 中不那么容易做到这一点。在离开PHP之前,我已经有近十年的专业PHP经验。我花了一年多的时间在Python上大规模构建一个抓取系统,我无法想象如果没有一些PHP无法提供的漂亮库,或者没有Python提供的简洁元编程技术, 。这也是我搬到Clojure以获得更强大的元编程能力的原因。
Jesse Sherlock

4
Enlive以及Clojure本身针对特定项目代码的强大功能,是最大的赢家。Schema是一个很棒的验证库,它是信息提取代码的重要组成部分。目前,我对与Java世界轻松实现互操作(例如Mahout以及Nashorn / Rhino用于某些js执行)感到非常满意。Clojure人就是这样的人,他们像github.com/shriphani/subotai这样编写库,因此您不必这样做。...继续在下一条评论中……
Jesse Sherlock 2014年

3
我还发现,当您真的需要一个真正的浏览器并且需要使用phantomjs / casperjs时,使用clojurescript(通常是clj和cljs之间使用cljx共享的代码)真的很不错,可以编写注入页面的js而不是clojurescript 。Core.async非常适合在服务器上协调高度并发的爬网代码以及摆脱js环境中的回调地狱(与其他方法相比,将浏览器自动化与phantomjs中的core.async cljs代码进行协调非常重要)。
杰西·夏洛克

21

是的,您可以自己做。只需获取页面源并按所需方式解析它们即可。

有多种可能性。一个很好的组合是使用python-requests(建立在urllib2之上,它urllib.request在Python3中)和BeautifulSoup4,它们具有选择元素的方法,还允许CSS选择器

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或其他东西

当您想要的数据由某些JavaScript生成时,上述方法将无法使用。您需要python-ghost或Selenium。我更喜欢将后者与PhantomJS结合使用,安装起来更轻便,更容易且易于使用:

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

我建议您开始自己的解决方案。您将了解Scrapy这样做的好处。

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

pps:看一下Portia,开始可视化地提取信息,而无需编程知识:https : //github.com/scrapinghub/portia


好的,感谢您的答案,唯一的问题是Python不在我的技能范围内。还有其他好的编程语言可以完成相同的任务吗?我主要使用PHP和Javascript。
0x1ad2 2014年

很抱歉造成混乱(我在问题中提到了Python框架),但是如果Python是最好的方法,我可以学习它。
0x1ad2 2014年

Python使抓痒变得非常容易。这也很容易学习。目前表现最佳的最佳刮板是刮板。他们也有很好的文档。
Abhishek 2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.