3

我有一个 json 文件存储一些用户信息,包括id,nameurl. json 文件如下所示:

{"link": "https://www.example.com/user1", "id": 1, "name": "user1"}
{"link": "https://www.example.com/user1", "id": 2, "name": "user2"}

这个文件是由一个scrapy spider编写的。现在我想从 json 文件中读取 url 并抓取每个用户的网页。但我无法从 json 文件中加载数据。

目前,我不知道如何获取这些 url。我想我应该先从 json 文件中读取这些行。我在 Python shell 中尝试了以下代码:

import json    
f = open('links.jl')    
line = json.load(f)

我收到以下错误消息:

Raise ValueError(errmsg("Extra data", s, end, len(s)))
ValueError: Extra data: line 2 column 1- line 138 column 497(char498-67908)

我在网上做了一些搜索。搜索表明 json 文件可能存在一些格式问题。但是json文件是使用scrapy管道创建并填充项目的。有人知道导致错误的原因吗?以及如何解决?关于阅读网址有什么建议吗?

非常感谢。

4

5 回答 5

7

正如导出器名称所暗示的那样,这些是 json 行。

看一看,看看和scrapy.contrib.exporter之间的区别JsonItemExporterJsonLinesItemExporter

这应该可以解决问题:

import json

lines = []

with open('links.jl', 'r') as f:
    for line in f:
        lines.append(json.loads(line))
于 2013-04-16T19:30:11.027 回答
1

嗯……那个例外很有趣……我就……把它留在这里(没有保证或良心)。

import json
import re

parse_err = re.compile(
    r'Extra data: line \d+ column \d+'
    r' - line \d+ column \d+'
    r' \(char (\d*).*')

def recover_bad_json(data):
    while data:
        try:
            yield json.loads(data)
            return
        except ValueError, e:
            char = parse_err.match(e.args[0]).group(1)
            maybe_data, data = data[:int(char)], data[int(char):]
            yield json.loads(maybe_data)

CORPUS = r'''{"link": "https://www.domain.com/user1", "id": 1, "name": "user1"}

{"link": "https://www.domain.com/user1", "id": 2, "name": "user2"}
'''

gen_recovered = recover_bad_json(CORPUS)

print gen_recovered.next()
print gen_recovered.next()
print gen_recovered.next()
于 2012-12-24T06:25:53.693 回答
0

AFAIK,一个 JSON 文件应该包含一个对象。在您的情况下,您有几个:

{"link": "https://www.domain.com/user1", "id": 1, "name": "user1"}

{"link": "https://www.domain.com/user1", "id": 2, "name": "user2"}

我会做类似的事情:

Python 2.7.3 (default, Sep 26 2012, 21:51:14) 
>>> import json
>>> inpt_json = """{"link": "https://www.domain.com/user1", "id": 1, "name": "user1"}
...     
...     {"link": "https://www.domain.com/user1", "id": 2, "name": "user2"}"""

>>> for line in inpt_json.splitlines():
...     line = line.strip()
...     if line:
...             print json.loads(line)
... 
{u'link': u'https://www.domain.com/user1', u'id': 1, u'name': u'user1'}
{u'link': u'https://www.domain.com/user1', u'id': 2, u'name': u'user2'}
>>> 

因此,说“我有一个存储一些用户信息的 json 文件……”是不正确的。Scrapy 将输出存储为“带有 json 编码行的文件”

于 2012-12-24T08:12:19.100 回答
0

如果您怀疑 JSON 文档可能格式不正确,我建议将该文档提交给JSONLint。该工具将美化文档格式,并突出在解析过程中遇到的任何结构或样式问题。我过去曾使用此工具在 JSON 文档生成器中查找多余的逗号和断引号。

于 2012-12-24T05:23:26.193 回答
0

我以前发现过这种格式设计不佳的 JSON API。这可能不是最好的解决方案,但这是我用来将这种输出转换为包含列表中所有结果对象的 dict 的一个小函数。

def json_parse(data):
    d = data.strip().replace("\n\n", ",")
    d = '{"result":[' + d + ']}'
    return json.loads(d)

您可能需要稍微修改一下,具体取决于分隔它们的换行符的数量等。读取文件.read()并调用json_parse数据,您应该能够通过访问data["results"].

如果您可以让您的抓取结果提供有效的 JSON,那就更好了,但与此同时,这样的事情也可以工作。

于 2012-12-24T05:27:03.150 回答