我有一个关于如何在scrapy中做这件事的问题。我有一只蜘蛛爬行列出物品页面。 每次找到具有项目的列表页面时,都会调用parse_item()回调来提取项目数据和产生项目。到目前为止,一切都很好。
但是每个项目,除其他数据外,还有一个网址,其中包含该项目的更多详细信息。我想跟随该URL并在另一个项目字段(url_contents)中存储该项目的URL的获取内容。
而且我不确定如何组织代码来实现这一点,因为两个链接(列表链接和一个特定的项链接)遵循不同的方式,在不同的时间调用回调,但我必须将它们关联在相同的项目处理。
到目前为止我的代码看起来像这样:
class MySpider(CrawlSpider):
name = "example.com"
allowed_domains = ["example.com"]
start_urls = [
"http://www.example.com/?q=example",
]
rules = (
Rule(SgmlLinkExtractor(allow=('example\.com', 'start='), deny=('sort='), restrict_xpaths = '//div[@class="pagination"]'), callback='parse_item'),
Rule(SgmlLinkExtractor(allow=('item\/detail', )), follow = False),
)
def parse_item(self, response):
main_selector = HtmlXPathSelector(response)
xpath = '//h2[@class="title"]'
sub_selectors = main_selector.select(xpath)
for sel in sub_selectors:
item = ExampleItem()
l = ExampleLoader(item = item, selector = sel)
l.add_xpath('title', 'a[@title]/@title')
......
yield l.load_item()
答案 0 :(得分:20)
经过一些测试和思考,我发现这个解决方案对我有用。 我们的想法是只使用第一条规则,它为您提供项目列表,同样非常重要的是,将follow = True添加到该规则中。
在parse_item()中,您必须生成请求而不是项目,但是在加载项目之后。请求是项目详细信息URL。并且您必须将加载的项目发送到该请求回调。你通过回应完成工作,并且你可以在那里产生物品。
所以parse_item()的结束将如下所示:
itemloaded = l.load_item()
# fill url contents
url = sel.select(item_url_xpath).extract()[0]
request = Request(url, callback = lambda r: self.parse_url_contents(r))
request.meta['item'] = itemloaded
yield request
然后parse_url_contents()将如下所示:
def parse_url_contents(self, response):
item = response.request.meta['item']
item['url_contents'] = response.body
yield item
如果有人有其他(更好)方法,请告诉我们。
的Stefan
答案 1 :(得分:1)
我遇到了完全相同的问题,并且事实上没有人在2天内回答了您的问题我认为唯一的解决方案就是从parse_item
内手动关注该网址功能。
我是Scrapy的新手,所以我不会尝试使用它(虽然我确信它是可能的),但我的解决方案是使用urllib
和BeatifulSoup手动加载第二页,我自己提取这些信息,并将其保存为项目的一部分。是的,比Scrapy进行正常解析要麻烦得多,但它应该以最少的麻烦完成工作。