UnicodeEncodeError в веб-браузере BeautifulSoup - PullRequest
0 голосов
/ 03 февраля 2019

У меня ошибка кодировки Unicode со следующим кодом для простого веб-скребка.

print 'JSON scraper initializing'

from bs4 import BeautifulSoup
import json
import requests
import geocoder


# Set page variable
page = 'https://www.bandsintown.com/?came_from=257&page='
urlBucket = []
for i in range (1,3):
    uniqueUrl = page + str(i)
    urlBucket.append(uniqueUrl)

# Build response container
responseBucket = []

for i in urlBucket:
    uniqueResponse = requests.get(i)
    responseBucket.append(uniqueResponse)


# Build soup container
soupBucket = []
for i in responseBucket:
    individualSoup = BeautifulSoup(i.text, 'html.parser')
    soupBucket.append(individualSoup)


# Build events container
allSanFranciscoEvents = []
for i in soupBucket:
    script = i.find_all("script")[4]

    eventsJSON = json.loads(script.text)

    allSanFranciscoEvents.append(eventsJSON)


with open("allSanFranciscoEvents.json", "w") as writeJSON:
   json.dump(allSanFranciscoEvents, writeJSON, ensure_ascii=False)
print ('end')

Иногда странно, этот код работает и не выдает ошибку.Это связано со строкой for i in range кода.Например, если я введу (2,4) для диапазона, он работает нормально.Если я изменю его на 1,3,, то будет написано:

UnicodeEncodeError: 'ascii' codec can't encode character u'\xe9' in position 12: ordinal not in range(128)

Может кто-нибудь сказать мне, как исправить эту проблему в моем коде?Если я печатаю allSanFranciscoEvents, он читает все данные, поэтому я считаю, что проблема возникает в последнем фрагменте кода, с дампом JSON.Большое спасибо.

Ответы [ 2 ]

0 голосов
/ 03 февраля 2019

eventsJSON - объект, который он не может использовать eventsJSON.encode('utf-8').Для Python 2.7, чтобы записать файл в utf-8 или в юникоде, вы можете использовать codecs или записать его, используя двоичный файл или флаг wb.

with open("allSanFranciscoEvents.json", "wb") as writeJSON:
   jsStr = json.dumps(allSanFranciscoEvents)
   # the decode() needed because we need to convert it to binary
   writeJSON.write(jsStr.decode('utf-8')) 
print ('end')

# and read it normally
with open("allSanFranciscoEvents.json", "r") as readJson:
    data = json.load(readJson)
    print(data[0][0]["startDate"])
    # 2019-02-04
0 голосов
/ 03 февраля 2019

Best Fix

Используйте Python 3!Python 2 очень скоро станет EOL .Новый код, написанный на устаревшем Python сегодня, будет иметь очень короткий срок годности.

Единственное, что мне пришлось изменить, чтобы заставить ваш код работать в Python 3, это вызвать функцию print() вместо printключевое слово.Ваш пример кода работал без ошибок.

Сохранение с Python 2

Странно то, что иногда этот код работает и не даетошибка.Это связано с тем, что я в строке кода.Например, если я введу (2,4) для диапазона, он будет работать нормально.

Это потому, что вы запрашиваете разные страницы с этими разными диапазонами, и не каждая страница имеет символ, которыйне может быть преобразован в str с использованием кодека ascii.Мне пришлось перейти на страницу 5 ответа, чтобы получить ту же ошибку, что и вы.В моем случае это было имя художника, u'Mø', которое вызвало проблему.Итак, вот 1 вкладыш, который воспроизводит проблему:

>>> str(u'Mø')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xf8' in position 0: ordinal not in range(128)

Ваша ошибка явно выделяет символ u'\xe9':

>>> str(u'\xe9')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe9' in position 0: ordinal not in range(128)

Та же проблема, только другой символ.Символ латинская строчная буква e с острым .Python пытается использовать кодировку по умолчанию, «ascii», чтобы преобразовать строку Unicode в str, но «ascii» не знает, что такое кодовая точка.

Я считаю,проблема возникает в последнем фрагменте кода с дампом JSON.

Да, это так:

>>> with open('tmp.json', 'w') as f:
...     json.dump(u'\xe9', f, ensure_ascii=False)
...
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
  File "/usr/lib/python2.7/json/__init__.py", line 190, in dump
    fp.write(chunk)
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe9' in position 1: ordinal not in range(128)

И по трассировке вы можете видеть, что это на самом делепри записи в файл (fp.write(chunk)).

file.write() записывает string в файл, но u'\xe9' является unicode объектом.Сообщение об ошибке: 'ascii' codec can't encode character... говорит нам, что python пытается закодировать этот unicode объект, чтобы превратить его в тип str, чтобы он мог записать его в файл.Вызов кодирования для строки Unicode использует «кодировку строки по умолчанию» , которая определяется здесь как «ascii».

Чтобы исправить, не оставляйте этодо Python для использования кодировки по умолчанию:

>>> with open('tmp.json', 'w') as f:
...     json.dump(u'\xe9'.encode('utf-8'), f, ensure_ascii=False)
...
# No error :)

В вашем конкретном примере вы можете исправить прерывистую ошибку, изменив это:

allSanFranciscoEvents.append(eventsJSON)

на следующее:

allSanFranciscoEvents.append(eventsJSON.encode('utf-8'))

Таким образом, вы явно используете кодек utf-8 для преобразования строк Unicode в str, так что python не пытается применить кодировку по умолчанию, ascii, при записи вфайл.

...