【问题标题】:Scrapy Scraper IssueScrapy Scraper 问题
【发布时间】:2015-09-22 12:54:13
【问题描述】:

我正在尝试使用 Scrapy 来抓取 - www.paytm.com 。该网站使用 AJAX 请求,以 XHR 的形式显示搜索结果。

我设法找到了 XHR,AJAX 响应类似于 JSON,但它实际上不是 JSON。

这是 XHR 请求之一的链接 - https://search.paytm.com/search/?page_count=2&userQuery=tv&items_per_page=30&resolution=960x720&quality=high&q=tv&cat_tree=1&callback=angular.callbacks._6 。如果你看到的 URL 正确,参数 - page_count - 负责显示不同页面的结果,参数 - userQuery - 负责传递的搜索查询到网站。

现在,如果您看到正确的响应。它实际上不是 JSON,只是看起来类似于 JSON(我在 http://jsonlint.com/ 上验证了它)。我想使用 SCRAPY ( SCRAPY 只是因为它是一个框架,它会比使用其他库(如 BeautifulSoup)更快,因为使用它们来创建一个以如此高的速度进行抓取的刮板需要很多努力- 这就是我想使用 Scrapy 的唯一原因。)

现在,这是我的 sn-p 代码,用于从 URL 中提取 JSON 响应 -:

    jsonresponse = json.loads(response.body_as_unicode())
    print json.dumps(jsonresponse, indent=4, sort_keys=True)

在执行代码时,它会向我抛出一个错误说明-:

2015-07-05 12:13:23 [scrapy] INFO: Scrapy 1.0.0 started (bot: scrapybot)
2015-07-05 12:13:23 [scrapy] INFO: Optional features available: ssl, http11
2015-07-05 12:13:23 [scrapy] INFO: Overridden settings: {'DEPTH_PRIORITY': 1, 'SCHEDULER_MEMORY_QUEUE': 'scrapy.squeues.FifoMemoryQueue', 'SCHEDULER_DISK_QUEUE': 'scrapy.squeues.PickleFifoDiskQueue', 'CONCURRENT_REQUESTS': 100}
2015-07-05 12:13:23 [scrapy] INFO: Enabled extensions: CloseSpider, TelnetConsole, LogStats, CoreStats, SpiderState
2015-07-05 12:13:23 [scrapy] INFO: Enabled downloader middlewares: HttpAuthMiddleware, DownloadTimeoutMiddleware, UserAgentMiddleware, RetryMiddleware, DefaultHeadersMiddleware, MetaRefreshMiddleware, HttpCompressionMiddleware, RedirectMiddleware, CookiesMiddleware, ChunkedTransferMiddleware, DownloaderStats
2015-07-05 12:13:23 [scrapy] INFO: Enabled spider middlewares: HttpErrorMiddleware, OffsiteMiddleware, RefererMiddleware, UrlLengthMiddleware, DepthMiddleware
2015-07-05 12:13:23 [scrapy] INFO: Enabled item pipelines: 
2015-07-05 12:13:23 [scrapy] INFO: Spider opened
2015-07-05 12:13:23 [scrapy] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min)
2015-07-05 12:13:23 [scrapy] DEBUG: Telnet console listening on 127.0.0.1:6023
2015-07-05 12:13:24 [scrapy] DEBUG: Crawled (200) <GET https://search.paytm.com/search/?page_count=2&userQuery=tv&items_per_page=30&resolution=960x720&quality=high&q=tv&cat_tree=1&callback=angular.callbacks._6> (referer: None)
2015-07-05 12:13:24 [scrapy] ERROR: Spider error processing <GET https://search.paytm.com/search/?page_count=2&userQuery=tv&items_per_page=30&resolution=960x720&quality=high&q=tv&cat_tree=1&callback=angular.callbacks._6> (referer: None)
Traceback (most recent call last):
  File "/usr/lib/python2.7/dist-packages/twisted/internet/defer.py", line 577, in _runCallbacks
    current.result = callback(current.result, *args, **kw)
  File "Startup App/SCRAPERS/paytmscraper_scrapy/paytmspiderscript.py", line 111, in parse
    jsonresponse = json.loads(response.body_as_unicode())
  File "/usr/lib/python2.7/json/__init__.py", line 338, in loads
    return _default_decoder.decode(s)
  File "/usr/lib/python2.7/json/decoder.py", line 366, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/lib/python2.7/json/decoder.py", line 384, in raw_decode
    raise ValueError("No JSON object could be decoded")
ValueError: No JSON object could be decoded
2015-07-05 12:13:24 [scrapy] INFO: Closing spider (finished)
2015-07-05 12:13:24 [scrapy] INFO: Dumping Scrapy stats:
{'downloader/request_bytes': 343,
 'downloader/request_count': 1,
 'downloader/request_method_count/GET': 1,
 'downloader/response_bytes': 6483,
 'downloader/response_count': 1,
 'downloader/response_status_count/200': 1,
 'finish_reason': 'finished',
 'finish_time': datetime.datetime(2015, 7, 5, 6, 43, 24, 733187),
 'log_count/DEBUG': 2,
 'log_count/ERROR': 1,
 'log_count/INFO': 7,
 'response_received_count': 1,
 'scheduler/dequeued': 1,
 'scheduler/dequeued/memory': 1,
 'scheduler/enqueued': 1,
 'scheduler/enqueued/memory': 1,
 'spider_exceptions/ValueError': 1,
 'start_time': datetime.datetime(2015, 7, 5, 6, 43, 23, 908135)}
2015-07-05 12:13:24 [scrapy] INFO: Spider closed (finished)

现在,我的问题是,如何使用 Scrapy 抓取这样的回复?如果需要任何其他代码,请随时在 cmets 中询问。我会心甘情愿地给的!

请提供与此相关的完整代码。将不胜感激!也许对 JSON 响应(来自 python)(类似于字符串比较)的一些操作也对我有用,如果它可以帮助我刮掉这个!

P.S:我不能每次都手动(用手)修改 JSON 响应,因为这是网站给出的响应。所以,请建议一种程序化(pythonic)方式来做到这一点。最好,我想使用 Scrapy 作为我的框架。

【问题讨论】:

    标签: python ajax json web-scraping scrapy


    【解决方案1】:

    如果您查看非 JSON 结果,很明显它包含 JSON。

    如果您从响应中删除 typeof angular.callbacks._6 === "function" &amp;&amp; angular.callbacks._6( 初始部分和最后的 );,您将获得一个有效的 JSON,您可以使用 JSONLint 对其进行验证。

    最终解决方案是在响应中分别找到{} 的第一个和最后一个出现并提取其中的文本(包括那些大括号)并将其与json.loads 一起使用而不是整个结果。

    【讨论】:

    • 不必手动提取 JSON。只需从请求中删除&amp;callback=angular.callbacks._6
    【解决方案2】:

    Paytm提供json数据,请查看

    https://catalog.paytm.com/v1//g/electronics/mobile-accessories/mobiles

    目录页面返回.json数据,包括产品名称、产品url、报价、实际价格和图片数据等。

    如何获取某个类别的数据:

    在上面的url中可以看到catalog.paytm.com/v1//g/,它对所有url都是通用的,你需要将url的其他部分替换成以下格式。

    菜单项 > 类别 > 子类别。

    其中 Electronics 是菜单项,mobile-accessories 是类别,mobiles 是移动配件的子类别。

    当你运行上述格式的url时,paytm会返回json数据,你可以通过以下参数查询paytm更多页面。

    page_count 和 items_per_count

    示例:catalog.paytm.com/v1//g/electronics/mobile-accessories/mobiles?page_count=2&items_per_count=30

    在json数据中搜索grid_layout,如果不可用页面没有商品,可以跳出循环,否则处理json数据并读取商品详情。

    【讨论】:

      【解决方案3】:

      变化:

      https://search.paytm.com/search/?page_count=2&userQuery=tv&items_per_page=30&resolution=960x720&quality=high&q=tv&cat_tree=1&callback=angular.callbacks._6
      

      到:

      https://search.paytm.com/search/?page_count=2&userQuery=tv&items_per_page=30&resolution=960x720&quality=high&q=tv&cat_tree=1
      

      .. 你有 JSON。

      【讨论】:

        猜你喜欢
        • 2013-03-05
        • 2015-02-08
        • 2019-04-05
        • 1970-01-01
        • 2011-02-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多