【问题标题】:Encode a raw string so it can be decoded as json编码原始字符串,以便可以将其解码为 json
【发布时间】:2018-01-27 01:46:09
【问题描述】:

我在这里认输。我正在尝试将使用scrapy(注入的javascript)从网站的源代码中抓取的字符串转换为json,以便我可以轻松访问数据。问题归结为解码错误。我尝试了各种编码、解码、转义、编解码器、正则表达式、字符串操作,但没有任何效果。哦,使用 Python 3。

我缩小了字符串(或至少部分)的罪魁祸首

scraped = '{"propertyNotes": [{"title": "Local Description", "text": "\u003Cp\u003EAPPS\u003C/p\u003E\n\n\u003Cp\u003EBig Island Revealed (comes as app or as a printed book)\u003C/p\u003E\n\n\u003Cp\u003EAloha Big Island\u003C/p\u003E\n\n\u003Cp\u003EBig Island\u003C/p\u003E\n\n\u003Cp\u003EBig Island Smart Maps (I like this one a lot)\u003C/p\u003E\n\n\u003Cp\u003EBig Island Adventures (includes videos)\u003C/p\u003E\n\n\u003Cp\u003EThe descriptions of beaches are helpful.  Suitability for swimming, ease of access, etc. is included.  Some beaches are great for picnics and scenic views, while others are suitable for swimming and snorkeling. Check before you go.\u003C/p\u003E"}]}'

scraped_raw = r'{"propertyNotes": [{"title": "Local Description", "text": "\u003Cp\u003EAPPS\u003C/p\u003E\n\n\u003Cp\u003EBig Island Revealed (comes as app or as a printed book)\u003C/p\u003E\n\n\u003Cp\u003EAloha Big Island\u003C/p\u003E\n\n\u003Cp\u003EBig Island\u003C/p\u003E\n\n\u003Cp\u003EBig Island Smart Maps (I like this one a lot)\u003C/p\u003E\n\n\u003Cp\u003EBig Island Adventures (includes videos)\u003C/p\u003E\n\n\u003Cp\u003EThe descriptions of beaches are helpful.  Suitability for swimming, ease of access, etc. is included.  Some beaches are great for picnics and scenic views, while others are suitable for swimming and snorkeling. Check before you go.\u003C/p\u003E"}]}'

data = json.loads(scraped_raw) #<= works
print(data["propertyNotes"])

failed = json.loads(scraped) #no work
print(failed["propertyNotes"])

不幸的是,我无法找到一种方法让 scrapy/splash 将字符串作为原始字符串返回。因此,不知何故,我需要让 python 在加载 json 时将字符串解释为原始字符串。请帮忙

更新:

适用于该字符串的是json.loads(str(data.encode('unicode_escape'), 'utf-8')) 但是,它不适用于较大的字符串。我这样做的错误是 JSONDecodeError: Invalid \escape 在较大的 json 字符串上

【问题讨论】:

  • 原始字符串是语言的句法特性,而不是运行时特性。您是从网站生成 Python source 吗? (请说不...)
  • 原始或非原始仅与字符串文字有关。对于您从其他地方读取的数据,这种区别是没有意义的。您需要向我们展示您在读取数据时遇到的失败,而不是文字数据。
  • 那行不通。适用于该字符串的是json.loads(str(data.encode('unicode_escape'), 'utf-8')) 但是,它不适用于较大的字符串。我这样做的错误是较大的 json 字符串上的 JSONDecodeError: Invalid \escapesee it here on repl.it
  • 使用起来有点困难,但如果我运行data_feed = json.loads(data.encode('unicode_escape').decode('utf-8')),它看起来就像读取为无效的 json
  • 如果您将字符串中的数据粘贴到 jsonlint.com 中,则会将其标记为有效。那是在任何编码/解码之前。

标签: python json python-3.x character-encoding


【解决方案1】:

问题存在是因为你得到的字符串已经转义了控制字符,当被 python 解释时,这些字符在编码时变成了实际的字节(虽然这不一定是坏的,我们知道这些转义字符是 json 不会期望的控制字符) .与 Turn 的回答类似,您需要解释字符串而不解释使用

完成的转义值

json.loads(scraped.encode('unicode_escape'))

它的工作原理是按照 latin-1 编码的预期对内容进行编码,同时将任何\u003 之类的转义字符解释为字面意义上的\u003,除非它是某种控制字符。

但是,如果我的理解是正确的,您可能不希望这样做,因为您会丢失转义的控制字符,因此数据可能与原始数据不同。

您可以通过注意到将编码字符串转换回普通 python 字符串后控制字符消失来看到这一点:

scraped.encode('unicode_escape').decode('utf-8')

如果你想保留控制字符,你将不得不在加载它们之前尝试转义字符串。

【讨论】:

  • 但是scraped.encode('unicode_escape').decode('unicode_escape') 正确地保留了控制字符。
  • 我很欣赏写得好的回复。我不介意修改字符串,只要它可以在保存到数据库之前转换回来,所以你是对的。我宁愿不要。
  • scraped.encode('unicode_escape').decode('unicode_escape') 也返回错误 'json.decoder.JSONDecodeError: Invalid control character at: line 1 column 71 (char 70)'
  • @DennisPitt 这是预期的,因为正如 Turn 所说,这将保留控制字符。
  • @Turn,当它被正确反转时,json.loads(s.encode('unicode_escape').decode('unicode_escape')) 会抛出一个错误。
【解决方案2】:

如果您使用的是 Python 3.6 或更高版本,我认为您可以使用它

 json.loads(scraped.encode('unicode_escape'))

根据docs,这会给你一个

适合作为 Unicode 文字内容的编码 ASCII 编码的 Python 源代码,但引号未转义。 从 Latin-1 源代码解码。当心 Python 源代码 实际上默认使用 UTF-8。

这似乎正是您所需要的。

【讨论】:

  • 是的。我试过了,得到“TypeError:JSON对象必须是str,而不是'bytes'”
  • 啊,我用 3.6 进行了测试,它有一个更宽松的 json 包:docs.python.org/3/whatsnew/3.6.html#json
【解决方案3】:

好的。所以因为我在 Windows 上,所以我必须设置控制台来处理特殊字符。我通过在终端中输入chcp 65001 来做到这一点。我还使用正则表达式并将字符串操作函数链接起来,这无论如何都是 python 方式。

usable_json = json.loads(re.search('start_sub_string(.*)end_sub_string', hxs.xpath("//script[contains(., 'some_string')]//text()").extract_first()).group(1))

然后一切都很顺利。下线写入数据库时​​,我会整理编码和转义。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-11-01
    • 1970-01-01
    • 2011-02-05
    • 2018-12-21
    • 2011-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多