【问题标题】:Decoding HTML character entities in JSON在 JSON 中解码 HTML 字符实体
【发布时间】:2016-06-18 23:03:32
【问题描述】:

当我这样做时:

s = response.xpath('//meta[@id="_bootstrap-neighborhood_card"]').extract()

我得到的是:

<meta content='{"hosting":{"id":2256573,"offset_lat":39.04258923718809,"offset_lng":-95.69083697887662},"map_url":"https://maps.googleapis.com/maps/api/staticmap?markers=%2C&size&zoom=14","place_recommendations":[],"neighborhood_breadcrumb_details":[{"link_text":"Southwest Fillmore Street,","search_text":"Southwest Fillmore Street Topeka, KS","link":"<span>Southwest Fillmore Street,</span>","link_route":"/s/Southwest-Fillmore-Street-Topeka--KS"},{"link_text":"Topeka,","search_text":"Topeka, KS","link":"<span>Topeka,</span>","link_route":"/s/Topeka--KS"},{"link_text":"Kansas,","search_text":"Kansas, United States","link":"<span>Kansas,</span>","link_route":"/s/Kansas--United-States"},{"link_text":"United States","search_text":"United States","link":"<span>United States</span>","link_route":"/s/United-States"}],"neighborhood_basic_info":null,"neighborhood_localized_name":null,"user_info":{"user_image":"<img alt=\"Elizabeth\" data-pin-nopin=\"true\" height=\"90\" src=\"https://a0.muscache.com/im/users/9199018/profile_pic/1380782460/original.jpg?aki_policy=profile_x_medium\" title=\"Elizabeth\" width=\"90\" />"}}' id="_bootstrap-neighborhood_card">

这显然是 JSON,但它已编码(如您所见)。我试过urllib.unquote 但这会引发错误。 AttributeError: 'list' object has no attribute 'split'

我希望不必求助于使用正则表达式来进行 URL 解码。我可以做什么(除了使用正则表达式)来制作这个有效的 JSON?

【问题讨论】:

  • 这不是 URL 编码的。 URL 编码类似于This%20is%20a%20test。您所拥有的是使用 HTML 字符实体的 HTML,例如 < 用于 <。关于如何处理这个问题已经有很多很好的答案。
  • 你试过eval('('+String+')')吗?这些是 HTML 实体。你的问题是这是一个字符串。你需要把它变成代码。
  • @larsks 你说得对,我改写了标题。

标签: python json scrapy


【解决方案1】:

获取content属性的值并通过json.loads()加载:

>>> import json
>>> content = response.xpath('//meta[@id="_bootstrap-neighborhood_card"]/@content').extract_first()
>>> json.loads(content)

请注意,您还需要使用extract_first() 而不是extract() 来获取字符串值而不是列表。

【讨论】:

    【解决方案2】:

    您可以使用json.loads() 进行解码,但是您需要获取包含在<meta> 标签的content 属性中的JSON 字符串。

    您可以多次调用xpath() 以深入了解所选标签的属性:

    meta = response.xpath('//meta[@id="_bootstrap-neighborhood_card"]')
    content = meta.xpath('@content').extract_first()
    data = json.loads(content)
    

    或者你可以一次性完成:

    content = response.xpath('//meta[@id="_bootstrap-neighborhood_card"]').xpath('@content').extract_first()
    data = json.loads(content)
    from pprint import pprint
    pprint(data)
    

    输出

    {u'hosting': {u'id': 2256573, u'offset_lat': 39.04258923718809, u'offset_lng':-95.69083697887662}, u'map_url': u'https://maps.googleapis.com/maps/api/staticmap?markers=%2C&size&zoom=14', u'neighborhood_basic_info':无, u'neighborhood_breadcrumb_details': [{u'link': u'Southwest Fillmore Street,', u'link_route': u'/s/Southwest-Fillmore-Street-Topeka--KS', u'link_text': u'西南菲尔莫尔街,', u'search_text': u'Southwest Fillmore Street Topeka, KS'}, {u'link': u'托皮卡,', u'link_route': u'/s/Topeka--KS', u'link_text': u'托皮卡', u'search_text': u'Topeka, KS'}, {u'link': u'堪萨斯州,', u'link_route': u'/s/Kansas--United-States', u'link_text': u'堪萨斯州,', u'search_text': u'美国堪萨斯州'}, {u'link': u'美国', u'link_route': u'/s/United-States', u'link_text': u'美国', u'search_text': u'美国'}], u'neighborhood_localized_name':无, 你'place_recommendations':[], u'user_info': {u'user_image': u''}}

    【讨论】:

    • 不相关,但是print和pprint有什么区别呢? (这里是相对新手)
    • pprint == “漂亮的印刷品”。对于嵌套数据结构,pprint 产生比print 更具可读性的输出。
    • @Jeroen:感谢您接受这个答案,尽管我确实认为 alecxe 的单个 xpath 查询更简洁:content = response.xpath('//meta[@id="_bootstrap-neighborhood_card"]/@content').extract_first()
    • 是的,它更简洁,我同意,但除此之外,它基本上是相同的,所以我查看了你们的声誉分数,而你们的分数更低...... :-)
    • @Jeroen:我很感激,但这不是接受答案的理由。您应该选择最能回答您的问题的那个。如果那是我的,那就太好了。您的选择也可能会影响未来可能遇到类似问题的读者。在此基础上,我倾向于将答案的第二部分更新为与 alecxe 的相同。
    猜你喜欢
    • 2017-07-05
    • 1970-01-01
    • 1970-01-01
    • 2011-02-24
    • 2013-11-17
    • 2018-01-14
    • 1970-01-01
    • 2019-01-08
    相关资源
    最近更新 更多