【发布时间】:2017-10-28 22:59:08
【问题描述】:
让 Scrapy 按计划运行让我在 Twist(ed) 中四处奔波。
我认为下面的测试代码会起作用,但是当蜘蛛被第二次触发时,我得到一个twisted.internet.error.ReactorNotRestartable 错误:
from quotesbot.spiders.quotes import QuotesSpider
import schedule
import time
from scrapy.crawler import CrawlerProcess
def run_spider_script():
process.crawl(QuotesSpider)
process.start()
process = CrawlerProcess({
'USER_AGENT': 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)',
})
schedule.every(5).seconds.do(run_spider_script)
while True:
schedule.run_pending()
time.sleep(1)
我猜想,作为 CrawlerProcess 的一部分,Twisted Reactor 会被调用以重新启动,而这不是必需的,因此程序会崩溃。有什么办法可以控制吗?
此外,在这个阶段,如果有另一种方法可以使 Scrapy 蜘蛛按计划自动运行,我会全力以赴。我试过 scrapy.cmdline.execute ,但也无法让它循环:
from quotesbot.spiders.quotes import QuotesSpider
from scrapy import cmdline
import schedule
import time
from scrapy.crawler import CrawlerProcess
def run_spider_cmd():
print("Running spider")
cmdline.execute("scrapy crawl quotes".split())
process = CrawlerProcess({
'USER_AGENT': 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)',
})
schedule.every(5).seconds.do(run_spider_cmd)
while True:
schedule.run_pending()
time.sleep(1)
编辑
添加代码,它使用 Twisted task.LoopingCall() 每隔几秒运行一次测试蜘蛛。我是否完全错误地安排每天在同一时间运行的蜘蛛?
from twisted.internet import reactor
from twisted.internet import task
from scrapy.crawler import CrawlerRunner
import scrapy
class QuotesSpider(scrapy.Spider):
name = 'quotes'
allowed_domains = ['quotes.toscrape.com']
start_urls = ['http://quotes.toscrape.com/']
def parse(self, response):
quotes = response.xpath('//div[@class="quote"]')
for quote in quotes:
author = quote.xpath('.//small[@class="author"]/text()').extract_first()
text = quote.xpath('.//span[@class="text"]/text()').extract_first()
print(author, text)
def run_crawl():
runner = CrawlerRunner()
runner.crawl(QuotesSpider)
l = task.LoopingCall(run_crawl)
l.start(3)
reactor.run()
【问题讨论】:
-
为什么不简单地使用 cron 或 systemd 计时器?
-
网络抓取数据只是预期应用程序的一部分,我希望将所有内容作为单个程序的一部分运行。但是,是的,如果我不能按照描述的那样工作,我将使用 OS 任务调度程序来运行 Scrapy 脚本,其余的应用程序单独运行。
标签: python web-scraping scrapy twisted