Scraping-ul funcționează bine până când primesc această eroare: codecul ‘ascii’ nu poate codifica caracterul u’u2122′ în poziția (Programare, Python, Json, Ascii, Răzuirea Ecranului)

Isak a intrebat.

Am doar câteva săptămâni de pregătire în python, așa că bănuiesc că există o soluție simplă la această problemă. Dar pentru mine este destul de frustrantă și după ce am lucrat câteva ore la asta, acum vă cer ajutorul!

Site-ul pe care încerc să îl răzuiesc este bine organizat (vezi https://twam2dcppennla6s.onion.to/), iar codul pe care l-am scris răzuiește cam jumătate din cele 26 de pagini până când primesc acest mesaj de eroare:

Traceback (most recent call last):
  File "SR2works4real2.py", line 18, in <module>
    csvWriter.writerows(jsonObj['vendors'])
  File "/usr/lib/python2.7/csv.py", line 154, in writerows
    return self.writer.writerows(rows)
UnicodeEncodeError: 'ascii' codec can't encode character u'u2122' in position 8: ordinal not in range(128)

Codul meu este:

import urllib2, json,csv
htmlTxt=""


urlpart1='https://twam2dcppennla6s.onion.to/vendors.php?_dc=1393967362998&start='
pageNum=0   
urlpart2='&limit=30&sort=%5B%7B%22property%22%3A%22totalFeedback%22%2C%22direction%22%3A%22DESC%22%7D%5D'
csvFile=open('S141.csv','wb')
csvWriter=csv.DictWriter(csvFile,['name','vendoringTime','lastSeen','avgFeedback','id','totalFeedback','united','shipsTo','shipsFrom'],delimiter=',', quotechar='"', quoting=csv.QUOTE_ALL)
csvWriter.writeheader()

while htmlTxt != "{"vendors":[]}":
    print("Page "+str(pageNum)+"...")
    pageNum+=30
    response=urllib2.urlopen((urlpart1)+str(pageNum)+(urlpart2))
    htmlTxt=response.read()
    htmlTxt.encode('utf-8')
    jsonObj=json.loads(htmlTxt)
    csvWriter.writerows(jsonObj['vendors'])

    #print(str(jsonObj))

csvFile.close()

Sper că există cineva care mă poate ajuta!

Comentarii

  • Probabil că va trebui să decode caracterele care nu încap în ASCII. La csv spune că nu suportă Unicode, dar menționează că puteți folosi utf8, așa că poate că există altceva ce puteți face cu modulul dvs. encode-(dar nu sunt sigur ce). –  > Por 2rs2ts.
2 răspunsuri
Aaron Hall

Acesta este unicode pentru simbolul mărcii comerciale: http://www.marathon-studios.com/unicode/U2122/Trade_Mark_Sign

Din moment ce faci scraping web, probabil că vei vedea mult mai multe erori de acest tip, așa că înlocuirea ar putea funcționa pentru această pagină, dar nu și pentru altele cu alte simboluri.

Modulul csv convertește unicode-ul în ascii înainte de a-l scrie. V-aș recomanda să faceți același lucru înainte de a-i da textul și să îl curățați voi înșivă, adică, în loc de

htmlTxt.encode('utf-8')

do

htmlTxt.encode('ascii', 'ignore')

Și apoi verificați textul pentru a vedea dacă este acceptabil pentru scopurile dumneavoastră.

EDIT

Iată rezultatul meu în Python 3:

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

și Python 2.6:

>>> u'u2122'.encode('ascii')
Traceback (most recent call last):
  File "<pyshell#92>", line 1, in <module>
    u'u2122'.encode('ascii')
UnicodeEncodeError: 'ascii' codec can't encode character u'u2122' in position 0: ordinal not in range(128)
>>> u'u2122'.encode('ascii', 'ignore')
''

Comentarii

  • Vă mulțumim foarte mult pentru ajutor! De fapt, am primit un mesaj de eroare similar după ce am făcut acest lucru: Traceback (ultimul apel cel mai recent): File „SR2works4real2.py”, line 18, in <module> csvWriter.writerows(jsonObj[‘vendors’]]) File „/usr/lib/python2.7/csv.py”, line 154, in writerows return self.writer.writerows(rows) UnicodeEncodeError: codecul ‘ascii’ nu poate codifica caracterul u’u2122′ în poziția 8: ordinal not in range(128) –  > Por Isak.
  • @user3343907 Văd că sunteți nou pe site, Bine ați venit pe Stackoverflow, dacă acceptați un răspuns făcând clic pe semnul de verificare de lângă el, atunci veți primi automat +2 la reprezentantul dvs. –  > Por Aaron Hall.
  • @user334343907 ai folosit steagul „ignore”? pentru mine funcționează în Python 2.6 și 3.3. –  > Por Aaron Hall.
  • Bună! Continui să primesc aceeași eroare, după ce am inclus htmlTxt.encode(‘ascii’, ‘ignore’) și u’u2122′.encode(‘ascii’, ‘ignore’) în cod =( – –  > Por Isak.
  • Acesta este mesajul de eroare pe care îl primesc după ce am adăugat elementele din comentariul de mai sus:Traceback (most recent call last): File „SR2.py”, line 19, in <module> csvWriter.writerows(jsonObj[‘vendors’]]) File „/usr/lib/python2.7/csv.py”, line 154, in writerows return self.writer.writerows(rows) UnicodeEncodeError: codecul ‘ascii’ nu poate codifica caracterul u’u2122′ în poziția 8: ordinal not in range(128) –  > Por Isak.
