Come posso eliminare il prefisso b in una stringa in Python?


90

Molti dei tweet che sto importando hanno questo problema in cui leggono

b'I posted a new photo to Facebook'

Ho bcapito che indica che è un byte. Ma questo si sta rivelando problematico perché nei miei file CSV che finisco per scrivere, il bnon scompare e interferisce con il codice futuro.

C'è un modo semplice per rimuovere questo bprefisso dalle mie righe di testo?

Tieni presente che mi sembra di aver bisogno di codificare il testo in utf-8 o tweepy ha problemi a estrarlo dal web.


Ecco il contenuto del collegamento che sto analizzando:

https://www.dropbox.com/s/sjmsbuhrghj7abt/new_tweets.txt?dl=0

new_tweets = 'content in the link'

Tentativo di codice

outtweets = [[tweet.text.encode("utf-8").decode("utf-8")] for tweet in new_tweets]
print(outtweets)

Errore

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>

puoi mostrare almeno una parte di quelle righe di testo ?
RomanPerekhrest

@RomanPerekhrest Mi dispiace, cosa vorresti di più? Codice o output?
Stan Shunpike

Specificare sempre la codifica all'apertura dei file.
MKesper

Risposte:


146

devi decodificare il bytesdi che vuoi una stringa:

b = b'1234'
print(b.decode('utf-8'))  # '1234'

Ho aggiornato la domanda. Non credo che questo metodo funzioni. Se è così, potresti spiegare perché?
Stan Shunpike

4
.encode("utf-8").decode("utf-8")non fa assolutamente nulla (se funziona) ... sei su Python 3, giusto? py3 ha una forte distinzione tra bytese str. qualcosa nel tuo codice sembra usare la cp1252codifica ... potresti provare ad aprire il tuo file open(..., mode='w', encoding='utf-8')e scrivere solo strsul file; oppure ti dimentichi di tutta la codifica e scrivi il file in binario: open(..., mode='wb')(nota il b) e scrivi solo bytes. questo aiuta?
Hiro protagonista il

No, questo non lo risolve. Ho"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'"
Stan Shunpike

Come puoi dire che codifica come cp1252? Inoltre non pensavo che .encode("utf-8").decode("utf-8")avrebbe fatto nulla, ma le persone qui sembravano pensare che fosse la risposta giusta, che non è per quanto posso vedere.
Stan Shunpike

Ho scoperto questo percorso in voi traceback: C:\Users\Stan Shunpike\Anaconda3\lib\encodings\cp1252.py. probabilmente dovresti provare a scoprire come / dove viene utilizzato. oh, e stai usando il csv.writer; in tal caso è necessario scrivere stranzi un no bytes. stai ricevendo cose da requests? la codifica ottenuta da una risorsa Web potrebbe essere diversa da utf-8.
Hiro protagonista il

19

Ti sta solo facendo sapere che l'oggetto che stai stampando non è una stringa, piuttosto un oggetto byte come un byte letterale . Le persone lo spiegano in modi incompleti, quindi ecco la mia opinione.

Considera la creazione di un oggetto byte digitando un byte letterale (definendo letteralmente un oggetto byte senza effettivamente utilizzare un oggetto byte, ad esempio digitando b '') e convertendolo in un oggetto stringa codificato in utf-8. (Nota che convertire qui significa decodificare )

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

Vedi che applichiamo semplicemente la .decode(utf8)funzione.

Byte in Python

https://docs.python.org/3.3/library/stdtypes.html#bytes

I letterali stringa sono descritti dalle seguenti definizioni lessicali:

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>

5

Devi decodificarlo per convertirlo in una stringa. Controlla qui la risposta sui byte letterali in python3 .

In [1]: b'I posted a new photo to Facebook'.decode('utf-8')
Out[1]: 'I posted a new photo to Facebook'

1
il problema con questo è che, quando provo a scaricare i tweet senza il messaggio, encode("utf-8")ottengo errori. E, come ho detto qui, la rimozione di stackoverflow.com/q/41915383/4422095 non ha risolto il problema. Anche se uso la decodifica come suggerisci, ricevo ancora un errore. Lo posterò nel post.
Stan Shunpike

fatto. non è esattamente lo stesso perché hai bisogno dei codici OAuth di Twitter per farlo. ma se fai solo l'esempio che ho dato, avrai lo stesso problema. non viene risolto con il metodo suggerito. annulla solo l'utf-8. ma non funziona perché non elaborerà i caratteri nei tweet senza la codifica utf-8
Stan Shunpike

Ovviamente devi usare la codifica corretta. utf-8era un esempio.
salmanwahed

5

**** Come rimuovere i caratteri b '' che è una stringa decodificata in Python ****

import base64
a='cm9vdA=='
b=base64.b64decode(a).decode('utf-8')
print(b)

2

Su python 3.6 con django 2.0, la decodifica su un byte letterale non funziona come previsto. Sì, ottengo il risultato giusto quando lo stampo, ma il b'value 'è ancora lì anche se lo stampi correttamente.

Questo è ciò che sto codificando

uid': urlsafe_base64_encode(force_bytes(user.pk)),

Questo è ciò che sto decodificando:

uid = force_text(urlsafe_base64_decode(uidb64))

Questo è ciò che dice django 2.0:

urlsafe_base64_encode(s)[source]

Codifica una stringa di byte in base64 da utilizzare negli URL, eliminando qualsiasi segno di uguale alla fine.

urlsafe_base64_decode(s)[source]

Decodifica una stringa con codifica base64, aggiungendo eventuali segni di uguale finali che potrebbero essere stati rimossi.


Questo è il mio file 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 %}

Questa è la mia risposta della console:

Tipo di contenuto: testo / normale; charset = "utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Oggetto: Attiva il tuo account MySite Da: webmaster @ localhost A: testuser@yahoo.com Data: Fri, 20 Apr 2018 06:26:46 - 0000 ID messaggio: <152420560682.16725.4597194169307598579@Dash-U>

Ciao testuser,

Fare clic sul collegamento sottostante per confermare la registrazione:

http://127.0.0.1:8000/activate/b'MjU'/4vi-fasdtRf2db2989413ba/

come potete vedere uid = b'MjU'

previsto uid = MjU


test in 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
>>> 

Dopo aver esaminato sembra che sia correlato a Python 3. La mia soluzione alternativa è stata abbastanza semplice:

'uid': user.pk,

lo ricevo come uidb64 sulla mia funzione di attivazione:

user = User.objects.get(pk=uidb64)

e voilà:

Content-Transfer-Encoding: 7bit
Subject: Activate Your MySite Account
From: webmaster@localhost
To: testuser@yahoo.com
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/

ora funziona bene. :)


Credo che il problema non sia la decodifica, ma piuttosto l'autoescape off nel template che non è in grado di rimuovere il byte letterale in una stringa proprio come fa decode.
Fernando D Jaime

1

L'ho fatto codificando solo l'output usando utf-8. Ecco l'esempio di codice

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)

cioè: non codificare quando si raccolgono dati da API, codifica solo l'output (stampa o scrittura).


0

Supponendo che tu non voglia decodificarlo di nuovo immediatamente come altri suggeriscono qui, puoi analizzarlo in una stringa e quindi rimuovere solo l'inizio 'be la fine '.

>>> 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"   

-2

Sebbene la domanda sia molto vecchia, penso che possa essere utile a chi sta affrontando lo stesso problema. Qui il testo è una stringa come di seguito:

text= "b'I posted a new photo to Facebook'"

Quindi non puoi rimuovere b codificandolo perché non è un byte. Ho fatto quanto segue per rimuoverlo.

cleaned_text = text.split("b'")[1]

che darà "I posted a new photo to Facebook"


3
No, questo darà "I posted a new photo to Facebook'". Comunque, non è di questo che si tratta.
tripleee
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.