如何在Scrapy CrawlSpider中找到当前的start_url?
How to find the current start_url in Scrapy CrawlSpider?
当 运行 从自己的脚本中提取 URLs 从数据库加载并跟踪这些网站上的所有内部链接时,我遇到了一个遗憾。我需要知道当前使用的是哪个 start_url,因为我必须保持与数据库 (SQL DB) 的一致性。但是:当 Scrapy 使用名为 'start_urls' 的内置列表来接收要跟踪的链接列表并且这些网站有立即重定向时,就会出现问题。例如,当Scrapy启动并正在抓取start_url时,爬虫会跟踪在那里找到的所有内部链接,我后来只能确定当前访问的URL,而不是start_url Scrapy 开始的地方。
网络上的其他答案是错误的,对于其他用例或已弃用,因为去年 Scrapy 的代码似乎发生了变化。
MWE:
from scrapy.spiders import CrawlSpider, Rule
from scrapy.linkextractors import LinkExtractor
from scrapy.crawler import CrawlerProcess
class CustomerSpider(CrawlSpider):
name = "my_crawler"
rules = [Rule(LinkExtractor(unique=True), callback="parse_obj", ), ]
def parse_obj(self, response):
print(response.url) # find current start_url and do something
a = CustomerSpider
a.start_urls = ["https://upb.de", "https://spiegel.de"] # I want to re-identify upb.de in the crawling process in process.crawl(a), but it is redirected immediately # I have to hand over the start_urls this way, as I use the class CustomerSpider in another class
a.allowed_domains = ["upb.de", "spiegel.de"]
process = CrawlerProcess()
process.crawl(a)
process.start()
在这里,我提供了一个 MWE,其中 Scrapy(我的爬虫)收到一个 URLs 的列表,就像我必须做的那样。重定向示例 - url 是 https://upb.de which redirects to https://uni-paderborn.de.
我正在寻找一种优雅的方式来处理这个问题,因为我想利用 Scrapy 的众多功能,例如并行爬行等。因此,我不想另外使用请求库之类的东西。我想找到目前内部使用的 Scrapy start_url(在 Scrapy 库中)。
感谢您的帮助。
理想情况下,您可以在原始请求上设置 meta
属性,稍后在回调中引用它。不幸的是,CrawlSpider
不支持通过 Rule
传递 meta
(参见 #929)。
您最好构建自己的蜘蛛,而不是子类化 CrawlSpider
。首先将您的 start_urls
作为参数传递给 process.crawl
,这使其在实例上可用作 属性。在 start_requests
方法中,为每个 url 生成一个新的 Request
,包括作为 meta
值的数据库键。
当 parse
收到加载您的 url 的响应时,运行 在其上 LinkExtractor
,并产生一个请求,让每个人单独抓取它。在这里,您可以再次传递 meta
,将原始数据库密钥传播到链中。
代码如下所示:
from scrapy.spiders import Spider
from scrapy import Request
from scrapy.linkextractors import LinkExtractor
from scrapy.crawler import CrawlerProcess
class CustomerSpider(Spider):
name = 'my_crawler'
def start_requests(self):
for url in self.root_urls:
yield Request(url, meta={'root_url': url})
def parse(self, response):
links = LinkExtractor(unique=True).extract_links(response)
for link in links:
yield Request(
link.url, callback=self.process_link, meta=response.meta)
def process_link(self, response):
print {
'root_url': response.meta['root_url'],
'resolved_url': response.url
}
a = CustomerSpider
a.allowed_domains = ['upb.de', 'spiegel.de']
process = CrawlerProcess()
process.crawl(a, root_urls=['https://upb.de', 'https://spiegel.de'])
process.start()
# {'root_url': 'https://spiegel.de', 'resolved_url': 'http://www.spiegel.de/video/'}
# {'root_url': 'https://spiegel.de', 'resolved_url': 'http://www.spiegel.de/netzwelt/netzpolitik/'}
# {'root_url': 'https://spiegel.de', 'resolved_url': 'http://www.spiegel.de/thema/buchrezensionen/'}
当 运行 从自己的脚本中提取 URLs 从数据库加载并跟踪这些网站上的所有内部链接时,我遇到了一个遗憾。我需要知道当前使用的是哪个 start_url,因为我必须保持与数据库 (SQL DB) 的一致性。但是:当 Scrapy 使用名为 'start_urls' 的内置列表来接收要跟踪的链接列表并且这些网站有立即重定向时,就会出现问题。例如,当Scrapy启动并正在抓取start_url时,爬虫会跟踪在那里找到的所有内部链接,我后来只能确定当前访问的URL,而不是start_url Scrapy 开始的地方。
网络上的其他答案是错误的,对于其他用例或已弃用,因为去年 Scrapy 的代码似乎发生了变化。
MWE:
from scrapy.spiders import CrawlSpider, Rule
from scrapy.linkextractors import LinkExtractor
from scrapy.crawler import CrawlerProcess
class CustomerSpider(CrawlSpider):
name = "my_crawler"
rules = [Rule(LinkExtractor(unique=True), callback="parse_obj", ), ]
def parse_obj(self, response):
print(response.url) # find current start_url and do something
a = CustomerSpider
a.start_urls = ["https://upb.de", "https://spiegel.de"] # I want to re-identify upb.de in the crawling process in process.crawl(a), but it is redirected immediately # I have to hand over the start_urls this way, as I use the class CustomerSpider in another class
a.allowed_domains = ["upb.de", "spiegel.de"]
process = CrawlerProcess()
process.crawl(a)
process.start()
在这里,我提供了一个 MWE,其中 Scrapy(我的爬虫)收到一个 URLs 的列表,就像我必须做的那样。重定向示例 - url 是 https://upb.de which redirects to https://uni-paderborn.de.
我正在寻找一种优雅的方式来处理这个问题,因为我想利用 Scrapy 的众多功能,例如并行爬行等。因此,我不想另外使用请求库之类的东西。我想找到目前内部使用的 Scrapy start_url(在 Scrapy 库中)。 感谢您的帮助。
理想情况下,您可以在原始请求上设置 meta
属性,稍后在回调中引用它。不幸的是,CrawlSpider
不支持通过 Rule
传递 meta
(参见 #929)。
您最好构建自己的蜘蛛,而不是子类化 CrawlSpider
。首先将您的 start_urls
作为参数传递给 process.crawl
,这使其在实例上可用作 属性。在 start_requests
方法中,为每个 url 生成一个新的 Request
,包括作为 meta
值的数据库键。
当 parse
收到加载您的 url 的响应时,运行 在其上 LinkExtractor
,并产生一个请求,让每个人单独抓取它。在这里,您可以再次传递 meta
,将原始数据库密钥传播到链中。
代码如下所示:
from scrapy.spiders import Spider
from scrapy import Request
from scrapy.linkextractors import LinkExtractor
from scrapy.crawler import CrawlerProcess
class CustomerSpider(Spider):
name = 'my_crawler'
def start_requests(self):
for url in self.root_urls:
yield Request(url, meta={'root_url': url})
def parse(self, response):
links = LinkExtractor(unique=True).extract_links(response)
for link in links:
yield Request(
link.url, callback=self.process_link, meta=response.meta)
def process_link(self, response):
print {
'root_url': response.meta['root_url'],
'resolved_url': response.url
}
a = CustomerSpider
a.allowed_domains = ['upb.de', 'spiegel.de']
process = CrawlerProcess()
process.crawl(a, root_urls=['https://upb.de', 'https://spiegel.de'])
process.start()
# {'root_url': 'https://spiegel.de', 'resolved_url': 'http://www.spiegel.de/video/'}
# {'root_url': 'https://spiegel.de', 'resolved_url': 'http://www.spiegel.de/netzwelt/netzpolitik/'}
# {'root_url': 'https://spiegel.de', 'resolved_url': 'http://www.spiegel.de/thema/buchrezensionen/'}