使用一个Scrapy爬虫抓取多个网站
我需要创建一个用户可以自定义的网络爬虫,我在考虑使用Scrapy这个工具。但是,我不能把域名和允许的URL规则写死在代码里——这些应该可以在一个图形界面中进行设置。
我该如何(尽量简单)用Scrapy创建一个爬虫,或者一组爬虫,让域名和允许的URL规则可以动态配置呢?比如,我把配置写到一个文件里,然后爬虫可以以某种方式读取这个文件。
4 个回答
3
在这里我来宣传一下我的项目 domo!在你的项目中,你需要按照示例中的方法来创建一个爬虫。
另外,你还需要让这个爬虫在运行时可以配置,也就是说,当配置发生变化时,只需要把新的设置传给爬虫,就能覆盖原来的设置。
4
你需要做的是动态创建爬虫类,也就是从你喜欢的通用爬虫类(比如scrapy
提供的CrawlSpider
,可以加上你的rules
,或者XmlFeedSpider
,等等)进行继承,然后添加domain_name
、start_urls
,还有可能的extra_domain_names
(和/或start_requests()
等),这些信息可以从你的图形界面(GUI)、配置文件或其他地方获取或推断出来。
Python让动态创建类对象变得很简单;一个非常简单的例子可能是:
from scrapy import spider
def makespider(domain_name, start_urls,
basecls=spider.BaseSpider):
return type(domain_name + 'Spider',
(basecls,),
{'domain_name': domain_name,
'start_urls': start_urls})
allspiders = []
for domain, urls in listofdomainurlpairs:
allspiders.append(makespider(domain, urls))
这会给你一系列非常基础的爬虫类——在你实例化它们之前,可能还需要给它们添加parse
方法。根据需要调整一下就好...;-)
10
警告:这个答案是针对Scrapy v0.7的,之后蜘蛛管理器的API变化很大。
你可以覆盖默认的SpiderManager类,从数据库或其他地方加载你自己的规则,然后用你自己的规则、正则表达式和域名实例化一个自定义的蜘蛛。
在mybot/settings.py中:
SPIDER_MANAGER_CLASS = 'mybot.spidermanager.MySpiderManager'
在mybot/spidermanager.py中:
from mybot.spider import MyParametrizedSpider
class MySpiderManager(object):
loaded = True
def fromdomain(self, name):
start_urls, extra_domain_names, regexes = self._get_spider_info(name)
return MyParametrizedSpider(name, start_urls, extra_domain_names, regexes)
def close_spider(self, spider):
# Put here code you want to run before spiders is closed
pass
def _get_spider_info(self, name):
# query your backend (maybe a sqldb) using `name` as primary key,
# and return start_urls, extra_domains and regexes
...
return (start_urls, extra_domains, regexes)
然后在mybot/spider.py中创建你的自定义蜘蛛类:
from scrapy.spider import BaseSpider
class MyParametrizedSpider(BaseSpider):
def __init__(self, name, start_urls, extra_domain_names, regexes):
self.domain_name = name
self.start_urls = start_urls
self.extra_domain_names = extra_domain_names
self.regexes = regexes
def parse(self, response):
...
注意事项:
- 如果你想利用CrawlSpider的规则系统,也可以扩展它。
- 要运行一个蜘蛛,可以使用:
./scrapy-ctl.py crawl <name>
,其中name
会传递给SpiderManager.fromdomain,并且是从后端系统获取更多蜘蛛信息的关键。 - 由于解决方案覆盖了默认的SpiderManager,经典的蜘蛛(每个蜘蛛一个Python模块)将无法工作,但我认为这对你来说不是问题。关于默认蜘蛛管理器的更多信息可以查看TwistedPluginSpiderManager。