2012-12-24 60 views
2

我有一個json文件,存儲一些用戶信息,包括id,名稱和url。該json文件看起來像如何在scrapy中讀取json文件中的行

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

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

此文件是由scrapy蜘蛛寫的。現在我想從json文件中讀取url,並抓取每個用戶的網頁。但我無法從json文件加載數據。

在這個時候,我不知道如何獲得這些網址。我想我應該首先閱讀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管道創建和填充項目的。是否有人知道是什麼原因導致了錯誤?以及如何解決它?有關閱讀網址的任何建議?

非常感謝,

奧利維亞

+0

你肯定有每個JSON對象之間的空行?你可以確認,以及scrapy版本。 –

回答

0

如果懷疑一個JSON文件可畸形,我建議將文件提交給JSONLint。該工具將對文檔格式進行優化,並突出顯示解析過程中遇到的任何結構或樣式問題。過去,我使用這個工具在JSON文檔生成器中查找額外的逗號和斷開的引號。

+0

erm ...提供的例子顯然是畸形的:'json.loads('{} {}')'給出了一個類似的錯誤。 – SingleNegationElimination

0

我以前發現這種格式與設計不佳的JSON API有關。這可能不是最好的解決方案,但這是一個小函數,我用它將這種輸出轉換爲包含列表中所有結果對象的字典。

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

根據分隔它們的換行符數量等,您可能需要修改一下。用.read()讀取文件並在數據上調用json_parse,並且您應該可以通過訪問data["results"]來遍歷所有內容。

如果你可以讓你的抓取結果提供有效的JSON,會更好,但同時這樣的事情可以工作。

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() 
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編碼行的文件」

5

這些是出口商名稱暗示的json行。

看看scrapy.contrib。出口商和看JsonItemExporter和JsonLinesItemExporter

之間的差別這應該做的伎倆:

import json 

lines = [] 

with open('links.jl', 'r') as f: 
    for line in f: 
     lines.append(json.loads(line))