Web挖掘或抓取或爬行? 我应该使用什么工具/库?

我想抓取并将一些网页保存为HTML。 比如说,爬进数百个热门网站,只需保存他们的前台和“关于”页面。

我调查了很多问题,但是没有从网页抓取或网页抓取问题中找到答案。

我应该使用什么库或工具来构建解决方案? 或者甚至有一些现有的工具可以处理这个?

这里确实没有好的解决方案。 你是对的,因为你怀疑Python可能是最好的开始方式,因为它非常强大地支持正则表达式。

为了实现这样的东西,SEO(搜索引擎优化)的强大知识将有所帮助,因为有效地优化搜索引擎的网页告诉你搜索引擎的行为。 我会从像SEOMoz这样的网站开始。

至于识别“关于我们”页面,您只有2个选项:

a)对于每个页面,获取about us页面的链接并将其提供给您的抓取工具。

b)解析某些关键字的页面的所有链接 ,例如“关于我们”,“关于”“了解更多”等等。

在使用选项b时,要小心,因为您可能会陷入无限循环,因为网站会多次链接到同一页面,尤其是如果链接位于页眉或页脚中,页面甚至可能链接回自身。 为避免这种情况,您需要创建一个访问过的链接列表,并确保不要重新访问它们。

最后,我建议让您的crawler尊重robot.txt文件中的指令,并且不要遵循标记为rel="nofollow"链接,这可能是一个好主意,因为这些链接主要用于外部链接。 再次,通过阅读SEO来学习这一点和更多。

问候,

在使用Python时,您可能对mechanize和BeautifulSoup感兴趣。

机械化类型模拟浏览器(包括代理,伪造浏览器标识,页面重定向等选项),并允许轻松获取表单,链接,…文档虽然有点粗糙/稀疏。

一些示例代码(来自mechanize网站)给你一个想法:

 import mechanize br = mechanize.Browser() br.open("http://www.example.com/") # follow second link with element text matching regular expression html_response = br.follow_link(text_regex=r"cheese\s*shop", nr=1) print br.title() print html_response 

BeautifulSoup允许很容易地解析html内容(你可以用机械化获取),并支持正则表达式。

一些示例代码:

 from BeautifulSoup import BeautifulSoup soup = BeautifulSoup(html_response) rows = soup.findAll('tr') for r in rows[2:]: #ignore first two rows cols = r.findAll('td') print cols[0].renderContents().strip() #print content of first column 

因此,上面的这10行几乎可以复制粘贴,以便打印网站上每个表行的第一列的内容。

尝试scrapy 。 它是python的web抓取库。 如果需要一个简单的python脚本,请在python中尝试urllib2 。

Python ==> Curl < - 爬虫的最佳实现

