Найти - Пользователи
Полная версия: Проблема с кодировкой кириллицы - BeautifulSoup и csv
Начало » Python для новичков » Проблема с кодировкой кириллицы - BeautifulSoup и csv
1 2
roloyar
Всем здрасьте! Я в питоне новичок, так что не судите строго. За советы заранее спасибо!

Цель - построить простой скрейпер. Конкретнее, имеется задача - используя mechanize зайти на украиноязычный сайт (сайт Верховной Рады, но думаю детали тут не так важны), используя BeautifulSoup вытащить из таблицы текст (только из одного столбца), немного его обработать (убрать HTML тэги и т.п.) и записать его с помощью модуля csv в файл.

Вот мой код:

from BeautifulSoup import BeautifulSoup
from mechanize import Browser
import csv
url = 'http://w1.c1.rada.gov.ua/pls/zweb2/webproc4_1?pf3511=48671'
br = Browser()
br.open(url)
soup = BeautifulSoup(br.response())
div = soup.find('div', attrs={'class':'zp-info'})
content = div.findAll('dd')
output = []
for d in content:
    output.append(d.text.strip().split(','))
outfile = open('test_out.txt', 'w')
writer = csv.writer(outfile)
writer.writerows(output)

В результате получаю ошибку:
UnicodeEncodeError: 'ascii' codec can't encode characters in position 5-7: ordinal not in range(128)
Если просто сделать
print output
вылезает, как я понимаю, список с юникод-символами вместо букв.

Перепробовал уже много всего. Ближе всего к цели пришел сделав следующее:
proper = repr(output).decode('raw_unicode_escape')
print proper
Но тут проблема в том, что это получается не список (что мне нужно для модуля csv) а unicode-объект.

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

Очень еще раз заранее спасибо за любые советы и помощь!
sanodin
# coding: cp1251
import csv
rows=[[u'\xca\xe0\xe1\xb3\xed\xe5\xf2 '], [u'3 \xf1\xe5\xf1\xb3\xff VII \xf1\xea\xeb\xe8\xea\xe0\xed\xed\xff']]
outfile = open('test_out.txt', 'w')
writer = csv.writer(outfile)
for i in rows:
    result = ''.join(i)
    print result.encode('ISO 8859-1')
    writer.writerows(result.encode('ISO 8859-1'))
s = u'\xf1'
print s.encode('ISO 8859-1')
rows==output
roloyar
sanodin
# coding: cp1251
import csv
rows=[[u'\xca\xe0\xe1\xb3\xed\xe5\xf2 '], [u'3 \xf1\xe5\xf1\xb3\xff VII \xf1\xea\xeb\xe8\xea\xe0\xed\xed\xff']]
outfile = open('test_out.txt', 'w')
writer = csv.writer(outfile)
for i in rows:
    result = ''.join(i)
    print result.encode('ISO 8859-1')
    writer.writerows(result.encode('ISO 8859-1'))
s = u'\xf1'
print s.encode('ISO 8859-1')
rows==output
Sanodin, большое спасибо! Но, к сожалению, проблему не решило.

Дело в том, что на выходе если сделать
print output
то я получаю
[[u'3424 \u0432\u0456\u0434 14.10.2013'], [u'3 \u0441\u0435\u0441\u0456\u044f VII \u0441\u043a\u043b\u0438\u043a\u0430\u043d\u043d\u044f'],...
и так далее, весь список содержит, если я правильно понимаю, символы кириллицы закодированные в юникоде (я еще только пытаюсь со всеми этими кодировками разобраться). То есть исходник у меня не в cp1251. Следовательно ничего с ним потом по инструкции sanodin не получается.

Если я попытаюсь сделать
print output.encode('ISO 8859-1')
то получаю
AttributeError: 'list' object has no attribute 'encode'
Это, впрочем, вполне ожидаемо, так как это список. Но даже если взять один элемент из этого списка и попытаться сделать xxx.encode('ISO 8859-1') то выходит то же самое, что выше в
print output
короче символы вообще не меняются.

Я практически уверен, что все ломается на стадии for при записи значений в список:
for d in content:
	output.append(d.text.strip().split(','))
Если просто записывать, без .text.strip().split(',')) все остается в той кодировке, в которой было (но с разметкой которая мне не нужна), если я пытаюсь используя .text.strip().split(',')) избавиться от HTML разметки, на выходе получаю кашу…

И еще, sanodin, если запустить твой скрипт, то он запишет в test_out.txt все символы из result по одному символу на строке. Несмотря даже на то, что
type(result)
возвращает
<type 'list'>
Я сам не понимаю, почему, но говорю просто раз заметил…

Эх, надеюсь я с этим таки разберусь.
sanodin
Все работает…не понимаю, объясните что нужно
from BeautifulSoup import BeautifulSoup
from mechanize import Browser
import csv
url = 'http://w1.c1.rada.gov.ua/pls/zweb2/webproc4_1?pf3511=48671'
br = Browser()
br.open(url)
soup = BeautifulSoup(br.response())
div = soup.find('div', attrs={'class':'zp-info'})
content = div.findAll('dd')
output = []
for d in content:
    output.append(d.text.strip().split(','))
outfile = open('test_out.txt', 'w')
writer = csv.writer(outfile)
for i in output:
    result = ''.join(i)
    print result.encode('ISO 8859-1')
    writer.writerows(result.encode('ISO 8859-1'))
единственное, записывает в файл по одному символу в строке, ну это Вы и сами переделаете
bismigalis
csv модуль из python2 напрямую не работает с unicode, поэтому ему надо отдавать закодированную информацию
roloyar
sanodin
Все работает…не понимаю, объясните что нужно
from BeautifulSoup import BeautifulSoup
from mechanize import Browser
import csv
url = 'http://w1.c1.rada.gov.ua/pls/zweb2/webproc4_1?pf3511=48671'
br = Browser()
br.open(url)
soup = BeautifulSoup(br.response())
div = soup.find('div', attrs={'class':'zp-info'})
content = div.findAll('dd')
output =
for d in content:
output.append(d.text.strip().split(','))
outfile = open('test_out.txt', ‘w’)
writer = csv.writer(outfile)
for i in output:
result = ‘'.join(i)
print result.encode(’ISO 8859-1')
writer.writerows(result.encode('ISO 8859-1'))
единственное, записывает в файл по одному символу в строке, ну это Вы и сами переделаете
У меня если запустить скрипт в чистом виде (как у вас) то выдает ошибку:
UnicodeEncodeError: ‘latin-1’ codec can't encode characters in position 5-7: ordinal not in range(256)
roloyar
bismigalis
csv модуль из python2 напрямую не работает с unicode, поэтому ему надо отдавать закодированную информацию
Закодированную в каком виде?
sanodin
а просто в cp1251 ?
это
u'3424 \u0432\u0456\u0434 14.10.2013'

u=u'3424 \u0432\u0456\u0434 14.10.2013'
print u.encode('cp1251')
roloyar
sanodin
а просто в cp1251 ?
это
u'3424 \u0432\u0456\u0434 14.10.2013'

u=u'3424 \u0432\u0456\u0434 14.10.2013'
print u.encode('cp1251')

Так все получается. даже если просто сделать print u. Я думаю проблема в том, что у все это с списке. А список так и отображается - списком со значками, а не читабельным текстом. и csv его не воспринимает.
sanodin
у вас список списков, переделать в строку и все
а в моем коде вы так делали ?
.encode('cp1251')
.decode('cp1251')
кодировками пробуйте подобрать
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB