【问题标题】:Scraping a JSON response with Scrapy使用 Scrapy 抓取 JSON 响应
【发布时间】:2013-08-12 20:52:46
【问题描述】:

如何使用 Scrapy 抓取返回 JSON 的 Web 请求?例如,JSON 看起来像这样:

{
    "firstName": "John",
    "lastName": "Smith",
    "age": 25,
    "address": {
        "streetAddress": "21 2nd Street",
        "city": "New York",
        "state": "NY",
        "postalCode": "10021"
    },
    "phoneNumber": [
        {
            "type": "home",
            "number": "212 555-1234"
        },
        {
            "type": "fax",
            "number": "646 555-4567"
        }
    ]
}

我希望抓取特定项目(例如上面的 namefax)并保存到 csv。

【问题讨论】:

    标签: python json web-scraping scrapy


    【解决方案1】:

    这与使用 Scrapy 的 HtmlXPathSelector 进行 html 响应相同。唯一的区别是您应该使用json 模块来解析响应:

    class MySpider(BaseSpider):
        ...
    
    
        def parse(self, response):
             jsonresponse = json.loads(response.text)
    
             item = MyItem()
             item["firstName"] = jsonresponse["firstName"]             
    
             return item
    

    希望对您有所帮助。

    【讨论】:

    • 您可能希望使用json.loads(response.body_as_unicode()),因为加载需要strunicode 对象,而不是scrapy 响应。
    • 伙计们,现在您已经解析了一个 json 响应。我将如何跟踪可能在 json 中的每个链接?
    • @Cmag 你需要returnyield 一个Request,查看更多信息here
    • 使用ujson会更有效
    • response.text 优于 body_as_unicode(),见doc.scrapy.org/en/latest/topics/…
    【解决方案2】:

    JSON 未加载的可能原因是它前后都有单引号。试试这个:

    json.loads(response.body_as_unicode().replace("'", '"'))
    

    【讨论】:

    • 也可以是一个奇怪的json,例如用不必要的括号,然后使用:json.loads(response.body_as_unicode().strip('()')).
    【解决方案3】:

    不需要使用json模块解析reponse对象。

    class MySpider(BaseSpider):
    ...
    
    
    def parse(self, response):
         jsonresponse = response.json()
    
         item = MyItem()
         item["firstName"] = jsonresponse.get("firstName", "")           
    
         return item
    

    【讨论】:

    • 我认为作为对已接受答案的评论会更好。
    • 我需要“50 声望”才能发表评论,所以我不能。