Cześć.
Mam skrypt, który pobiera mi zawartość strony www i zapisuje do pliku txt. Strona kodowana jest w iso-8859-2 i jeśli próbuję normalnie to zapisać, dostaję błąd "UnicodeEncodeError: 'ascii' codec can't encode character u'\xb3' in position ...". Jak wykorzystam kodowanie utf-8, to zapisuje bez błędu, ale w pliku są 'krzaczki' typu: ¿ ³. Jak temu zaradzić? Przeczytałem sporo wątków, ale nie znalazłem nic, co rozwiązałoby mój problem.
Jeśli dobrze cie rozumiem to data = data.decode("iso-8859-2").encode("utf-8")
Niestety nie pomogło. Wrzucę jeszcze cały błąd, dla jasności, choć raczej dobrze zrozumiałeś.
strona = strona.decode("iso-8859-2").encode("utf-8")
File "/usr/lib/python2.7/encodings/iso8859_2.py", line 15, in decode
return codecs.charmap_decode(input,errors,decoding_table)
UnicodeEncodeError: 'ascii' codec can't encode character u'\xb3' in position 339: ordinal not in range(128)
Jak dla mnie z tego wynika że te twoje dane wcale nie są iso8859-2
Początek strony: "<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-2">", a do tego, jak pobiorę ręcznie i sprawdzę format to też jest taki.
Wrzuc jakis przykładowy plik z danymi może? ;]
Przykładowa pobrana strona po wymuszeniu utf-8.
Nie no ja chce oryginalny plik, bo to co wrzuciłeś jest już bezużyteczne.
Oryginalny plik, pobrany prosto ze strony. Choć raczej niczym się nie różni od tamtego, poza tymi polskimi znakami.
No ale to co teraz wstawiłeś to jest UTF-8, więc ja w ogóle nie rozumiem o co chodzi ;]
plik.htm: HTML document, UTF-8 Unicode text, with very long lines
Ajć, mój błąd, późno już i walnąłem głupotę. Tutaj wrzucam jeszcze raz.
No i robisz to co napisałem na samym początku:
import codecs
with codecs.open("in.htm") as f:
data = f.read()
with codecs.open("out.htm", "w") as o:
o.write(data.decode("iso-8859-2").encode("utf-8"))
I voila, masz plik out.htm
kodowany w UTF-8. W czym jest problem?
To chyba jednak do końca się nie zrozumieliśmy. Ja ogólnie tego pliku fizycznie nie mam, dopiero pobieram go przez pyhtona, przez requests i wtedy pojawia się ten problem. Tutaj wysłałem ci plik, który ręcznie pobrałem.
No, chyba się nie rozumiemy, bo cały czas nie potrafisz zaprezentować jaki problem u ciebie występuje. Potrafisz podać kroki do reprodukcji twojego błędu? Bo ja cały czas nie widzę gdzie tu występuje jakikolwiek problem.
edit:
<code=python<>
import codecs
import requests
x = requests.get("http://polwro.pl/t,godzina-podania-wynikow,27555")
with codecs.open("out.htm","w") as o:
o.write(x.content.decode("iso-8859-2").encode("UTF-8"))
Pobieram losowy temat z tego twojego forum i zapisuje go do pliku out.htm z kodowaniem UTF-8. Nadal nie rozumiem gdzie jest problem.
Dobra, to spróbuję od początku. Otóż mam taki kawałek kodu:
#!/usr/bin/env python
#!/bin/bash
import requests
import sys
import subprocess
import os
import linecache
import time
import codecs
#-*- coding: utf-8 -*-
reload(sys)
sys.setdefaultencoding('utf8')
name = "****"
passwd = "******"
temp_file = open('strona.txt', 'w')
session = requests.session()
cookies = {}
url_login = 'http://polwro.pl/login.php'
login_request = requests.get(url_login, cookies=cookies)
login_page = login_request.text
cookies = login_request.cookies
session = requests.post(url_login, data={'username': name, 'password': passwd, "login": "Zaloguj"}, cookies=cookies)
strony = [0, 50, 100, 150, 200, 250, 300, 350, 400, 450, 500, 550, 600]
page = [6, 7, 8, 9, 10, 11, 12, 25]
for petla in page:
for petelka in strony:
session = requests.get("http://polwro.pl/viewforum.php?f="+str(petla)+"&topicdays=0&start="+str(petelka), cookies=cookies)
strona = session.text
temp_file = open('strona.txt', 'w')
temp_file.write(strona);
temp_file.close()
Po prostu pobiera on podstrony z forum. I w tym momencie w pliku 'strona.txt' są krzaczki zamiast niektórych polskich znaków. Natomiast jeśli usunę linię 'sys.setdefaultencoding('utf8')' to wyrzuca błąd taki jak na pierwszej stronie.
- Patrz mój edytowany post
- reuqest.text zwraca ci dane jako unicode więc potrzebujesz je encokodować tylko jeśli już, jeśli pobierzesz request.content tak jak ja to dostaniesz je kodowane w tym iso8859-2
Dobra, teraz zadziałało. Problem leżał albo w tym, że nie otwierałem pliku przez 'codecs' albo używał .text zamiast .content.
W każdym razie wielkie dzięki za pomoc!
Problem raczej w tym że próbowałes zgadywać ;) Pod debugerem od razu widziałbyś że .text
zwraca ci dane jako unicode a nie jako enkodowanego stringa, w przeciwieństwie do .content
.
Masz rację, ale z pythonem dopiero zaczynam, można powiedzieć. Wszystkiego uczę się na bieżąco i w sumie tylko dlatego, że akurat jest mi potrzebny. To tylko część programu, reszta jest w C++.
Jeszcze raz dzięki, teraz na pewno będę o tym pamiętał.