以下代码可以在一台漂亮的服务器上在300秒内抓取10,000个页面。

 #! /usr/bin/env python # -*- coding: iso-8859-1 -*- # vi:ts=4:et # $Id: retriever-multi.py,v 1.29 2005/07/28 11:04:13 mfx Exp $ # # Usage: python retriever-multi.py  [<# of # concurrent connections>] # import sys import pycurl # We should ignore SIGPIPE when using pycurl.NOSIGNAL - see # the libcurl tutorial for more info. try: import signal from signal import SIGPIPE, SIG_IGN signal.signal(signal.SIGPIPE, signal.SIG_IGN) except ImportError: pass # Get args num_conn = 10 try: if sys.argv[1] == "-": urls = sys.stdin.readlines() else: urls = open(sys.argv[1]).readlines() if len(sys.argv) >= 3: num_conn = int(sys.argv[2]) except: print "Usage: %s  [<# of concurrent connections>]" % sys.argv[0] raise SystemExit # Make a queue with (url, filename) tuples queue = [] for url in urls: url = url.strip() if not url or url[0] == "#": continue filename = "doc_%03d.dat" % (len(queue) + 1) queue.append((url, filename)) # Check args assert queue, "no URLs given" num_urls = len(queue) num_conn = min(num_conn, num_urls) assert 1 <= num_conn <= 10000, "invalid number of concurrent connections" print "PycURL %s (compiled against 0x%x)" % (pycurl.version, pycurl.COMPILE_LIBCURL_VERSION_NUM) print "----- Getting", num_urls, "URLs using", num_conn, "connections -----" # Pre-allocate a list of curl objects m = pycurl.CurlMulti() m.handles = [] for i in range(num_conn): c = pycurl.Curl() c.fp = None c.setopt(pycurl.FOLLOWLOCATION, 1) c.setopt(pycurl.MAXREDIRS, 5) c.setopt(pycurl.CONNECTTIMEOUT, 30) c.setopt(pycurl.TIMEOUT, 300) c.setopt(pycurl.NOSIGNAL, 1) m.handles.append(c) # Main loop freelist = m.handles[:] num_processed = 0 while num_processed < num_urls: # If there is an url to process and a free curl object, add to multi stack while queue and freelist: url, filename = queue.pop(0) c = freelist.pop() c.fp = open(filename, "wb") c.setopt(pycurl.URL, url) c.setopt(pycurl.WRITEDATA, c.fp) m.add_handle(c) # store some info c.filename = filename c.url = url # Run the internal curl state machine for the multi stack while 1: ret, num_handles = m.perform() if ret != pycurl.E_CALL_MULTI_PERFORM: break # Check for curl objects which have terminated, and add them to the freelist while 1: num_q, ok_list, err_list = m.info_read() for c in ok_list: c.fp.close() c.fp = None m.remove_handle(c) print "Success:", c.filename, c.url, c.getinfo(pycurl.EFFECTIVE_URL) freelist.append(c) for c, errno, errmsg in err_list: c.fp.close() c.fp = None m.remove_handle(c) print "Failed: ", c.filename, c.url, errno, errmsg freelist.append(c) num_processed = num_processed + len(ok_list) + len(err_list) if num_q == 0: break # Currently no more I/O is pending, could do something in the meantime # (display a progress bar, etc.). # We just call select() to sleep until some more data is available. m.select(1.0) # Cleanup for c in m.handles: if c.fp is not None: c.fp.close() c.fp = None c.close() m.close() 

如果您要填充爬虫(需要特定于Java):

  1. 了解如何使用java.net.URL和java.net.URLConnection类或使用HttpClient库
  2. 了解http请求/响应标头
  3. 理解重定向(HTTP,HTML和Javascript)
  4. 理解内容编码(字符集)
  5. 使用一个好的库来解析格式错误的HTML(例如cyberNecko,Jericho,JSoup)
  6. 向不同的主机发出并发HTTP请求,但确保每隔约5秒向同一主机发出不超过一个的请求
  7. 保留已提取的页面,因此如果它们不经常更改,则不需要每天都重新获取它们(HBase可能很有用)。
  8. 一种从当前页面提取链接到下一个爬网的方法
  9. 服从robots.txt

还有一堆其他的东西。

这并不困难,但有很多繁琐的边缘情况(例如重定向,检测编码(结帐Tika))。

有关更多基本要求,您可以使用wget。 Heretrix是另一种选择,但还有另一个需要学习的框架。

识别关于我们页面可以使用各种启发式方法完成:

  1. 入站链接文本
  2. 页面标题
  3. 页面上的内容
  4. url

如果你想更加量化它,你可以使用机器学习和分类器(也许是贝叶斯)。

保存首页显然更容易,但首页重定向(有时到不同的域,通常在HTML元重定向标记甚至JS中实现)非常常见,因此您需要处理此问题。

Heritrix有一个陡峭的学习曲线,但可以配置为只有主页,以及“看起来像”(使用正则表达式filter)页面的页面将被抓取。

更多开源Java(Web)爬虫: http : //java-source.net/open-source/crawlers