【问题标题】:How to parse a file that looks like JSON but which is not如何解析看起来像 JSON 但不是的文件
【发布时间】:2020-01-28 09:45:38
【问题描述】:

我正在尝试在 python 中解析一个文件 (filename.inc),它看起来像:

a: 2: {
    s: 3: "somestuff";
    a: 14: {
        i: 601600;
        a: 6: {
            i: 559;
            a: 4: {
                s: 5: "label";
                s: 3: "somelabel";
                s: 2: "id";
                s: 3: "559";
                s: 10: "timestart";
                s: 16: "01 01 1970 00:00";
                s: 8: "timestop";
                s: 16: "24 01 2020 20:55";
            }
            i: 18158;
            a: 4: {
                s: 5: "label";
                s: 12: "someotherlabel";
                s: 2: "id";
                s: 5: "18158";
                s: 10: "timestart";
                s: 16: "01 01 1970 00:00";
                s: 8: "timestop";
                s: 16: "25 01 2020 18:55";
            }
            i: 10402;
            a: 4: {
                s: 5: "label";
                s: 3: "newlabel";
                s: 2: "id";
                s: 5: "10402";
                s: 10: "timestart";
                s: 16: "01 01 1970 00:00";
                s: 8: "timestop";
                s: 16: "26 01 2020 06:55";
            }

等等…… 我尝试使用:

import json

with open('filename.inc') as json_file:
    data = json.load(json_file)

但得到: ValueError:无法解码任何 JSON 对象

我尝试删除第一个冒号,添加引号,用逗号替换分号:

"a2": {
    "s3": "somestuff",
    "a14": {
        "i": 601600,
        "a6": {
            "i": 559,
            "a4": {
                "s5": "label",
                "s3": "somelabel",
                "s2": "id",
                "s3": "559",
                "s10": "timestart",
                "s16": "01 01 1970 00:00",
                "s8": "timestop",
                "s16": "24 01 2020 20:55",
            }
            "i": 18158,
            "a4": {
                "s5": "label",
                "s12": "someotherlabel",
                "s2": "id",
                "s5": "18158",
                "s10": "timestart",
                "s16": "01 01 1970 00:00",
                "s8": "timestop",
                "s16": "25 01 2020 18:55",
            }
            "i": 10402,
            "a4": {
                "s5": "label",
                "s3": "newlabel",
                "s2": "id",
                "s5": "10402",
                "s10": "timestart",
                "s16": "01 01 1970 00:00",
                "s8": "timestop",
                "s16": "26 01 2020 06:55",
            }

但这给了我多个具有相同 ID 的键... 想把它变成一个带有标签的html文件,用beautifulsoup解析,但这样的文件似乎太复杂了。 如有任何提示,我将不胜感激,在此先感谢。

【问题讨论】:

  • 它看起来像 PHP serialize 输出,但经过美化。试试看phpserialize 是否可以解决这个问题。我不知道多余的空格是否会造成伤害,您可能需要先取消美化。
  • 绝对不是 JSON,也不是 Python 字典。你能告诉我们这是从哪里来的吗?或者您应该尝试查找并了解它是如何生成的,这可能有助于您了解如何解析它。
  • @Amadan,我必须承认我自己做了美化,使它更容易阅读^^ 起初,文件是:a:2:{s:3:"somestuff";a: 14:{i:601600;a:6:{i:559;a:4:{s:5:"label";s:3:"somelabel";s:2:"id";s:3:" 559";s:10:"timestart";s:16:"0101197000:00";s:8:"timestop";s:16:"2401202020:55";}i:18158;a:4:{s :5:"标签"
  • 在这种情况下,phpserialize.loads(source)source 是一个字节串)应该可以工作。
  • @BastienAntoine 实际上,它是一个每小时更新一次的文件,我认为它与 SQLite 导入有关,但不确定。无法真正说出它的来源,但我只能说我需要解析它;)感谢您的时间

标签: python json parse-error jsonparser


【解决方案1】:

我检查过,空格会伤害 PHP 的原生 serialize 以及 Python phpserialize。您执行的“清理”无论如何都会使其成为无效转储(例如s: 3: "somestuff" 是非法的,它编码 3 个字符的字符串“somestuff”,其中“somestuff”显然不是 3 个字符长),所以我必须构造我自己的例子:

source = """
a: 2: {
    i: 0;
    s: 3: "foo";
    i: 1;
    s: 4: "quux";
};
"""

import re
import phpserialize     # requires: pip install phpserialize

cleanup_re = re.compile('(".*?")|\s+')
clean_source = cleanup_re.sub(lambda m: m.group(0) if m.group(1) else "", source)
data = phpserialize.loads(bytes(clean_source, 'utf8'))

这只有在字符串中没有双引号时才有效;如果不编写适当的解析器,我想不出办法。

【讨论】:

  • 非常感谢@Amadan !!其实你是对的,真正的 somestuff 标签是 3 个字符长,我不知道 s 后面的这个数字:是字符数!并且没有字符串中有双引号,所以应该可以,迫不及待地想试试!谢谢!!! :)
  • 正如我在问题的 cmets 中所说,如果您没有美化版本,那么最后一行就足够了。剩下的只是撤消多余的空格。
  • 是的:s:3:"foo"; 是 3 个字符的字符串 "foo"i:10402; 是整数 10402d:3.2 是双精度 (4.2),a:2:{...}; 是一个 2 元素数组(你应该在 curlies 中有 4 个条目,作为 key-value-key-value),尽管 PHP “arrays” 在 Python 中表现为字典和列表,所以phpserialize 总是将它们变成字典。
  • 完美运行,谢谢!我将您的答案标记为有用,但我没有足够的“声誉点”来使其计数;)只有一件事:当我从您的代码中打印数据时,它给出:{0:b'foo',1:b' quux'},我怎样才能摆脱“b”而只保留 {0: 'foo', 1: 'quux'}?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-10-28
  • 1970-01-01
  • 2021-10-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多