我正在使用Scrapy爬网。
我有类似的代码:
class mySpider(scrapy.Spider):
def start_requests(self):
yield SplashRequest(url=example_url,
callback=self.parse,
cookies={'store_language':'en'},
endpoint='render.html',
args={'wait': 5},
)
def parse(self, response):
try:
self.extract_data_from_page(response)
if (next_link_still_on_page(response):
next_url = grok_next_url(response)
yield SplashRequest(url=next_url,
callback=self.parse,
cookies={'store_language':'en'},
endpoint='render.html',
args={'wait': 5},
)
except Exception:
pass
def extract_data_from_page(self, response):
pass
def next_link_still_on_page(self,response):
pass
def grok_next_url(self, response):
pass
在parse()
方法中,回调函数parse()
会被忽略(例如,导致潜在的堆栈溢出的逻辑错误?)。
答案 0 :(得分:0)
您可以使用相同的回调。从技术角度来看,这不是问题。尤其是如果产生的请求与当前请求具有相同的性质,那么理想情况下它应该重用相同的逻辑。
但是,从必须阅读源代码的人的角度来看,最好为不同任务或页面使用单独的解析器类型(整体单一责任原则)。
让我举例说明。假设您有一个列表网站(工作,产品或其他),并且有两个主要的URL类:
.../search?q=something&page=2
.../item/abc
搜索结果页面包含分页链接和项目。这样的页面会产生两种请求:
“项目”页面将不会产生其他请求。
因此,现在您 可以将所有这些填充到同一解析器中,并用于每个请求:
def parse(self, response):
if 'search' in response.url:
for item in response.css('.item'):
# ...
yield Request(item_url, callback=self.parse)
# ...
yield Request(next_url, callback=self.parse)
if 'item' in response.url:
yield {
'title': response.css('...'),
# ...
}
这显然是一个非常简洁的例子,但是随着它的增长,它将变得更加难以遵循。
相反,请分解不同的页面解析器:
def parse_search(self, response):
for item in response.css('.items'):
yield Request(item_url, callback=self.parse_item)
next_url = response.css('...').get()
yield Request(next_url, callback=self.parse_search)
def parse_item(self, response):
yield {
'title': response.css('...'),
# ...
}
因此,基本上,如果是“另一种相同类型的页面”的问题,那么使用相同的回调以便重用相同的逻辑是正常的。如果下一个请求需要另一种类型的解析,请创建一个单独的解析器。