Python - проблема с акцентированными символами при очистке данных с сайта - PullRequest
1 голос
/ 08 июля 2011

Я Никола, новый пользователь Python, не имеющий опыта в программировании.Поэтому мне действительно нужна помощь с проблемой, которая у меня есть.Я написал код для очистки данных с этой веб-страницы:

http://finanzalocale.interno.it/sitophp/showQuadro.php?codice=2080500230&tipo=CO&descr_ente=MODENA&anno=2009&cod_modello=CCOU&sigla=MO&tipo_cert=C&isEuro=0&quadro=02

По сути, цель моего кода - очистить данные из всех таблиц на странице и записать их втекстовый файл.Здесь я вставляю свой код:

#!/usr/bin/env python


from mechanize import Browser
from BeautifulSoup import BeautifulSoup
import urllib2, os


def extract(soup):
table = soup.findAll("table")[1]
for row in table.findAll('tr')[1:19]:
        col = row.findAll('td')
        voce = col[0].string
        accertamento = col[1].string
        competenza = col[2].string
        residui = col[3].string
        record = (voce, accertamento, competenza, residui)
        print >> outfile, "|".join(record)

table = soup.findAll("table")[2]
for row in table.findAll('tr')[1:21]:
        col = row.findAll('td')
        voce = col[0].string
        accertamento = col[1].string
        competenza = col[2].string
        residui = col[3].string
        record = (voce, accertamento, competenza, residui)
        print >> outfile, "|".join(record)

table = soup.findAll("table")[3]
for row in table.findAll('tr')[1:44]:
        col = row.findAll('td')
        voce = col[0].string
        accertamento = col[1].string
        competenza = col[2].string
        residui = col[3].string
        record = (voce, accertamento, competenza, residui)
        print >> outfile, "|".join(record)

table = soup.findAll("table")[4]
for row in table.findAll('tr')[1:18]:
        col = row.findAll('td')
        voce = col[0].string
        accertamento = col[1].string
        competenza = col[2].string
        residui = col[3].string
        record = (voce, accertamento, competenza, residui)
        print >> outfile, "|".join(record)

    table = soup.findAll("table")[5]
for row in table.findAll('tr')[1:]:
        col = row.findAll('td')
        voce = col[0].string
        accertamento = col[1].string
        competenza = col[2].string
        residui = col[3].string
        record = (voce, accertamento, competenza, residui)
        print >> outfile, "|".join(record)

    table = soup.findAll("table")[6]
for row in table.findAll('tr')[1:]:
        col = row.findAll('td')
        voce = col[0].string
        accertamento = col[1].string
        competenza = col[2].string
        residui = col[3].string
        record = (voce, accertamento, competenza, residui)
        print >> outfile, "|".join(record)


outfile = open("modena_quadro02.txt", "w")
br = Browser()
br.set_handle_robots(False)
url = "http://finanzalocale.interno.it/sitophp/showQuadro.php?codice=2080500230&tipo=CO&descr_ente=MODENA&anno=2009&cod_modello=CCOU&sigla=MO&tipo_cert=C&isEuro=0&quadro=02"
page1 = br.open(url)
html1 = page1.read()
soup1 = BeautifulSoup(html1)
extract(soup1)
outfile.close()

Все будет работать нормально, но первый столбец некоторых таблиц на этой странице содержит слова с символами ударения.Когда я запускаю код, я получаю следующее:

Traceback (most recent call last):
File "modena2.py", line 158, in <module>
  extract(soup1)
File "modena2.py", line 98, in extract
  print >> outfile, "|".join(record)
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe0' in position 32: ordinal not in range(128)

Я знаю, что проблема заключается в кодировании символов с акцентом.Я пытался найти решение для этого, но это действительно выходит за рамки моих знаний.Я хочу заранее поблагодарить всех, кто собирается мне помочь. Я действительно ценю это!И извините, если вопрос слишком простой, но, как я уже сказал, я только начинаю с python и изучаю все сам.

Спасибо!Nicola

Ответы [ 5 ]

0 голосов
/ 01 июля 2015

Проблема заключается в печати текста Unicode в двоичный файл:

>>> print >>open('e0.txt', 'wb'), u'\xe0'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe0' in position 0: ordinal not in range(128)

Чтобы исправить это, либо закодируйте текст Unicode в байты (u'\xe0'.encode('utf-8')), либо откройте файл в текстовом режиме:

