所以我正在阅读一个网站的json,这是我输出的一部分
{"objects": [{"first_name": "Pascale", "last_name": "D\u00e9ry",...
在搜索中我看到\ u00e9是与é相对应的unicode字符。好吧,我明白了。然而,当试图解决它时,我认为我应该在从网站上读取数据时使用.encode(),如下所示:
import urllib
i=0
j=250
while i<2000:
with urllib.request.urlopen(r"https://represent.opennorth.ca/candidates/house-of-commons/?limit=250&offset={}".format(i)) as url:
with open(r"F:\electoral_map\candidates_python\candidates{0}_to_{1}.js".format(i,j), "wb+") as f:
f.write(url.read().encode('utf-8'))
i+=250
j=i+250
print("all done")
然后我才得到错误
AttributeError: 'bytes' object has no attribute 'encode'
我向后退了吗?我也试过.decode('utf-8'),但这也行不通。 (获取TypeError:'str'不支持缓冲区接口)
我应该提到我使用的是Python 3。
答案 0 :(得分:0)
如果您的真正目标是将数据存储在电子表格中,请尝试以下程序:
import requests
import csv
import json
base_url="https://represent.opennorth.ca/candidates/house-of-commons/?limit=250&offset={}"
#base_filename=r"F:\electoral_map\candidates_python\candidates{0}_to_{1}.csv"
base_filename=r"candidates{0}_to_{1}.csv"
keys = [
'name',
'first_name',
'last_name',
'election_name',
'elected_office',
'district_name',
'email',
'incumbent',
'party_name',
'personal_url',
'photo_url',
'source_url',
'url',
]
for i in range(0, 2000, 250):
url = base_url.format(i)
filename=base_filename.format(i, i+250)
data = requests.get(url)
data = data.text
data = json.loads(data)
data = data['objects']
with open(filename, 'wt', encoding='utf-8') as f:
w = csv.DictWriter(f, keys, extrasaction='ignore')
w.writeheader()
w.writerows(data)
注意:此程序需要Python3。如果您使用的是Python2,请告诉我,我会尝试为您提供适用于该版本的版本。
答案 1 :(得分:0)
在这种情况下,decode()
对下载的JSON字符串是适当的。
考虑这个简化的示例,它将通过在URL中指定limit=1&offset=0
来下载单个候选人的JSON:
>>> from urllib.request import urlopen
>>> url = urlopen('https://represent.opennorth.ca/candidates/house-of-commons/?limit=1&offset=0')
>>> content = url.read()
>>> print(type(content))
<class 'bytes'>
>>> print(url.getheader('Content-Type'))
application/json; charset=utf-8
>>> content
b'{"objects": [{"first_name": "Pascale", "last_name": "D\\u00e9ry", "election_name": "House of Commons", "name": "Pascale D\\u00e9ry", "elected_office": "candidate", "url": "", "gender": "", "extra": {}, "related": {"boundary_url": "/boundaries/federal-electoral-districts-next-election/24025/", "election_url": "/elections/house-of-commons/"}, "source_url": "http://www.conservative.ca/?member=candidates", "offices": [], "party_name": "Conservative", "incumbent": null, "district_name": "Drummond", "email": "", "personal_url": "http://www.conservative.ca/team/member/?fname=Pascale&lname=D\\u00e9ry&type=candidates", "photo_url": "http://www.conservative.ca/media/team/Pascale-Dery.jpg"}], "meta": {"next": "/candidates/house-of-commons/?limit=1&offset=1", "total_count": 1129, "previous": null, "limit": 1, "offset": 0}}'
由此我们看到内容是字节类型,即字节字符串。字节字符串没有encode()
方法;假定它们已经在某些编码中,并且只能使用正确的编码解码为unicode。在这种情况下,数据是UTF-8编码的JSON,如Content-Type
标题所示。
你可以在这里做很多事情:
以二进制模式打开输出文件,只需编写JSON字符串即可 就像文件一样。因为传入的数据是UTF-8编码的 将导致UTF-8编码的JSON文件,这可能是什么 CSV转换器期望:
with open('output.json', 'wb') as f:
f.write(content)
使用支持的编码以文本模式打开输出文件 CSV转换器,将来自UTF-8的传入JSON字符串解码为文本 string(unicode),并将解码后的字符串写入文件:
with open('output.json', 'w', encoding='iso-8859-1') as f:
f.write(content.decode('utf-8'))
这里我选择了iso-8859-1编码作为示例,您也可以选择ASCII。请注意,如果编码为UTF-8,则会对数据进行解码,然后将数据重新编码为UTF-8,因此您也可以按原样编写数据。
另一个选项,也就是我推荐的选项,是使用JSON解码器解码传入的数据,然后使用您的首选编码将其写入文件。这样做的好处是可以确保传入的数据实际上是JSON,并允许您在切换到CSV转换器之前发现任何错误:
import json
with open('output.json', 'w') as f:
data = json.loads(content.decode('utf8'))
json.dump(data, f)
您实际上可能会发现使用requests
模块更容易。它具有内置的JSON解析和字符解码:
>>> import requests
>>> r = requests.get('https://represent.opennorth.ca/candidates/house-of-commons/?limit=1&offset=0')
>>> type(r.text)
>>> type(r.content)
>>> data = r.json()
>>> data
{'objects': [{'first_name': 'Pascale', 'extra': {}, 'url': '', 'last_name': 'Déry', 'district_name': 'Drummond', 'incumbent': None, 'offices': [], 'gender': '', 'personal_url': 'http://www.conservative.ca/team/member/?fname=Pascale&lname=Déry&type=candidates', 'elected_office': 'candidate', 'party_name': 'Conservative', 'source_url': 'http://www.conservative.ca/?member=candidates', 'election_name': 'House of Commons', 'email': '', 'name': 'Pascale Déry', 'photo_url': 'http://www.conservative.ca/media/team/Pascale-Dery.jpg', 'related': {'boundary_url': '/boundaries/federal-electoral-districts-next-election/24025/', 'election_url': '/elections/house-of-commons/'}}], 'meta': {'total_count': 1129, 'limit': 1, 'next': '/candidates/house-of-commons/?limit=1&offset=1', 'previous': None, 'offset': 0}}
此处r.content
是以服务器发送数据的任何编码下载的原始内容。 r.text
是解码为unicode字符串的相同原始内容。 r.json()
为您提供解析后的JSON数据作为字典。将其写入文件就像这样简单:
with open('output.json', 'w') as f:
json.dump(r.json(), f)