【问题标题】:Scrapy crawled pages, but scraped 0 itemsScrapy 抓取了页面,但抓取了 0 个项目
【发布时间】:2016-10-18 09:35:28
【问题描述】:

我对 Python、Scrapy 和这个板子还很陌生,所以请多多包涵,因为我试图说明我的问题。

我的目标是在 Scrapy 的帮助下,在特定日期(例如参见预定义的 start_url)在 booking.com 上收集柏林所有可用酒店的名称(可能还有价格)。

我认为关键部分是:

  1. 我想对所有下一页进行分页,直到最后。
  2. 在每一页我想收集每家酒店的名字,名字应该分别保存。

如果我为下面的代码运行“scrapy runspider bookingspider.py -o items.csv -t csv”,终端会显示它爬过所有可用页面,但最后我只得到一个空 items.csv .

第 1 步似乎有效,因为终端显示正在抓取后续网址(例如 [...]offset=15,然后 [...]offset=30)。因此,我认为我的问题是第 2 步。 对于第 2 步,需要定义一个容器或块,其中每个酒店信息是单独包含的,可以作为循环的基础,对吗? 我选择了“div class="sr_item_content sr_item_content_slider_wrapper"”,因为每个酒店街区都有这个元素处于上级,但我真的不确定这部分。也许必须考虑更高的层次 (但我应该采用哪个元素,因为它们在酒店街区中不一样?)。 无论如何,基于此,我找出了元素的剩余 XPath,其中包含酒店名称。

我遵循了两个设置相似的教程(尽管网站不同),但不知何故它在这里不起作用。

也许您有一个想法,非常感谢您的每一个帮助。谢谢!

from scrapy.spiders import CrawlSpider
from scrapy.selector import Selector
from scrapy.item import Item, Field
from scrapy.http.request import Request

class HotelItem(Item):
    title = Field()
    price = Field()

class BookingCrawler(CrawlSpider):
    name = 'booking_crawler'
    allowed_domains = ['booking.com']
    start_urls = ['http://www.booking.com/searchresults.html?checkin_monthday=25;checkin_year_month=2016-10;checkout_monthday=26;checkout_year_month=2016-10;class_interval=1;dest_id=-1746443;dest_type=city;offset=0;sb_travel_purpose=leisure;si=ai%2Cco%2Cci%2Cre%2Cdi;src=index;ss=Berlin']
    custom_settings = {
        'BOT_NAME': 'booking-scraper',
        }

    def parse(self, response):
        s = Selector(response)
        index_pages = s.xpath('//div[@class="results-paging"]/a/@href').extract()
        if index_pages:
            for page in index_pages:
                yield Request(response.urljoin(page), self.parse)

        hotels = s.xpath('//div[@class="sr_item_content sr_item_content_slider_wrapper"]') 
        items = []
        for hotel in hotels:
            item = HotelItem()
            item['title'] = hotel.xpath('div[1]/div[1]/h3/a/span/text()').extract()[0]
            item['price'] = hotel.xpath('//div[@class="sr-prc--num sr-prc--final"]/text()').extract()[0]
            items.append(item)

        for item in items:
            yield item

【问题讨论】:

  • 尝试在其中输入self.logger.debug(hotels)。这可能是空的,这意味着您需要修改相应的 XPath 表达式。记得检查网页的内容(而不是你在浏览器中检查看到的 DOM,在 Firefox 中你可以使用 Ctrl+U 检查实际的 HTML 内容)

标签: python web-scraping scrapy web-crawler


【解决方案1】:

我认为问题可能出在您的XPath 这一行:

hotels = s.xpath('//div[@class="sr_item_content sr_item_content_slider_wrapper"]')

this SO question看来,您需要定义更多类似以下内容的内容:

//div[contains(@class, 'sr_item_content') and contains(@class, 'sr_item_content_slider_wrapper')]

为了帮助您进一步调试,您可以先尝试输出index_pages 的内容,看看它是否确实返回了您在该级别所期望的内容。

另外,检查Xpath Visualiser(问题中也提到),它可以帮助构建 Xpath。

【讨论】:

  • 非常感谢。我现在使用 "hotels = s.xpath('//div[contains(@class, "sr_item_new")]')",因为它介绍了每个酒店街区。它会有所帮助,因为终端会为每个已爬网页面显示更多内容,但现在它会为每个已爬网页面返回“IndexError:列表索引超出范围”。你有想法吗?顺便说一句,我尝试了 XPath Visualizer,它似乎无法处理预订 xml,因为它一次又一次地崩溃。
  • @MaikDrop 不用担心!我猜想item['title'] = hotel.xpath('div[1]/div[1]/h3/a/span/text()').extract()[0] item['price'] = hotel.xpath('//div[@class="sr-prc--num sr-prc--final"]/text()').extract()[0] 线上的数组可能是空的。您是否还更新了这些行的代码?如果这篇文章解决了您的问题,您应该将其标记为答案,那么也许您可以为下一个问题创建一个新问题
  • 是的,我做到了,例如item['title'] = hotel.xpath('div[2]/div[1]/div[1]/h3/a/span/text()').extract()[0]。尽管如此,它还是行不通。基本上我现在遇到了同样的问题,它会抓取,但收集了 0 个项目,现在每个爬网页面都有一个错误。我的错误是什么?基于酒店路径,我使用元素的剩余 XPath。谢谢。
  • @MaikDrop 你能在运行item['title'] 命令之前检查hotels 的内容吗?在尝试将其取出之前,了解它是否具有正确的数据是值得的。如果没有这些信息,很难为您提供帮助 - 我建议使用 hotels 的输出来编辑您的问题,或者如果 hotels xpath 也返回错误,您应该发布该错误!
猜你喜欢
  • 1970-01-01
  • 2018-09-22
  • 2023-02-15
  • 2018-09-17
  • 1970-01-01
  • 1970-01-01
  • 2021-12-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多