#!/usr/bin/env python
from __future__ import print_function
import io

with io.open('e0.utf8.txt', encoding='utf-8') as file:
    print(u'\xe0', file=file)
0 голосов
/ 24 июня 2015

У меня была похожая проблема на прошлой неделе.Это было легко исправить в моей IDE (PyCharm).

Вот мое исправление:

Начиная со строки меню PyCharm: Файл -> Настройки ... -> Редактор -> Кодировки файлов,затем установите: «Кодировка IDE», «Кодировка проекта» и «Кодировка по умолчанию для файлов свойств» ВСЕ в UTF-8, и теперь она работает как шарм.

Надеюсь, это поможет!

0 голосов
/ 08 июля 2011

Я собираюсь попробовать еще раз, основываясь на отзывах.Поскольку вы используете оператор print для создания выходных данных, ваши выходные данные должны быть байтами, а не символами (это реальность современных операционных систем).По умолчанию в Python sys.stdout (что пишет оператор print) используется кодировка символов ascii.Поскольку ASCII определяет только байтовые значения от 0 до 127, это единственные байтовые значения, которые вы можете распечатать.Следовательно, ошибка для значения байта '\xe0'.

Вы можете изменить кодировку символов sys.stdout на UTF-8, выполнив следующее:

import codecs, sys
sys.stdout = codecs.getwriter('UTF-8')(sys.stdout)
print u'|'.join([u'abc', u'\u0100'])

Приведенный выше оператор печати не будет жаловатьсяо печати строки Unicode, которая не может быть представлена ​​в кодировке ASCII.Однако приведенный ниже код, который печатает байты, а не символы, создает исключение UnicodeDecodeError, так что будьте осторожны:

import codecs, sys
sys.stdout = codecs.getwriter('UTF-8')(sys.stdout)
print '|'.join(['abc', '\xe0'])

Возможно, вы обнаружите, что ваш код пытается печатать символы, и это устанавливает кодировку символов sys.Стандартный вывод в UTF-8 (или ISO-8859-1) исправляет это.Но вы можете обнаружить, что код пытается напечатать байты (полученные из API BeautifulSoup), и в этом случае исправление может выглядеть примерно так:

import codecs, sys
sys.stdout = codecs.getwriter('UTF-8')(sys.stdout)
print '|'.join(['abc', '\xe0']).decode('ISO-8859-1')

Я не знаком с пакетом BeautifulSoup,но я советую протестировать его с различными документами, чтобы убедиться в правильности определения кодировки символов.Ваш код явно не предоставляет кодировку, и он явно выбирает кодировку самостоятельно.Если это решение исходит из тега кодирования meta, тогда отлично.

0 голосов
/ 11 июля 2011

edit: я только что попробовал, и, как я предполагаю, вы хотите таблицу в конце, вот решение, которое приводит к CSV.

from mechanize import Browser
from BeautifulSoup import BeautifulSoup
import urllib2, os
import csv


def extract(soup):
    table = soup.findAll("table")[1]
    for row in table.findAll('tr')[1:19]:
            col = row.findAll('td')
            voce = col[0].string
            accertamento = col[1].string
            competenza = col[2].string
            residui = col[3].string
            record = (voce, accertamento, competenza, residui)
            outfile.writerow([s.encode('utf8') if type(s) is unicode else s for s in record])

    # swap print for outfile statement in all other blocks as well
    # ... 

outfile = csv.writer(open(r'modena_quadro02.csv','wb'))
br = Browser()
br.set_handle_robots(False)
url = "http://finanzalocale.interno.it/sitophp/showQuadro.php?codice=2080500230&tipo=CO&descr_ente=MODENA&anno=2009&cod_modello=CCOU&sigla=MO&tipo_cert=C&isEuro=0&quadro=02"
page1 = br.open(url)
html1 = page1.read()
soup1 = BeautifulSoup(html1)
extract(soup1)
0 голосов
/ 08 июля 2011

Попробуйте изменить эту строку:

html1 = page1.read()

На это:

html1 = page1.read().decode(encoding)

, где encoding будет, например, 'UTF-8', 'ISO-8859-1' и т. Д. I 'Я не знаком с пакетом mechanize, но, надеюсь, есть способ обнаружить кодировку документа, возвращаемого методом read().Похоже, что метод read() дает вам байтовую строку, а не символьную строку, и поэтому вызов join позднее должен принять ASCII в качестве кодировки.

...