如何组织多个Scrapy Spiders并在它们之间传递数据?
How to organize multiple Scrapy Spiders and pass data between them?
我有一个问题阻止我推进我的项目。
我会尽量解释清楚,但我对抓取还比较陌生。
我想从网站 A 抓取文章。
网站 A 在其 HTML 代码中没有文章内容,但链接到其他网站(比如说网站 B 和网站 C)上的文章
我创建了一个从网站 A 提取链接并以 JSON 格式生成它们的蜘蛛。
我想从网站 A 提取链接并从网站 B 和 C 抓取文章。
现在 - 我想为网站 B 和网站 C 创建单独的蜘蛛(稍后使用它们直接抓取这些网站而不是通过网站 A)并以某种方式将从网站 A 抓取的数据作为参数传递给它们 - 但是“不知何故”部分是我需要你的帮助。
谢谢:)
编辑
Anwsering jqc - 因为我发布了我的问题,所以我做了一些开发 - 这是我到目前为止的代码。
class QuotesSpider(scrapy.Spider):
name = 'Website A Spider'
start_urls = ['start_url']
def parse(self, response):
self.logger.info('###### Link Parser ######')
important_news = response.xpath('//div[contains(@class, "importantNews")]//div[contains(@class, "items")]/a')
for news in important_news:
yield {
'link': news.xpath('./@href').get(),
'title': news.xpath('.//span[contains(@class, "title")]/text()').get()
}
article_url = news.xpath('./@href').get()
self.logger.info('FOLLOWING URL OF THE ARTICLE')
if 'Website B' in article_url:
yield response.follow(article_url, callback=self.parse_Website_B)
else:
pass
def parse_Website_B(self, response):
yield {
'Website B article title': response.xpath('//p[contains(@class, "Header_desktopTextElement")]').get()
}
不用担心未完成的解析,这是最不重要的部分:)
现在我正在创建单独的方法来解析特定网站,但我不知道这是否是最佳方法。
我想查看您正在尝试抓取的 URL。然后我可以做一些测试并尝试破译你的问题。
我可以给你一些提示,我不确定我是否理解你。
如果你想从 A 中抓取给定的 URLs,你可以直接这样做:
def parse_Website_B(self, response):
yield {
'Website B article title': response.xpath('//p[contains(@class, "Header_desktopTextElement")]').get()
}
您只需提供链接,我会尝试使用 start_requests。查看文档 here.
如果您提供 URL,我们可以尝试其他方式。
干杯
我认为在您的情况下,在 spyder 文件中创建一个 URL 列表作为全局变量会容易得多,然后将其用作请求列表。
像这样:
from twisted.internet import reactor, defer
from scrapy.crawler import CrawlerRunner
from scrapy.utils.log import configure_logging
from scrapy import signals
URL_LIST = []
DATA_LIST = []
def store_url(*args, **kwargs):
URL_LIST.append(kwargs['item'])
def store_data(*args, **kwargs):
DATA_LIST.append(kwargs['item'])
class QuotesSpiderWebsiteA(scrapy.Spider):
#Your code
class QuotesSpiderWebsiteB(scrapy.Spider):
# etc...
if __name__ == '__main__':
configure_logging()
runner = CrawlerRunner()
@defer.inlineCallbacks
def crawl():
crawler1 = runner.create_crawler(QuotesSpiderWebsiteA)
crawler2 = runner.create_crawler(QuotesSpiderWebsiteB)
crawler1.signals.connect(store_url, signals.item_scraped)
crawler2.signals.connect(store_data, signals.item_scraped)
yield runner.crawl(crawler1)
yield runner.crawl(crawler2)
reactor.stop()
crawl()
reactor.run()
# the script will block here until the crawling is finished
with open('output.json', 'w', encoding='utf8') as f:
json.dump(DATA_LIST)
我有一个问题阻止我推进我的项目。 我会尽量解释清楚,但我对抓取还比较陌生。
我想从网站 A 抓取文章。
网站 A 在其 HTML 代码中没有文章内容,但链接到其他网站(比如说网站 B 和网站 C)上的文章
我创建了一个从网站 A 提取链接并以 JSON 格式生成它们的蜘蛛。
我想从网站 A 提取链接并从网站 B 和 C 抓取文章。
现在 - 我想为网站 B 和网站 C 创建单独的蜘蛛(稍后使用它们直接抓取这些网站而不是通过网站 A)并以某种方式将从网站 A 抓取的数据作为参数传递给它们 - 但是“不知何故”部分是我需要你的帮助。
谢谢:)
编辑
Anwsering jqc - 因为我发布了我的问题,所以我做了一些开发 - 这是我到目前为止的代码。
class QuotesSpider(scrapy.Spider):
name = 'Website A Spider'
start_urls = ['start_url']
def parse(self, response):
self.logger.info('###### Link Parser ######')
important_news = response.xpath('//div[contains(@class, "importantNews")]//div[contains(@class, "items")]/a')
for news in important_news:
yield {
'link': news.xpath('./@href').get(),
'title': news.xpath('.//span[contains(@class, "title")]/text()').get()
}
article_url = news.xpath('./@href').get()
self.logger.info('FOLLOWING URL OF THE ARTICLE')
if 'Website B' in article_url:
yield response.follow(article_url, callback=self.parse_Website_B)
else:
pass
def parse_Website_B(self, response):
yield {
'Website B article title': response.xpath('//p[contains(@class, "Header_desktopTextElement")]').get()
}
不用担心未完成的解析,这是最不重要的部分:)
现在我正在创建单独的方法来解析特定网站,但我不知道这是否是最佳方法。
我想查看您正在尝试抓取的 URL。然后我可以做一些测试并尝试破译你的问题。 我可以给你一些提示,我不确定我是否理解你。 如果你想从 A 中抓取给定的 URLs,你可以直接这样做:
def parse_Website_B(self, response):
yield {
'Website B article title': response.xpath('//p[contains(@class, "Header_desktopTextElement")]').get()
}
您只需提供链接,我会尝试使用 start_requests。查看文档 here.
如果您提供 URL,我们可以尝试其他方式。
干杯
我认为在您的情况下,在 spyder 文件中创建一个 URL 列表作为全局变量会容易得多,然后将其用作请求列表。
像这样:
from twisted.internet import reactor, defer
from scrapy.crawler import CrawlerRunner
from scrapy.utils.log import configure_logging
from scrapy import signals
URL_LIST = []
DATA_LIST = []
def store_url(*args, **kwargs):
URL_LIST.append(kwargs['item'])
def store_data(*args, **kwargs):
DATA_LIST.append(kwargs['item'])
class QuotesSpiderWebsiteA(scrapy.Spider):
#Your code
class QuotesSpiderWebsiteB(scrapy.Spider):
# etc...
if __name__ == '__main__':
configure_logging()
runner = CrawlerRunner()
@defer.inlineCallbacks
def crawl():
crawler1 = runner.create_crawler(QuotesSpiderWebsiteA)
crawler2 = runner.create_crawler(QuotesSpiderWebsiteB)
crawler1.signals.connect(store_url, signals.item_scraped)
crawler2.signals.connect(store_data, signals.item_scraped)
yield runner.crawl(crawler1)
yield runner.crawl(crawler2)
reactor.stop()
crawl()
reactor.run()
# the script will block here until the crawling is finished
with open('output.json', 'w', encoding='utf8') as f:
json.dump(DATA_LIST)