【发布时间】:2010-09-08 01:27:21
【问题描述】:
我有丰富的 PHP 经验,尽管我意识到 PHP 可能不是大型网络爬虫的最佳语言,因为进程不能无限期地运行。人们建议使用哪些语言?
【问题讨论】:
标签: php c++ python web-crawler
我有丰富的 PHP 经验,尽管我意识到 PHP 可能不是大型网络爬虫的最佳语言,因为进程不能无限期地运行。人们建议使用哪些语言?
【问题讨论】:
标签: php c++ python web-crawler
大多数语言可能都比较合适,关键组件是
如今,大多数语言都有对上述内容提供良好支持的库,当然您需要一些方法来保存可能是某种数据库的结果。
比语言更重要的是理解你需要处理的所有概念。以下是一些 Python 示例,可能有助于您入门。
【讨论】:
您可以轻松使用的任何语言都具有良好的网络库并支持解析您要抓取的格式。这些确实是唯一的资格。
【讨论】:
您可以考虑使用 python 和 PyGtkMozEmbed 或 PyWebKitGtk 加上 javascript 的组合来创建您的蜘蛛。
在页面和所有其他脚本加载后,可以在 javascript 中进行爬取。
您将拥有少数支持 javascript 的网络蜘蛛之一,并且可能会拾取一些其他人看不到的隐藏内容 :)
【讨论】:
C++ - 如果你知道你在做什么。您将不需要 Web 服务器和 Web 应用程序,因为 Web 爬虫毕竟只是一个客户端。
【讨论】:
既然可以复制http://code.activestate.com/recipes/576551-simple-web-crawler/,为什么还要自己写
您可能需要在这里和那里修复一些问题,例如使用 htmlentities 而不是将 & 替换为 &
【讨论】:
在编写多核/线程爬虫时,C 是最重要的,但它也有其自身的复杂性。在 C 之后,一些人选择了 JAVA(由于广泛的探索和使用),而另一些人则选择了 Python。如果你有很好的架构,我可以向你保证这三种语言真的不会限制你的效率。
这个 python 代码是一个 C 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 <file with URLs to fetch> [<# 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 <file with URLs to fetch> [<# 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()
【讨论】:
C# 和 C++ 可能是这方面最好的两种语言,只是你更了解哪种语言更快(C# 可能更容易)的问题。
我不推荐 Python、Javascript 或 PHP。与 C 系列语言相比,它们的文本处理速度通常较慢。如果您希望抓取网络的任何重要部分,您将需要尽可能快的速度。
我之前使用过 C# 和 HtmlAgilityPack,它的效果相对较好,而且很容易上手。能够像使用 XML 一样使用许多相同的命令来处理 HTML,这让它变得很好(我曾在 C# 中使用过 XML)。
您可能想要测试可用的 C# HTML 解析库与 C++ 解析库的速度。我知道在我的应用程序中,我每秒要浏览 60-70 个相当混乱的页面,并从每个页面中提取大量数据(但那是一个布局相当稳定的网站)。
编辑:我注意到您提到访问数据库。 C++ 和 C# 都有可用于大多数常见数据库系统的库,从 SQLite(这对于在几个站点上的快速爬虫来说非常有用)到 MySQL 和 MSSQL 等中端引擎,再到更大的 DB 引擎(我从未使用过 Oracle或来自任一语言的 DB2,但这是可能的)。
【讨论】:
strlen() 与时间线性的 C 中的 string length 进行比较,tcl 中的 string length 是恒定时间。这是因为高级语言中的“字符串”通常在后端实现为适当的数据结构,而不是原始 C 字符串。当然,没有任何保证。例如,Microsoft 的 javascript 的行为就好像 String 对象只是 C 字符串的一个薄包装器。