【问题标题】:Scraping a page with awkwardly formatted JSON in python在 python 中使用格式笨拙的 JSON 抓取页面
【发布时间】:2014-09-16 16:08:09
【问题描述】:

我正在抓取网页中的数据,其格式如下:

<!-- Web header up here -->
[{"foo": "Bar", "foo2": "Bar2"},
 {"foo3": ["hello", "world"], "foo4": "Bar4"},
...
]
<!-- Web footer here -->

问题是 JSON 与其他内容一起出现在页面上,并且页面源在引号内有 JSON 列表,在 JSON 中带有其他 html 标记的“pre”标记内,如下所示:

<pre>" [{ "foo": "Bar", <p>"foo2": "Bar2"</p>}, ... ] "</pre>

有没有办法绕过这种糟糕的格式并在给定 JSON 对象字符串列表的情况下获取 JSON 对象列表,最好摆脱过程中的嵌入标签?

编辑:我现在已经按照 Mauricio 的建议安装并开始学习 BeautifulSoup4,但我仍然有些不足。在“汤”上使用 .pre 运算符给了我

&lt;pre&gt; [{ ... (Good formatted JSON but inside tags still) ...}]&lt;/pre&gt;

HTML:&lt;pre&gt; 代码只是在其上方和下方有一些标题。)

<pre>
[{
  "title": “blah”,
  "refs": [“a”, “a”],
  "description": [“a”,
  “a”,
  "a”],
  “a”: [
    {“a”: “a"}]
},
{
  "title": “a”,
  "refs": [“a”, “a”],
  "description": [“a”,
  “a”,
  “a”],
  “a”: [
    {“a”: “a”}]
}]
</pre>

【问题讨论】:

    标签: python html json html-parsing beautifulsoup


    【解决方案1】:

    您需要获取 .textstrip() 引号和空格。

    然后,你可以使用json.loads()来加载json字符串:

    import json
    from bs4 import BeautifulSoup
    
    
    data = """
    <div>
        <pre>" [{ "foo": "Bar", <p>"foo2": "Bar2"</p>}] "</pre>
    </div>
    """
    
    soup = BeautifulSoup(data)
    
    json_data = soup.pre.text.strip('" ')
    print json.loads(json_data)
    

    打印:

    [{u'foo': u'Bar', u'foo2': u'Bar2'}]
    

    还有一个问题——pre里面的引号不正常,应该替换掉:

    # -*- coding: utf-8 -*-
    
    import json
    from bs4 import BeautifulSoup
    
    
    data = u"""
    <div>
        <pre>
    [{
      "title": “blah”,
      "refs": [“a”, “a”],
      "description": [“a”,
      “a”,
      "a”],
      “a”: [
        {“a”: “a"}]
    },
    {
      "title": “a”,
      "refs": [“a”, “a”],
      "description": [“a”,
      “a”,
      “a”],
      “a”: [
        {“a”: “a”}]
    }]
    </pre>
    </div>
    """
    
    soup = BeautifulSoup(data)
    
    json_data = soup.pre.text.encode('utf-8').strip('" ').replace('“', '"').replace('”', '"')
    print json.loads(json_data)
    

    打印:

    [{u'a': [{u'a': u'a'}], u'refs': [u'a', u'a'], u'description': [u'a', u'a', u'a'], u'title': u'blah'}, 
     {u'a': [{u'a': u'a'}], u'refs': [u'a', u'a'], u'description': [u'a', u'a', u'a'], u'title': u'a'}]
    

    【讨论】:

    • 由于某种原因 json.loads 无法解码任何内容。如果您将另一个对象放在括号中,您的方法是否仍然有效:&lt;pre&gt;" [{"a":"b"},{"c":"d"}] "&lt;/pre&gt;
    • @mlinsenbard 请显示完整的 html,以便我重现该问题。谢谢。
    • 已将其添加到问题中。
    • 太棒了!像魅力一样工作。非常感谢。我没有看到那些打开/关闭引号存在并且把一切都搞砸了。如果可以的话,我会 +1(如果可以的话,我会的!)
    【解决方案2】:

    我推荐你使用 BeautifulSoup 来解析网页。

    http://www.crummy.com/software/BeautifulSoup/

    文档:

    http://www.crummy.com/software/BeautifulSoup/bs4/doc/

    然后你可以这样做:

    from bs4 import BeautifulSoup
    from urllib2 import urlopen
    
    html_doc = urlopen("http://www.google.com/").read()
    soup = BeautifulSoup(html_doc)
    print soup.p.text
    

    它将从P下面的每个标签中提取文本,包括P本身。

    【讨论】:

    • 谢谢!这让我接近我想要的。有没有办法在获取数据时省略标签,以便我得到 [{ ... }] 而不是 &lt;pre&gt;[{ ... }]&lt;/pre&gt; ? soup.pre.text 给了我一团乱七八糟的 HTML,而只有 soup.pre 给了我页面显示时的内容,但附加了这些标签。
    • soup.pre.text to me 只返回文本,但是,如果它仍然有标签,你可以这样做:BeautifulSoup(soup.pre.text).text
    猜你喜欢
    • 2015-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-05
    • 1970-01-01
    • 1970-01-01
    • 2013-04-29
    相关资源
    最近更新 更多