首页 > 解决方案 > Scrapy Request 以某种方式切断 URL

问题描述

我喜欢抓取一个如下所示的网址: https ://steamcommunity.com/market/search?appid=730#p1_popular_desc

因为 End 是动态的,所以我在 parse 中创建 url 列表,然后进行请求循环。

问题是,他在 appid=730 之后剪切了 url - 所以每个 url 看起来都一样。如果我切换到 dont_filter=true,我会看到他在 page1 上一次又一次地循环。我没有得到问题:(

代码中的“x”稍后会变得动态(这就是需要 start_url),认为这与问题无关。

似乎他总是从引荐网址中抓取,而不是我给他的那个。网址可能不会以 730 结尾。

调试消息:

...

2019-03-28 23:44:36 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://steamcommunity.com/market/search?appid=730> (referer: None)

2019-03-28 23:44:37 [scrapy.core.engine] DEBUG: Crawled (200) **<GET https://steamcommunity.com/market/search?appid=730#p7_popular_desc> (referer: https://steamcommunity.com/market/search?appid=730)**

...

2019-03-28 23:44:37 [scrapy.core.scraper] DEBUG: Scraped from <200 https://steamcommunity.com/market/search?appid=730>
{'item_count': u'7,899',
 'item_name': u'Prisma Case',
 'item_price': u'$2.79 USD',
 'item_subtext': u'Counter-Strike: Global Offensive'}
2019-03-28 23:44:37 [scrapy.core.scraper] DEBUG: **Scraped from <200 https://steamcommunity.com/market/search?appid=730>**
{'item_count': u'192,519',
 'item_name': u'Danger Zone Case',
 'item_price': u'$0.30 USD',
 'item_subtext': u'Counter-Strike: Global Offensive'}

allowed_domains = ['steamcommunity.com/market']
start_urls = ['https://steamcommunity.com/market/search?appid=730']

def parse(self, response):
    x = 15 
    steam_xpath = [u'//steamcommunity.com/market/search?appid=730#p'+str(i)+'_popular_desc' for i in range(1, x)]
    for link in steam_xpath:
        yield Request(response.urljoin(link), self.parse_steam, dont_filter=True)

def parse_steam(self, response):
    xitem_name = response.xpath('//span[@class="market_listing_item_name"]/text()').extract()
    xitem_price = response.xpath('//span[@class="normal_price"]/text()').extract()
    xitem_subtext = response.xpath('//span[@class="market_listing_game_name"]/text()').extract()
    xitem_count = response.xpath('//span[@class="market_listing_num_listings_qty"]/text()').extract()
    for item in zip(xitem_name, xitem_price, xitem_subtext, xitem_count):
        new_item = SteammarketItem()
        new_item['item_name'] = item[0]
        new_item['item_price'] = item[1]
        new_item['item_subtext'] = item[2]
        new_item['item_count'] = item[3]
        yield new_item

预期:150 个结果,循环中每个 url 10 个。

实际:15 个结果,但每个 10 次 - 全部来自第一个 url。

标签: pythonscrapy

解决方案


地址栏上的 URL 如您所说,但如果您检查浏览器开发人员工具的网络选项卡上的请求,您将看到返回新项目的请求是这样的:

https://steamcommunity.com/market/search/render/?query=&start=0&count=10&search_descriptions=0&sort_column=popular&sort_dir=desc&appid=730

此 Json 包含字段上的页面 HTML,results_html如果您想使用 xpath 获取数据,可以使用此值创建一个选择器。

import json

def parse(self, response):
    data = json.loads(response.text)
    sel = scrapy.Selector(text=data['results_html'])
    # then use sel
    value = sel.xpath('//value').get()

阅读此 URL 的响应,您还可以注意到有一种tip说法,即也可以&norender=1在 URL 中添加一个参数,并且根本不使用 HTML。因此,您可以选择最适合自己的方式。

许多网站都这样做,因此您必须密切关注请求,并且不要总是相信地址栏上显示的内容。我建议您永远不要相信“检查器”上出现的内容,并始终检查源代码(右键单击>查看页面源代码)。


推荐阅读