Muchos de los tweets que estoy importando tienen este problema donde leen
b'I posted a new photo to Facebook'
Recojo el b
indica que es un byte. Pero esto está resultando problemático porque en mis archivos CSV que termino escribiendo, b
no desaparecen e interfieren en el código futuro.
¿Existe una forma sencilla de eliminar este b
prefijo de mis líneas de texto?
Tenga en cuenta que parece que necesito tener el texto codificado en utf-8 o tweepy tiene problemas para sacarlo de la web.
Aquí está el contenido del enlace que estoy analizando:
https://www.dropbox.com/s/sjmsbuhrghj7abt/new_tweets.txt?dl=0
new_tweets = 'content in the link'
Intento de código
outtweets = [[tweet.text.encode("utf-8").decode("utf-8")] for tweet in new_tweets]
print(outtweets)
Error
UnicodeEncodeError Traceback (most recent call last)
<ipython-input-21-6019064596bf> in <module>()
1 for screen_name in user_list:
----> 2 get_all_tweets(screen_name,"instance file")
<ipython-input-19-e473b4771186> in get_all_tweets(screen_name, mode)
99 with open(os.path.join(save_location,'%s.instance' % screen_name), 'w') as f:
100 writer = csv.writer(f)
--> 101 writer.writerows(outtweets)
102 else:
103 with open(os.path.join(save_location,'%s.csv' % screen_name), 'w') as f:
C:\Users\Stan Shunpike\Anaconda3\lib\encodings\cp1252.py in encode(self, input, final)
17 class IncrementalEncoder(codecs.IncrementalEncoder):
18 def encode(self, input, final=False):
---> 19 return codecs.charmap_encode(input,self.errors,encoding_table)[0]
20
21 class IncrementalDecoder(codecs.IncrementalDecoder):
UnicodeEncodeError: 'charmap' codec can't encode characters in position 64-65: character maps to <undefined>
Respuestas:
necesitas decodificar el
bytes
que quieres una cadena:b = b'1234' print(b.decode('utf-8')) # '1234'
fuente
.encode("utf-8").decode("utf-8")
no hace absolutamente nada (si funciona) ... estás en Python 3, ¿verdad? py3 tiene una fuerte distinción entrebytes
ystr
. algo en su código parece usar lacp1252
codificación ... podría intentar abrir su archivo conopen(..., mode='w', encoding='utf-8')
y solo escribirstr
en el archivo; o te olvidas de toda la codificación y escribes el archivo en binario:open(..., mode='wb')
(nota elb
) y solo escribebytes
. ¿Eso ayuda?"b'Due to the storms this weekend, we have rescheduled the Blumenfield Bike Ride for Feb 26. Hope to see you there.\xe2\x80\xa6'"
.encode("utf-8").decode("utf-8")
que haría nada, pero la gente aquí parecía pensar que esa era la respuesta correcta, que no es hasta donde puedo ver.C:\Users\Stan Shunpike\Anaconda3\lib\encodings\cp1252.py
. probablemente debería intentar averiguar cómo / dónde se usa. oh, y estás usandocsv.writer
; en ese caso, debe escribirstr
un nobytes
. estás recibiendo cosas derequests
? la codificación que obtiene de un recurso web puede diferir deutf-8
.Solo le permite saber que el objeto que está imprimiendo no es una cadena, sino un objeto de byte como un byte literal . La gente explica esto de manera incompleta, así que aquí está mi opinión.
Considere la posibilidad de crear un objeto byte escribiendo un byte literal (literalmente definiendo un objeto byte sin usar realmente un objeto byte, por ejemplo, escribiendo b '') y convirtiéndolo en un objeto de cadena codificado en utf-8. (Tenga en cuenta que convertir aquí significa decodificar )
byte_object= b"test" # byte object by literally typing characters print(byte_object) # Prints b'test' print(byte_object.decode('utf8')) # Prints "test" without quotations
Verá que simplemente aplicamos la
.decode(utf8)
función.Bytes en Python
https://docs.python.org/3.3/library/stdtypes.html#bytes
Los literales de cadena se describen mediante las siguientes definiciones léxicas:
https://docs.python.org/3.3/reference/lexical_analysis.html#string-and-bytes-literals
stringliteral ::= [stringprefix](shortstring | longstring) stringprefix ::= "r" | "u" | "R" | "U" shortstring ::= "'" shortstringitem* "'" | '"' shortstringitem* '"' longstring ::= "'''" longstringitem* "'''" | '"""' longstringitem* '"""' shortstringitem ::= shortstringchar | stringescapeseq longstringitem ::= longstringchar | stringescapeseq shortstringchar ::= <any source character except "\" or newline or the quote> longstringchar ::= <any source character except "\"> stringescapeseq ::= "\" <any source character> bytesliteral ::= bytesprefix(shortbytes | longbytes) bytesprefix ::= "b" | "B" | "br" | "Br" | "bR" | "BR" | "rb" | "rB" | "Rb" | "RB" shortbytes ::= "'" shortbytesitem* "'" | '"' shortbytesitem* '"' longbytes ::= "'''" longbytesitem* "'''" | '"""' longbytesitem* '"""' shortbytesitem ::= shortbyteschar | bytesescapeseq longbytesitem ::= longbyteschar | bytesescapeseq shortbyteschar ::= <any ASCII character except "\" or newline or the quote> longbyteschar ::= <any ASCII character except "\"> bytesescapeseq ::= "\" <any ASCII character>
fuente
Necesita decodificarlo para convertirlo en una cadena. Verifique la respuesta aquí sobre bytes literales en python3 .
In [1]: b'I posted a new photo to Facebook'.decode('utf-8') Out[1]: 'I posted a new photo to Facebook'
fuente
encode("utf-8")
, obtengo errores. Y, como mencioné aquí, stackoverflow.com/q/41915383/4422095 eliminar eso no lo resolvió. Incluso si uso la decodificación como sugieres, todavía obtengo un error. Publicaré eso en la publicación.utf-8
fue un ejemplo.**** Cómo eliminar los caracteres b '' que son cadenas decodificadas en Python ****
import base64 a='cm9vdA==' b=base64.b64decode(a).decode('utf-8') print(b)
fuente
En python 3.6 con django 2.0, la decodificación en un byte literal no funciona como se esperaba. Sí, obtengo el resultado correcto cuando lo imprimo, pero el 'valor b' sigue ahí incluso si lo imprime correctamente.
Esto es lo que estoy codificando
uid': urlsafe_base64_encode(force_bytes(user.pk)),
Esto es lo que estoy decodificando:
Esto es lo que dice django 2.0:
Codifica una cadena de bytes en base64 para su uso en URL, eliminando cualquier signo igual al final.
Decodifica una cadena codificada en base64, agregando cualquier signo igual al final que pueda haber sido eliminado.
Este es mi archivo account_activation_email_test.html
{% autoescape off %} Hi {{ user.username }}, Please click on the link below to confirm your registration: http://{{ domain }}{% url 'accounts:activate' uidb64=uid token=token %} {% endautoescape %}
Esta es la respuesta de mi consola:
Tipo de contenido: texto / sin formato; charset = "utf-8" Versión MIME: 1.0 Codificación de transferencia de contenido: 7 bits Asunto: Active su cuenta de MySite De: webmaster @ localhost Para: [email protected] Fecha: viernes, 20 de abril de 2018 06:26:46 - 0000 ID de mensaje: <152420560682.16725.4597194169307598579@Dash-U>
Hola, usuario de prueba,
Haga clic en el enlace a continuación para confirmar su registro:
http://127.0.0.1:8000/activate/b'MjU'/4vi-fasdtRf2db2989413ba/
como puedes ver
uid = b'MjU'
esperado
uid = MjU
prueba en consola:
$ python Python 3.6.4 (default, Apr 7 2018, 00:45:33) [GCC 5.4.0 20160609] on linux Type "help", "copyright", "credits" or "license" for more information. >>> from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode >>> from django.utils.encoding import force_bytes, force_text >>> var1=urlsafe_base64_encode(force_bytes(3)) >>> print(var1) b'Mw' >>> print(var1.decode()) Mw >>>
Después de investigar, parece que está relacionado con Python 3. Mi solución fue bastante simple:
'uid': user.pk,
lo recibo como uidb64 en mi función de activación:
y voilá:
Content-Transfer-Encoding: 7bit Subject: Activate Your MySite Account From: webmaster@localhost To: [email protected] Date: Fri, 20 Apr 2018 20:44:46 -0000 Message-ID: <152425708646.11228.13738465662759110946@Dash-U> Hi testuser, Please click on the link below to confirm your registration: http://127.0.0.1:8000/activate/45/4vi-3895fbb6b74016ad1882/
ahora funciona bien. :)
fuente
Lo hice codificando solo la salida usando utf-8. Aquí está el ejemplo de código
new_tweets = api.GetUserTimeline(screen_name = user,count=200) result = new_tweets[0] try: text = result.text except: text = '' with open(file_name, 'a', encoding='utf-8') as f: writer = csv.writer(f) writer.writerows(text)
es decir: no codifique al recopilar datos de la API, codifique la salida (imprimir o escribir) solo.
fuente
Suponiendo que no desea volver a decodificarlo inmediatamente, como otros sugieren aquí, puede analizarlo en una cadena y luego simplemente quitar el principio
'b
y el final'
.>>> x = "Hi there 😄" >>> x = "Hi there 😄".encode("utf-8") >>> x b"Hi there \xef\xbf\xbd" >>> str(x)[2:-1] "Hi there \\xef\\xbf\\xbd"
fuente
Aunque la pregunta es muy antigua, creo que puede ser útil para quién se enfrenta al mismo problema. Aquí los textos son una cadena como la siguiente:
text= "b'I posted a new photo to Facebook'"
Por lo tanto, no puede eliminar b codificándolo porque no es un byte. Hice lo siguiente para eliminarlo.
cleaned_text = text.split("b'")[1]
que dará
"I posted a new photo to Facebook"
fuente
"I posted a new photo to Facebook'"
. De todos modos, esto no es de lo que se trata la pregunta.