【问题标题】:Python - Parsing JSON formatted text file with regexPython - 使用正则表达式解析 JSON 格式的文本文件
【发布时间】:2018-05-07 08:55:22
【问题描述】:

我有一个格式类似于 JSON 文件的文本文件,但是所有内容都在一行上(可能是 MongoDB 文件)。有人可以指点我如何使用 Python 正则表达式方法提取值的方向吗?

文本显示如下:

{"d":{"__type":"WikiFileNodeContent:http:\/\/samplesite.com.‌​au\/ns\/business\/wi‌​ki","author":null,"d‌​escription":null,"fi‌​leAssetId":"034b9317‌​-60d9-45c2-b6d6-0f24‌​b59e1991","filename"‌​:"Reports.pdf"},"cre‌​atedBy":1531,"create‌​dByUsername":"John Cash","icon":"\/Assets10.37.5.0\/pix\/16x16\/page_white_acro‌​bat.png","id":3041,"‌​inheritedPermissions‌​":false,"name":"map"‌​,"permissions":[23,8‌​7,35,49,65],"type":3‌​,"viewLevel":2},{"__‌​type":"WikiNode:http‌​:\/\/samplesite.com.‌​au\/ns\/business\/wi‌​ki","children":[],"c‌​ontent": 

我想要获取“fileAssetId”和文件名“。我尝试使用 Pythons JSON 模块加载类似内容,但出现错误

对于 FileAssetid,我尝试了这个正则表达式:

regex = re.compile(r"([0-9a-f]{8})\S*-\S*([0-9a-f]{4})\S*-\S*([0-9a-f]{4})\S*-\S*([0-9a-f]{4})\S*-\S*([0-9a-f]{12})")

但我得到以下 034b9317‌​、60d9、45c2、b6d6、0f24‌​b59e1991

我不确定如何获取显示的数据。

【问题讨论】:

  • 你能把你文件的一些数据放在这里吗?
  • 文本显示如下: {"d":{"__type":"WikiFileNodeContent:http:\/\/samplesite.com.au\/ns\/business\/wiki", "author":null,"description":null,"fileAssetId":"034b9317-60d9-45c2-b6d6-0f24b59e1991","filename":"Reports.pdf"},"createdBy":1531,"createdByUsername":" John Cash","icon":"\/Assets10.37.5.0\/pix\/16x16\/page_white_acrobat.png","id":3041,"inheritedPermissions":false,"name":"map","权限":[23,87,35,49,65],"type":3,"viewLevel":2},{"__type":"WikiNode:http:\/\/samplesite.com.au\/ns \/business\/wiki","children":[],"content": 我想获取 "fileAssetId" 和文件名"
  • 字典未完成。你是missgin[开头和}]结尾
  • 我很想提取 "fileAssetId": 之后的值和文件名之后的值,但我不知道该怎么做。
  • 使用 JSON 解析器一定是更好的选择?

标签: python json regex python-2.7


【解决方案1】:

如何使用积极的前瞻和后瞻:

(?<=\"fileAssetId\":\")[a-fA-F0-9-]+?(?=\")

捕获fileAssetId

(?<=\"filename\":\").+?(?=\")

匹配文件名。

有关正则表达式的详细说明,请查看Regex101-Example。 (注意:我在示例中将两者与 OR-Operator | 结合在一起,以同时显示两个匹配项)

要获取所有匹配项的列表,请使用 re.findallre.finditer 而不是 re.match

re.findall(pattern, string) 返回匹配字符串的列表。

re.finditer(pattern, string) 返回带有对象的迭代器。

【讨论】:

  • 这行得通,非常感谢,但它只显示第一个,而不是所有值,我这样做是这样的:import re f=open("jsonfile.txt") f=f. readlines() for line in f: m = re.search(r'(?
  • 正如我在答案编辑中所说,使用 findall 或 finditer 而不是搜索。
  • 这是一种享受,谢谢。有没有办法我可以存储“filename”和“fileAssetId”的所有值,所以我可以做类似 wget = urllib.urlopen('samplewebsite.com' + fileAssetId_value + filename_value) 的事情???感谢您的帮助。
  • 如果一个资产 ID 始终与一个文件名相关联,我会尝试修复您的 json 数据并加载它,而不是使用正则表达式,因为获取关联值将是一个非常复杂的正则表达式。你能做with open('jsonfile', 'r') as f: distros_dict = json.load(f) for distro in distros_dict: print(distro) 并分享输出吗?那我也许可以告诉你为什么你不能访问文件名。
  • 将代码加载为 JSON 文件的输出只是字母 d
【解决方案2】:

您可以使用 python 的walk method 并使用re.match 检查每个条目。

如果你得到的字符串不能转换为python dict,你可以只使用正则表达式:

print re.match(r'.*fileAssetId\":\"([^\"]+)\".*', your_pattern).group(1)

您的示例的解决方案:

import re

example_string = '{"d":{"__type":"WikiFileNodeContent:http:\/\/samplesite.com.u\/ns\/business\/wiki","author":null,"description":null,"fileAssetId":"034b9317-60d9-45c2-b6d6-0f24b59e1991","filename":"Reports.pdf"},"createdBy":1531,"createdByUsername":"John Cash","icon":"\/Assets10.37.5.0\/pix\/16x16\/page_white_acrobat.png","id":3041,"inheritedPermissions":false,"name":"map","permissions":[23,87,35,49,65],"type":3,"viewLevel":2},{"__type":"WikiNode:http:\/\/samplesite.com.au\/ns\/business\/wiki","children":[],"content"'

regex_pattern = r'.*fileAssetId\":\"([^\"]+)\".*'
match = re.match(regex_pattern, example_string)
fileAssetId = match.group(1)
print('fileAssetId: {}'.format(fileAssetId))

执行这个会产生:

34b9317‌​-60d9-45c2-b6d6-0f24‌​b59e1991

【讨论】:

  • 在崇高文本中出现红色 \":\"([^\"]+)\".*`).group(1)
  • 文件“test2.py”,第 18 行 fileAsset = re.match(r.*fileAssetId\":\"([^\"]+)\".*, regex).group(1) ^ SyntaxError: invalid syntax
  • 你不见了'
  • 谢谢,这样更好,但会出错。 return _compile(pattern, flags).m​​atch(string) TypeError: expected string or buffer
  • @KhaledAhmedSobhy [^\"]+ 匹配至少一个不是" 的字符,因此也会匹配 int 和 float。不过,您可能希望在匹配后将其转换为 int 或 float。
【解决方案3】:

尝试将 \n 添加到您正在输入文件的字符串中(\n 表示换行)

【讨论】:

    【解决方案4】:

    基于此处https://stackoverflow.com/a/3845829 给出的想法并遵循JSON 标准https://www.json.org/json-en.html,我们可以使用Python + 正则表达式https://pypi.org/project/regex/ 并执行以下操作:

    json_pattern = (
        r'(?(DEFINE)'
        r'(?P<whitespace>( |\n|\r|\t)*)'
        r'(?P<boolean>true|false)'
        r'(?P<number>-?(0|([1-9]\d*))(\.\d*[1-9])?([eE][+-]?\d+)?)'
        r'(?P<string>"([^"\\]|\\("|\\|/|b|f|n|r|t|u[0-9a-fA-F]{4}))*")'
        r'(?P<array>\[((?&whitespace)|(?&value)(,(?&value))*)\])'
        r'(?P<key>(?&whitespace)(?&string)(?&whitespace))'
        r'(?P<value>(?&whitespace)((?&boolean)|(?&number)|(?&string)|(?&array)|(? &object)|null)(?&whitespace))'
        r'(?P<object>\{((?&whitespace)|(?&key):(?&value)(,(?&key):(?&value))*)\})'
        r'(?P<document>(?&object)|(?&array))'
        r')'
        r'(?&document)'
    )
    
    json_regex = regex.compile(json_pattern)
    
    match = json_regex.match(json_document_text)
    

    您可以更改json_pattern 中的最后一行,以匹配将(?&amp;document) 替换为(?&amp;object) 的单个对象而不是文档。我认为正则表达式比我预期的要容易,但我没有对此进行广泛的测试。它对我来说很好,我已经测试了数百个文件。我会尝试改进我的答案,以防在运行时发现任何问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-19
      • 2013-08-13
      • 1970-01-01
      • 2016-04-27
      相关资源
      最近更新 更多