用Python抓取格式奇怪的JSON页面
我正在抓取一个网页的数据,网页的格式是这样的:
<!-- Web header up here -->
[{"foo": "Bar", "foo2": "Bar2"},
{"foo3": ["hello", "world"], "foo4": "Bar4"},
...
]
<!-- Web footer here -->
问题是,页面上有其他内容,JSON数据被放在引号里,并且在一个'pre'标签里面,里面还有其他的HTML标签,像这样:
<pre>" [{ "foo": "Bar", <p>"foo2": "Bar2"</p>}, ... ] "</pre>
有没有办法绕过这种糟糕的格式,直接从一个包含JSON对象列表的字符串中提取出JSON对象,最好在这个过程中去掉那些嵌套的标签?
编辑:我现在已经安装并开始学习BeautifulSoup4,正如Mauricio推荐的那样,但我还是有点困难。使用.pre操作符在'soup'上给我的结果是:
<pre> [{ ... (格式良好的JSON,但仍然在标签里面) ...}]</pre>
HTML: (这个<pre>
标签上面和下面都有一些标题。)
<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>
2 个回答
0
我建议你使用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标签及其下面每个标签里的文本。
2
你需要获取 .text
和 strip()
中的引号和空格。
然后,你可以使用 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'}]