Muitos dos tweets que estou importando estão tendo esse problema de leitura
b'I posted a new photo to Facebook'
Percebi que b
indica que é um byte. Mas isso está se mostrando problemático porque em meus arquivos CSV que acabo escrevendo, o arquivo b
não desaparece e está interferindo no código futuro.
Existe uma maneira simples de remover esse b
prefixo de minhas linhas de texto?
Lembre-se de que preciso ter o texto codificado em utf-8 ou tweepy e tem problemas para puxá-lo da web.
Este é o conteúdo do link que estou analisando:
https://www.dropbox.com/s/sjmsbuhrghj7abt/new_tweets.txt?dl=0
new_tweets = 'content in the link'
Tentativa de código
outtweets = [[tweet.text.encode("utf-8").decode("utf-8")] for tweet in new_tweets]
print(outtweets)
Erro
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>
Respostas:
você precisa decodificar o
bytes
que deseja uma string:b = b'1234' print(b.decode('utf-8')) # '1234'
fonte
.encode("utf-8").decode("utf-8")
não faz absolutamente nada (se é que funciona) ... você está no python 3, certo? py3 tem uma forte distinção entrebytes
estr
. algo em seu código parece usar acp1252
codificação ... você pode tentar abrir seu arquivo comopen(..., mode='w', encoding='utf-8')
e apenas gravarstr
no arquivo; ou você se esquece de toda a codificação e escreve o arquivo em binário:open(..., mode='wb')
(observe ob
) e apenas escrevebytes
. Isso ajuda?"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 faria nada, mas as pessoas aqui pareciam pensar que era a resposta certa, o que não é pelo que vejo.C:\Users\Stan Shunpike\Anaconda3\lib\encodings\cp1252.py
. você provavelmente deve tentar descobrir como / onde isso é usado. oh, e você está usando ocsv.writer
; nesse caso, vocêstr
realmente precisa escrever um nãobytes
. você está recebendo coisasrequests
? a codificação que você obtém de um recurso da web pode ser diferenteutf-8
.Ele apenas informa que o objeto que você está imprimindo não é uma string, e sim um objeto de byte como um literal de byte . As pessoas explicam isso de maneiras incompletas, então aqui está minha opinião.
Considere a criação de um objeto de byte digitando um literal de byte (literalmente definindo um objeto de byte sem realmente usar um objeto de byte, por exemplo, digitando b '') e convertendo-o em um objeto de string codificado em utf-8. (Observe que converter aqui 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
Você vê que simplesmente aplicamos a
.decode(utf8)
função.Bytes em Python
https://docs.python.org/3.3/library/stdtypes.html#bytes
Literais de string são descritos pelas seguintes definições lexicais:
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>
fonte
Você precisa decodificá-lo para convertê-lo em uma string. Verifique a resposta aqui sobre bytes literais em python3 .
In [1]: b'I posted a new photo to Facebook'.decode('utf-8') Out[1]: 'I posted a new photo to Facebook'
fonte
encode("utf-8")
erros, recebo. E, como mencionei aqui, stackoverflow.com/q/41915383/4422095 remover isso não resolveu o problema. Mesmo se eu usar a decodificação como você sugeriu, ainda recebo um erro. Vou postar isso no post.utf-8
foi um exemplo.**** Como remover b '' chars que são strings decodificadas em python ****
import base64 a='cm9vdA==' b=base64.b64decode(a).decode('utf-8') print(b)
fonte
No python 3.6 com django 2.0, decodificar em um literal de byte não funciona como esperado. Sim, obtenho o resultado certo quando imprimo, mas o b'value 'ainda está lá, mesmo que você imprima corretamente.
Isso é o que estou codificando
uid': urlsafe_base64_encode(force_bytes(user.pk)),
Isso é o que estou decodificando:
Isso é o que django 2.0 diz:
Codifica uma sequência de bytes em base64 para uso em URLs, removendo quaisquer sinais de igual à direita.
Decodifica uma string codificada em base64, adicionando de volta quaisquer sinais de igual à direita que possam ter sido removidos.
Este é meu arquivo 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 é a minha resposta do console:
Tipo de conteúdo: texto / simples; charset = "utf-8" Versão MIME: 1.0 Content-Transfer-Encoding: 7bit Assunto: Ative sua conta do MySite De: webmaster @ localhost Para: [email protected] Data: Sex, 20 Abr 2018 06:26:46 - 0000 Message-ID: <152420560682.16725.4597194169307598579@Dash-U>
Olá, testuser,
Clique no link abaixo para confirmar seu registro:
http://127.0.0.1:8000/activate/b'MjU'/4vi-fasdtRf2db2989413ba/
como você pode ver
uid = b'MjU'
esperado
uid = MjU
teste no console:
$ 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 >>>
Depois de investigar, parece que está relacionado ao python 3. Minha solução alternativa foi bastante simples:
'uid': user.pk,
eu recebo como uidb64 na minha função de ativação:
e voila:
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/
agora funciona bem. :)
fonte
Eu fiz isso codificando apenas a saída usando utf-8. Aqui está o exemplo 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)
ou seja: não codifique ao coletar dados da API, codifique apenas a saída (impressão ou gravação).
fonte
Assumindo que você não deseja decodificá-lo imediatamente como os outros estão sugerindo aqui, você pode analisá-lo em uma string e, em seguida, remover o início
'b
e o fim'
.>>> 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"
fonte
Embora a questão seja muito antiga, acho que pode ser útil para quem está enfrentando o mesmo problema. Aqui, os textos são uma string como abaixo:
text= "b'I posted a new photo to Facebook'"
Portanto, você não pode remover b codificando-o porque não é um byte. Eu fiz o seguinte para removê-lo.
cleaned_text = text.split("b'")[1]
que vai dar
"I posted a new photo to Facebook"
fonte
"I posted a new photo to Facebook'"
. Não é disso que se trata, de qualquer maneira.