【问题标题】:Parse JSON from HTML responseText从 HTML responseText 解析 JSON
【发布时间】:2016-08-19 16:06:17
【问题描述】:

Python 的 webob 模块默认返回 text/html 响应,特别是 ServerErorr 的响应,这些最终会在 HTML responseText 的正文中嵌入错误 JSON Paylod,其中包含以下内容:

<html>
<head>
  <title>503 Service Unavailable</title>
</head>
<body>
<h1>503 Service Unavailable</h1>
{
    "status": "object-specific error",
    "payload": {
            "Message": "Unable to list resources",
            "HTTP Method": "GET",
            "URI": "api/myManager/1.0/Node",
            "Operation": "LIST",
            "Object": {
                    "Name": "myManager.Node",
                    "Interface": "Node"
            },
            "Version": {
                    "Major": 1,
                    "Minor": 0
            }
       }
}<br /><br />
</body>
</html>

在客户端使用 Javascript 提取嵌入在 HTML 中的 JSON 的最佳方法是什么? 提取嵌入在 HTML 中的 JSON 对象的最佳方法是什么?

【问题讨论】:

  • 解析成DOM结构,然后找到h1元素后面的文本元素。
  • 我认为最好的方法是在服务器端处理错误并将响应返回为 json only 。如您所示,没有直接的方法来解析嵌入在 html 中的json。如果你真的需要从这里提取json,你需要读取dom(这是唯一的方法)分隔json字符串,然后使用JSON.parse()
  • 从 HTML 中提取 JSON 是不好的做法。您应该修改服务器端脚本以仅返回 JSON

标签: javascript python html json parsing


【解决方案1】:

所以我一般同意,更好的解决方案是确保服务器只返回 JSON,但是正如@Barmer 建议的那样,通过客户端上的 Javascript 快速实现这一点,将 html 解析到 DOM,获取文本在 body 中的 childNode 并在其上运行 JSONParse。

var responseStr = '<html>' +
                  '<head>' +
                  '  <title>503 Service Unavailable</title>' +
                  '</head>' +
                  '<body>' +
                  '<h1>503 Service Unavailable</h1>' +
                  '{' +
                  '  "status": "object-specific error",' +
                  '  "payload": {' +
                  '    "Message": "Unable to list resources",' +
                  '    "HTTP Method": "GET",' +
                  '    "URI": "api/myManager/1.0/Node",' +
                  '    "Operation": "LIST",' +
                  '    "Object": {' +
                  '      "Name": "myManager.Node",' +
                  '      "Interface": "Node"' +
                  '    },' +
                  '    "Version": {' +
                  '      "Major": 1,' +
                  '      "Minor": 0' +
                  '    }' +
                  '  }' +
                  '}<br /><br />' +
                  '</body>' +
                  '</html>';
var parser = new DOMParser();
var doc = parser.parseFromString(responseStr, "text/html");
var items = doc.body.getElementsByTagName("*");
var json_obj;

for (var i = 0, len = doc.body.childNodes.length; i < len; i++) {
    if (doc.body.childNodes[i].nodeName == "#text") {
        json_obj = JSON.parse(doc.body.childNodes[i].data);
        break;
    }
}

// You can access json directly now e.g.
console.log(json_obj.status);
console.log(json_obj.payload['HTTP Method']);

【讨论】:

    【解决方案2】:

    使用正则表达式进行解析(不是很可靠但很有效) 重新进口 导入json

    content = """\
    <html>
    <head>
      <title>503 Service Unavailable</title>
    </head>
    <body>
    <h1>503 Service Unavailable</h1>
    {
        "status": "object-specific error",
        "payload": {
                "Message": "Unable to list resources",
                "HTTP Method": "GET",
                "URI": "api/myManager/1.0/Node",
                "Operation": "LIST",
                "Object": {
                        "Name": "myManager.Node",
                        "Interface": "Node"
                },
                "Version": {
                        "Major": 1,
                        "Minor": 0
                }
           }
    }<br /><br />
    </body>
    </html>"""
    
    mo = re.search(r"</h1>(.*?)<br", content, flags=re.DOTALL)
    if mo:
        data = mo.group(1)
        obj = json.loads(data)
        print(obj)
    

    你会得到:

    {'payload': {'Operation': 'LIST', 'HTTP Method': 'GET',
    'URI': 'api/myManager/1.0/Node',
    'Message': 'Unable to list resources',
    'Version': {'Major': 1, 'Minor': 0},
    'Object': {'Interface': 'Node', 'Name': 'myManager.Node'}},
    'status': 'object-specific error'}
    

    或者,使用lxml

    import json
    from lxml import etree
    
    content = """\
    <html>
    ...
    </html>"""
    
    tree = etree.XML(content)
    
    h1 = tree.xpath("/html/body/h1[1]")[0]
    data = h1.tail
    obj = json.loads(data)
    

    同样的结果

    【讨论】:

    • 感谢您的回复..但是我正在尝试使用 Javascript 而不是 Python 来实现解析...也许我的标题不够清楚
    猜你喜欢
    • 2015-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-16
    相关资源
    最近更新 更多