Heikki Toivonen

Șirurile de caractere din jsonObj vor fi în unicode deoarece Python json va produce șiruri unicode. Scriitorul dvs. csv dorește ca totul să fie în str tip. În Python 2.7, acesta va încerca să convertească automat unicode tip în str tip presupunând ASCII. Acest lucru va eșua, desigur, dacă tipul unicode nu conține ASCII.

Cea mai simplă soluție ar fi să modificați această linie:

csvWriter.writerows(jsonObj['vendors'])

pentru a codifica unicode în str în utf8 chiar înainte de a trimite la scriitorul csv. jsonObj['vendors'] este o listă de dicționare cu chei și valori unicode, deci putem face acest lucru:

unicode_vendors = jsonObj['vendors']
str_vendors = []
for unicode_dict in unicode_vendors:
    str_dict = {}
    for key, value in unicode_dict.items():
        str_dict[key.encode('utf8')] = value.encode('utf8') if value else value
    str_vendors.append(str_dict)
csvWriter.writerows(str_vendors)

Comentarii

  • Vă mulțumim pentru ajutor! De fapt, am primit un mesaj de eroare după ce am făcut acest lucru: Traceback (ultimul apel cel mai recent): Fișier „SR2works4real2.py”, linia 18, in <module> csvWriter.writerows(jsonObj[‘vendors’].encode(‘utf8’))) AttributeError: obiectul ‘list’ nu are atributul ‘encode’ –  > Por Isak.
  • Ah, nu mi-am dat seama că este o listă. Am modificat răspunsul, ceea ce ar trebui să rezolve problema. –  > Por Heikki Toivonen.
  • Mulțumesc! Am încercat și am primit acest mesaj de eroare: Traceback (ultimul apel cel mai recent): File „SR2works4real3.py”, line 20, in <module> str_vendors = [s.encode(‘utf8’) for s in unicode_vendors] AttributeError: obiectul ‘dict’ nu are atributul ‘encode’ –  > Por Isak.
  • Bine, a trebuit să vă execut aplicația pentru a afla ce date erau în jsonObj[‘vendors’]. Este o listă de dicționare în care cheile și valorile sunt șiruri unicode, iar unele valori erau, de asemenea, None. Ai fi putut afla cu ușurință acest lucru prin imprimarea unora dintre acestea și includerea lor în întrebare. Oricum, după ce am rulat aplicația cu aceste modificări, pare să funcționeze pentru mine, folosind Python 2.7.6 pe Mac. –  > Por Heikki Toivonen.
  • Fantstic, funcționează! Mulțumesc mult pentru ajutor, Heikki! –  > Por Isak.