从网站上抓取数据的最好方法是什么?
我需要从网站中提取内容,但应用程序不提供任何应用程序编程接口或其他机制以编程方式访问该数据。
我发现了一个名为Import.io的有用的第三方工具,它提供了用于抓取网页和构build数据集的点击和移动function,唯一的是我想在本地保存数据,而且我不想订阅任何订阅计划。
这家公司使用什么样的技术来抓取网页和build立他们的数据集? 我发现一些网页抓取框架pjscrape和Scrapy可以提供这样的function
你一定会想从一个好的网页抓取框架开始。 稍后你可能会认为它们太过于限制,你可以把自己的一堆库放在一起,但是没有太多的抓取经验,你的devise会比pjscrape或scrapy更糟糕。
注意:我在这里使用的术语爬行和抓取基本上可以互换。 这是我的回答你的Quora问题的副本,这是相当长的。
工具
根据您的首选浏览器熟悉Firebug或Chrome开发工具。 当您浏览您要从中提取数据的网站并确定哪些url包含您正在查找的数据以及哪些数据格式组成响应时,这将是绝对必要的。
你将需要一个良好的HTTP和HTML的工作知识,并可能会想在中间代理软件中find一个体面的人。 您将需要能够检查HTTP请求和响应,并了解Cookie和会话信息以及查询参数如何传递。 Fiddler( http://www.telerik.com/fiddler )和Charles Proxy( http://www.charlesproxy.com/ )是stream行的工具。 我使用mitmproxy( http://mitmproxy.org/ )很多,因为我更像一个键盘人,而不是老鼠。
某种types的控制台/shell/ REPLtypes环境,您可以通过即时反馈来testing各种代码片段,这是非常宝贵的。 像这样的反向工程任务有很多反复试验,所以你需要一个简单的工作stream程。
语言
PHP基本上已经出来了,它不太适合这个任务,而且这个领域的库/框架支持很差。 Python(Scrapy是一个很好的起点)和Clojure / Clojurescript(难以置信的强大和高效率,但一个巨大的学习曲线)是这个问题的伟大的语言。 既然你宁愿不学习一种新的语言,你已经知道Javascript,我一定会build议坚持与JS。 我没有使用pjscrape,但从文档的快速阅读看起来相当不错。 它非常适合并实现了我在下面描述的问题的一个出色的解决scheme。
关于正则expression式的注意事项:不要使用正则expression式来分割HTML。 很多初学者都这样做,因为他们已经熟悉正则expression式。 这是一个巨大的错误,使用xpath或cssselect器浏览html,只使用正则expression式从html节点内的实际文本中提取数据。 这对你来说可能已经是显而易见的了,如果你尝试了,很快就会变得很明显,但是很多人因为某种原因浪费了很多时间。 不要害怕xpath或cssselect器,它们比正则expression式更容易学习,它们被devise来解决这个确切的问题。
Javascript重度网站
在过去,你只需要做一个http请求并parsingHTML响应。 现在,您几乎可以肯定必须处理由标准HTML HTTP请求/响应和由目标站点的javascript部分进行的asynchronousHTTP调用混合的站点。 这是您的代理软件和萤火虫/ devtools的networking标签非常方便的地方。 对这些的回应可能是HTML或者他们可能是JSON,在极less数情况下,他们将是XML或其他东西。
有两种解决这个问题的方法:
低级方法:
你可以找出什么Ajax的urlJavaScript调用,以及这些回应是什么样子,并自己做出这些相同的请求。 所以你可能会从http://example.com/foobar提取html,并提取一个数据,然后必须将http://example.com/api/baz?foo=b …的json响应获取另一条数据。 您需要注意传递正确的cookie或会话参数。 这是非常罕见的,但偶尔一些ajax调用所需的参数将是在网站的JavaScript做一些疯狂的计算的结果,逆向工程这可能是烦人的。
embedded式浏览器方法:
为什么需要计算出html中的数据以及ajax调用的数据? pipe理所有的会话和cookie数据? 你不必在浏览网站,浏览器和网站的JavaScript那样做。 这就是整个问题。
如果您只是将页面加载到像phantomjs这样的无头浏览器引擎中,它将加载页面,运行javascript并告诉您何时所有ajax调用已完成。 您可以注入自己的JavaScript,如果有必要触发适当的点击或任何必要的触发网站的JavaScript加载适当的数据。
你现在有两个select,得到它吐出完成的HTML,并parsing它或注入一些JavaScript的页面进行parsing和数据格式,并吐出数据(可能以json格式)。 您也可以自由混合这两个选项。
哪种方法最好?
这取决于,你需要熟悉和舒适的低层次的方法。 embedded式浏览器的方法适用于任何事情,这将是更容易实施,并会使一些棘手的问题在消失。 这也是相当复杂的一部分,你需要了解。 这不仅仅是HTTP请求和响应,它是请求,embedded式浏览器渲染,网站JavaScript,注入JavaScript,您自己的代码和与embedded式浏览器进程的双向交互。
embedded式浏览器的规模也要慢得多,因为渲染开销太大了,但是除非你搞不清很多不同的领域,否则几乎肯定不会有问题。 在单个域名的情况下,您需要限制您的请求将使渲染时间完全可以忽略不计。
速率限制/机器人行为
你需要非常清楚这一点。 您需要以合理的速度向目标域名提出请求。 在抓取网站时,您需要编写一个行为良好的机器人,这意味着尊重robots.txt,而不是要求服务器锤击。 这里的错误或疏忽是非常不道德的,因为这可以被认为是拒绝服务攻击。 可接受的速度取决于您问的人数,1req / s是Google抓取工具运行的最大值,但您不是Google,您可能不像Google那么受欢迎。 保持合理的缓慢。 我build议在每个页面请求之间2-5秒。
使用用户代理string识别您的请求,该string标识您的机器人并为您的机器人提供一个网页,以说明其目的。 这个url在代理string中。
如果网站想阻止你,你将很容易被阻止。 一个聪明的工程师在他们的最后可以很容易地识别机器人,而他们最后几分钟的工作可能会导致数周的工作改变你的terminal上的刮码,或者使之变得不可能。 如果这种关系是对立的,那么目标网站上的一名智能工程师就可以完全阻止一名撰写爬虫的天才工程师。 刮码本质上是脆弱的,这很容易被利用。 一些会引起这种反应的东西肯定是不道德的,所以编写一个行为良好的机器人,不要担心这个。
testing
不是一个单位/整合testing人员? 太糟糕了。 你现在必须成为一个。 网站频繁更换,您将经常更改您的代码。 这是挑战的很大一部分。
在现代网站上有很多移动部件,好的testing实践会有很大的帮助。 编写这种types的代码时遇到的许多错误将会是那种只是静态地返回损坏的数据的types。 如果没有良好的testing来检查回归,你会发现你已经将无用的损坏的数据保存了一段时间,而没有注意到。 这个项目将使你非常熟悉数据validation(find一些好的库使用)和testing。 结合需要综合testing,难度很大的其他问题并不多见。
testing的第二部分涉及caching和更改检测。 在编写你的代码的时候,你不想一次又一次地无意识地在同一个页面上敲击服务器。 在运行你的unit testing的时候,你想知道你的testing是否因为破坏你的代码或因为网站被重新devise而失败。 针对相关url的caching副本运行unit testing。 caching代理在这里非常有用,但是configuration和使用都很困难。
你也想知道该网站是否已经改变。 如果他们重新devise了网站,并且抓取工具已经损坏,那么您的unit testing仍然会通过,因为它们是针对caching副本运行的! 您将需要另外一组较小的集成testing,这些集成testing针对实时站点不常运行,或者您的爬网代码中的日志logging和错误检测良好,logging确切的问题,提醒您遇到问题并停止爬网。 现在你可以更新你的caching,运行你的unit testing,看看你需要改变。
法律问题
如果你做愚蠢的事情,这里的法律可能会有点危险。 如果涉及到法律问题,那么你们经常把那些经常提到wget和curl的人称为“黑客工具”。 你不想要这个。
这种情况的道德现实是,使用浏览器软件请求一个URL并查看一些数据,并使用自己的软件来请求一个URL并查看一些数据,没有任何区别。 谷歌是世界上最大的刮板公司,他们为此深受喜爱。 在用户代理中识别您的机器人名称,并开放您的networking爬虫的目标和意图将在这里帮助,因为法律了解谷歌是什么。 如果您做了任何黑幕,比如创build假用户帐户或访问不应该(不是由robots.txt“阻止”或由于某种授权利用而被阻止)的站点区域,请注意您正在做的事情是不道德的法律对技术的无知在这里将是非常危险的。 这是一个荒谬的情况,但它是一个真实的。
从字面上可以尝试build立一个新的search引擎,作为一个优秀的公民,犯错或者在你的软件中有一个bug,被视为黑客。 不是你想要考虑当前的政治现实。
我该怎么写这个巨大的文字墙呢?
在我的生活中,我写了很多与networking爬虫相关的代码。 作为顾问,员工和创业公司的创始人,我已经做了十多年的networking相关软件开发。 早期写perl crawlers / scrapers和php的网站。 当我们embedded隐藏的iframe将csv数据加载到网页中,然后在Jesse James Garrett将其命名为ajax之前,在XMLHTTPRequest是一个想法之前做ajax。 在jQuery之前,在json之前。 我已经30多岁了,这显然被认为是古老的业务。
我曾经为一家媒体公司的大型团队(Perl)写过一次大规模的抓取/抓取系统,最近也是一个小型团队担任search引擎初创公司(Python / Javascript)的首席技术官。 我目前是一名顾问,主要是编写Clojure / Clojurescript(一个非常棒的专家语言,并且有一些库使抓取/抓取问题变得愉快)
我也写了成功的反爬行软件系统。 如果你想要识别和破坏你不喜欢的僵尸程序,那么写出几乎无法破解的网站是相当容易的。
我喜欢写爬虫,刮板和parsing器比任何其他types的软件。 这是具有挑战性的,有趣的,可以用来创造惊人的东西。
是的,你可以自己做。 这只是一个抓取页面的来源和parsing他们的方式,你想要的问题。
有各种各样的可能性。 一个很好的组合是使用python-requests (build立在urllib2之上,它是Python3中的urllib.request
)和BeautifulSoup4 ,它有它的方法来select元素,也允许CSSselect器 :
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")
有些人会喜欢xpathparsing或jquery-like pyquery, lxml或其他东西 。
当你想要的数据是由一些JavaScript生成的时候,上面的内容将不起作用。 您可能需要python-ghost或Selenium。 我更喜欢后者与PhantomJS相结合 ,更轻,更简单的安装和易于使用:
from selenium import webdriver client = webdriver.PhantomJS() client.get("http://foo") soup = bs(client.page_source)
我会build议开始你自己的解决scheme。 你会理解Scrapy的好处。
ps:看看scrapyly: https : //github.com/scrapy/scrapely
pps:看看Portia,开始直观地提取信息,无需编程知识: https : //github.com/scrapinghub/portia