Skip to main content

常见做法

本节介绍使用Scrapy时的常见做法。这些是涵盖许多主题的东西,并且经常不属于任何其他特定部分。

从脚本运行Scrapy

您可以使用 API 从脚本运行Scrapy,而不是通过 scrapy crawl 运行Scrapy的典型方法。

记住,Scrapy是建立在Twisted异步网络库之上的,所以你需要在Twisted反应器中运行它。

你可以用来运行你的蜘蛛的第一个工具是 scrapy.crawler.CrawlerProcess。这个类将为您启动一个Twisted反应器,配置日志记录和设置关闭处理程序。这个类是所有Scrapy命令使用的类。

这里是一个例子,显示如何运行一个单一的蜘蛛。

import scrapy
from scrapy.crawler import CrawlerProcess

class MySpider(scrapy.Spider):
    # Your spider definition
    ...

process = CrawlerProcess({
    'USER_AGENT': 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)'
})

process.crawl(MySpider)
process.start() # the script will block here until the crawling is finished

请务必检查 CrawlerProcess 文档以熟悉其使用详细信息。

如果你在一个Scrapy项目中,还有一些额外的帮助程序可以用来在项目中导入这些组件。您可以自动将您的蜘蛛名称传送给 CrawlerProcess,然后使用 get_project_settings 通过您的项目设置获取 Settings 实例。

下面是一个如何做的工作示例,使用 testspiders 项目作为示例。

from scrapy.crawler import CrawlerProcess
from scrapy.utils.project import get_project_settings

process = CrawlerProcess(get_project_settings())

# 'followall' is the name of one of the spiders of the project.
process.crawl('followall', domain='scrapinghub.com')
process.start() # the script will block here until the crawling is finished

还有另一个Scrapy实用程序可以更好地控制抓取过程:scrapy.crawler.CrawlerRunner。这个类是一个薄包装器,封装了一些简单的帮助器来运行多个爬虫,但它不会以任何方式启动或干扰现有的反应器。

使用这个类,反应器应该在安排你的蜘蛛之后显式运行。如果您的应用程序已经在使用Twisted并且您想在同一个反应器中运行Scrapy,建议您使用 CrawlerRunner 而不是 CrawlerProcess

注意,你也必须在蜘蛛完成后自己关闭Twisted反应器。这可以通过向 CrawlerRunner.crawl 方法返回的延迟添加回调来实现。

这里有一个使用示例,以及在 MySpider 完成运行后手动停止反应器的回调。

from twisted.internet import reactor
import scrapy
from scrapy.crawler import CrawlerRunner
from scrapy.utils.log import configure_logging

class MySpider(scrapy.Spider):
    # Your spider definition
    ...

configure_logging({'LOG_FORMAT': '%(levelname)s: %(message)s'})
runner = CrawlerRunner()

d = runner.crawl(MySpider)
d.addBoth(lambda _: reactor.stop())
reactor.run() # the script will block here until the crawling is finished

在同一进程中运行多个蜘蛛程序

默认情况下,当您运行 scrapy crawl 时,Scrapy在每个进程上运行一个蜘蛛。但是,Scrapy支持使用 内部API 在每个进程上运行多个蜘蛛程序。

以下是同时运行多个蜘蛛的示例:

import scrapy
from scrapy.crawler import CrawlerProcess

class MySpider1(scrapy.Spider):
    # Your first spider definition
    ...

class MySpider2(scrapy.Spider):
    # Your second spider definition
    ...

process = CrawlerProcess()
process.crawl(MySpider1)
process.crawl(MySpider2)
process.start() # the script will block here until all crawling jobs are finished

使用 CrawlerRunner 的相同示例:

import scrapy
from twisted.internet import reactor
from scrapy.crawler import CrawlerRunner
from scrapy.utils.log import configure_logging

class MySpider1(scrapy.Spider):
    # Your first spider definition
    ...

class MySpider2(scrapy.Spider):
    # Your second spider definition
    ...

configure_logging()
runner = CrawlerRunner()
runner.crawl(MySpider1)
runner.crawl(MySpider2)
d = runner.join()
d.addBoth(lambda _: reactor.stop())

reactor.run() # the script will block here until all crawling jobs are finished

相同的示例,但通过链接延迟的顺序运行蜘蛛:

from twisted.internet import reactor, defer
from scrapy.crawler import CrawlerRunner
from scrapy.utils.log import configure_logging

class MySpider1(scrapy.Spider):
    # Your first spider definition
    ...

class MySpider2(scrapy.Spider):
    # Your second spider definition
    ...

configure_logging()
runner = CrawlerRunner()

@defer.inlineCallbacks
def crawl():
    yield runner.crawl(MySpider1)
    yield runner.crawl(MySpider2)
    reactor.stop()

crawl()
reactor.run() # the script will block here until the last crawl call is finished

分布式爬网

Scrapy不提供任何内置工具以分布(多服务器)方式运行爬网。但是,有一些分发抓取的方法,具体取决于您计划分发抓取的方式。

如果你有很多蜘蛛,分配负载的明显方法是设置许多Scrapyd实例并在其中分发蜘蛛程序。

如果你想要通过许多机器运行单个(大)蜘蛛,你通常做的是分割网址抓取并发送给每个单独的蜘蛛。这里有一个具体的例子:

首先,准备要爬网的网址列表,并将其放在单独的文件/网址中:

http://somedomain.com/urls-to-crawl/spider1/part1.list
http://somedomain.com/urls-to-crawl/spider1/part2.list
http://somedomain.com/urls-to-crawl/spider1/part3.list

然后你在3个不同的Scrapyd服务器上运行一个蜘蛛。蜘蛛会收到一个(蜘蛛)参数 part 与要抓取的分区的编号:

curl http://scrapy1.mycompany.com:6800/schedule.json -d project=myproject -d spider=spider1 -d part=1
curl http://scrapy2.mycompany.com:6800/schedule.json -d project=myproject -d spider=spider1 -d part=2
curl http://scrapy3.mycompany.com:6800/schedule.json -d project=myproject -d spider=spider1 -d part=3

避免被禁止

一些网站实施某些措施,以防止机器人爬行他们,具有不同程度的复杂性。实现这些措施可能是困难和棘手的,有时可能需要特殊的基础设施。如有疑问,请考虑与 commercial support 联系。

以下是处理这类网站时需要注意的一些提示:

  • 从浏览器中的一个知名的池中旋转您的用户代理(谷歌周围得到它们的列表)

  • 禁用cookie(请参阅 COOKIES_ENABLED),因为某些网站可能使用Cookie来发现bot行为

  • 使用下载延迟(2或更高版本)。请参阅 DOWNLOAD_DELAY 设置。

  • 如果可能,使用 Google cache 获取页面,而不是直接访问网站

  • 使用旋转IP池。例如,免费 Tor project 或付费服务,如 ProxyMesh。开源替代是 scrapoxy,一个超级代理,你可以附加你自己的代理。

  • 使用高度分布的下载程序,在内部规避禁止,所以你可以只关注解析干净的页面。这样的下载器的一个示例是 Crawlera

如果您仍然无法阻止您的漫游器被禁止,请考虑联系 commercial support