如何使用Scrapy爬取多个域名

5

我有一个项目需要爬取大量不同的网站。由于我不需要从其主体页面中提取信息,因此所有这些网站的爬取都可以使用相同的Spider。我想到的方法是在Spider文件中对要爬取的域进行参数化,并传递域和起始URL作为参数调用Scrapy爬行命令,以便我可以避免为每个站点生成单个Spider(站点列表将随时间增加)。我的想法是将其部署到运行Scrapyd的服务器上,因此我有几个问题:

  • 这是我可以采取的最佳方法吗?
  • 如果是这样,如果我多次以不同的参数调度相同的Spider,是否存在并发问题?
  • 如果这不是最好的方法,更好的方法是为每个站点创建一个单独的Spider……我将经常更新项目。项目更新会影响正在运行的Spiders吗?
1个回答

6

爬虫设计

构建域名爬虫有两种方法:

  1. 将url列表作为参数发送给单个爬虫。
  2. 使用不同的start_url参数运行相同爬虫的多个实例。

第一种方法最直截了当且易于测试(可以使用scrapy crawl运行),在许多情况下都很好。

第二种方法使用起来不太方便,但编写代码更容易:

  1. 将url列表作为参数发送到单个爬虫中:
    • 最小的CPU占用:启动一个进程处理所有的urls
    • 用户友好:可以作为scrapy crawl或scrapyd运行
    • 调试较困难:没有域限制
  2. 每个start_url运行一个实例
    • 占用资源较大:为每个url启动1个专用进程
    • 不太用户友好:需要创建外部脚本来启动爬虫和提供url。
    • 调试较容易:编写代码以便每次只运行一个域

.

from urlparse import urlparse
...
class .....(Spider):
    def __init__(*args, *kwargs):
        ...
        self.start_urls = ....
        ...
        self.allowed_domains = map(lambda x: urlparse(x).netloc, self.start_urls)

我建议只有在你遇到编程挑战时才采用第二种方法。否则,出于简单性和可扩展性的考虑,请坚持选项1。
并发
您可以通过在settings.py中添加CONCURRENT_REQUESTS_BY_DOMAIN变量来控制并发。
项目更新
两种架构都只需要编写一个蜘蛛。您仅需实例化一次蜘蛛(选项1)或每个URL实例化一次(选项2)。您不需要编写多个蜘蛛。
FYI:更新项目不会影响正在运行的蜘蛛。

1
为什么第一个选项更好?我看不出有什么优势。关于项目更新,我会重新提出问题,然后自己回答。我想知道在 scrapyd 服务下运行 scrapy 爬虫是否会受到影响,如果我在它们运行时进行 scrapyd 部署。答案是不会,它们可以继续运行而没有进一步的问题。 - Bernardo Botella
1
我不能给你一个赞同的投票,因为我没有足够的声望。 - Bernardo Botella
感谢您的反馈。我相信我已经澄清了您所有的问题。您认为呢? - Frederic Bazin
我不理解第二个选项如何可能,因为爬虫使用蜘蛛类(而不是实例)来启动。所以你必须为想要爬取的每个域名都创建一个类。我知道这没有意义,但我找不到其他方法来做到这一点。 - Mr Alexander
@AlexPatchanka,Crawler实际上使用实例(parse方法等是实例方法,而不是类方法)。在单个进程中实例化多个蜘蛛还是在单独的进程中实例化多个蜘蛛是另一个挑战。 我认为你对成员变量allowed_domains感到困惑,它可以在运行时(基于输入)设置,而不是在源代码中设置。 - Frederic Bazin
@FredericBazin我如何在运行时设置allowed_domains而不是在源代码中? - Mr Alexander

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接