Wie entferne ich das b-Präfix in einer Zeichenfolge in Python?

88

Einige der Tweets, die ich importiere, haben dieses Problem, wo sie gelesen werden

b'I posted a new photo to Facebook'

Ich sammle die bzeigt an, dass es ein Byte ist. Dies erweist sich jedoch als problematisch, da in meinen CSV-Dateien, die ich am Ende schreibe, die bnicht verschwinden und den zukünftigen Code stören.

Gibt es eine einfache Möglichkeit, dieses bPräfix aus meinen Textzeilen zu entfernen ?

Denken Sie daran, ich muss anscheinend den Text in utf-8 codieren lassen, oder Tweepy hat Probleme, sie aus dem Web zu ziehen.


Hier ist der Linkinhalt, den ich analysiere:

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

new_tweets = 'content in the link'

Code-Versuch

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>
Stan Shunpike
quelle
Können Sie mindestens einen Teil dieser Textzeilen anzeigen ?
RomanPerekhrest
@RomanPerekhrest Es tut mir leid, von was möchtest du mehr? Code oder Ausgabe?
Stan Shunpike
Geben Sie beim Öffnen von Dateien immer die Codierung an.
MKesper
1
Mögliches Duplikat von Suppress / print ohne b 'Präfix für Bytes in Python 3
wesinat0r

Antworten:

136

Sie müssen die von Ihnen gewünschte Zeichenfolge dekodierenbytes :

b = b'1234'
print(b.decode('utf-8'))  # '1234'
Hiro-Protagonist
quelle
Ich habe die Frage aktualisiert. Ich denke nicht, dass diese Methode funktioniert. Wenn ja, können Sie erläutern, warum?
Stan Shunpike
4
.encode("utf-8").decode("utf-8")macht absolut nichts (wenn es überhaupt funktioniert) ... du bist auf Python 3, oder? py3 unterscheidet stark zwischen bytesund str. Etwas in Ihrem Code scheint die cp1252Codierung zu verwenden. Sie könnten versuchen, Ihre Datei mit zu öffnen open(..., mode='w', encoding='utf-8')und nur strin die Datei zu schreiben . oder Sie vergessen die gesamte Codierung und schreiben die Datei in Binärform: open(..., mode='wb')(beachten Sie die b) und schreiben nur bytes. Hilft das?
Hiro Protagonist
Nein, das behebt es nicht. Ich habe"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
Wie können Sie feststellen, dass es als cp1252 codiert? Ich dachte auch nicht, .encode("utf-8").decode("utf-8")dass ich irgendetwas tun würde, aber die Leute hier schienen zu denken, dass dies die richtige Antwort war, was nicht so weit ist, wie ich sehen kann.
Stan Shunpike
Ich habe diesen Pfad in Ihrem Traceback entdeckt : C:\Users\Stan Shunpike\Anaconda3\lib\encodings\cp1252.py. Sie sollten wahrscheinlich versuchen herauszufinden, wie / wo das verwendet wird. oh, und du benutzt das csv.writer; In diesem Fall müssen Sie in der strTat ein Nicht schreiben bytes. Bekommst du Dinge von requests? Die Codierung, die Sie von einer Webressource erhalten, kann von abweichen utf-8.
Hiro Protagonist
19

Es soll Sie nur wissen lassen, dass das Objekt, das Sie drucken, keine Zeichenfolge ist, sondern ein Byte-Objekt als Byte-Literal . Die Leute erklären dies auf unvollständige Weise, also hier ist meine Meinung.

Erstellen Sie ein Byte-Objekt, indem Sie ein Byte-Literal eingeben (ein Byte-Objekt buchstäblich definieren, ohne tatsächlich ein Byte-Objekt zu verwenden, z. B. durch Eingabe von b '') und es in ein in utf-8 codiertes Zeichenfolgenobjekt konvertieren . (Beachten Sie, dass Konvertieren hier Dekodieren bedeutet )

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

Sie sehen, dass wir die .decode(utf8)Funktion einfach anwenden .

Bytes in Python

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

String-Literale werden durch die folgenden lexikalischen Definitionen beschrieben:

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>
Jonathan Komar
quelle
5

Sie müssen es dekodieren, um es in eine Zeichenfolge zu konvertieren. Überprüfen Sie hier die Antwort zum Byte-Literal in Python3 .

In [1]: b'I posted a new photo to Facebook'.decode('utf-8')
Out[1]: 'I posted a new photo to Facebook'
salmanwahed
quelle
1
Das Problem dabei ist, dass ich beim Versuch, Tweets ohne das herunterzuladen encode("utf-8"), Fehler bekomme. Und, wie ich hier erwähnte, hat das Entfernen von stackoverflow.com/q/41915383/4422095 das Problem nicht gelöst. Selbst wenn ich die Dekodierung wie vorgeschlagen verwende, wird immer noch eine Fehlermeldung angezeigt. Ich werde das in der Post posten.
Stan Shunpike
erledigt. Es ist nicht genau das gleiche, weil Sie Twitter OAuth-Codes benötigen, um es zu tun. Aber wenn Sie nur das Beispiel machen, das ich gegeben habe, werden Sie das gleiche Problem bekommen. es wird nicht durch die vorgeschlagene Methode gelöst. es macht nur die utf-8 rückgängig. aber das funktioniert nicht, weil es die Zeichen in den Tweets ohne utf-8-Codierung nicht verarbeitet
Stan Shunpike
Sie müssen natürlich die richtige Kodierung verwenden. utf-8war ein Beispiel.
Salmanwahed
4

**** So entfernen Sie b '' Zeichen, die als Zeichenfolge in Python dekodiert sind ****

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

Unter Python 3.6 mit Django 2.0 funktioniert die Dekodierung in einem Byte-Literal nicht wie erwartet. Ja, ich bekomme das richtige Ergebnis, wenn ich es drucke, aber der b'-Wert ist immer noch da, selbst wenn Sie es richtig drucken.

Dies ist, was ich codiere

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

Dies ist, was ich dekodiere:

uid = force_text(urlsafe_base64_decode(uidb64))

Dies ist, was Django 2.0 sagt:

urlsafe_base64_encode(s)[source]

Codiert einen Bytestring in base64 zur Verwendung in URLs, wobei alle nachfolgenden Gleichheitszeichen entfernt werden.

urlsafe_base64_decode(s)[source]

Dekodiert eine Base64-codierte Zeichenfolge und fügt alle nachfolgenden Gleichheitszeichen zurück, die möglicherweise entfernt wurden.


Dies ist meine Datei 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 %}

Dies ist meine Konsolenantwort:

Inhaltstyp: Text / Klartext; charset = "utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Betreff: Aktivieren Sie Ihr MySite-Konto Von: webmaster @ localhost An: [email protected] Datum: Fr, 20 Apr 2018 06:26:46 - 0000 Nachrichten-ID: <152420560682.16725.4597194169307598579@Dash-U>

Hallo Testbenutzer,

Bitte klicken Sie auf den Link unten, um Ihre Registrierung zu bestätigen:

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

Wie du siehst uid = b'MjU'

erwartet uid = MjU


Test in der Konsole:

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

Nach der Untersuchung scheint es mit Python 3 zu tun zu haben. Meine Problemumgehung war recht einfach:

'uid': user.pk,

Ich erhalte es als uidb64 auf meiner Aktivierungsfunktion:

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

und 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/

jetzt funktioniert es gut. :) :)

Fernando D Jaime
quelle
Ich glaube, dass das Problem nicht die Dekodierung ist, sondern die automatische Abschaltung in der Vorlage, die das Byteliteral nicht wie die Dekodierung in eine Zeichenfolge zerlegen kann.
Fernando D Jaime
1

Ich habe es geschafft, indem ich nur die Ausgabe mit utf-8 codiert habe. Hier ist das Codebeispiel

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)

dh: beim Sammeln von Daten aus der API nicht codieren, sondern nur die Ausgabe (Drucken oder Schreiben) codieren.

DevJoe
quelle
0

Angenommen, Sie möchten es nicht sofort wieder dekodieren, wie andere es hier vorschlagen, können Sie es zu einer Zeichenfolge analysieren und dann nur die führenden 'bund nachfolgenden Zeichenfolgen entfernen '.

>>> 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"   
Joseph Boyd
quelle
-2

Obwohl die Frage sehr alt ist, denke ich, dass es hilfreich sein kann, wer vor dem gleichen Problem steht. Hier ist der Text eine Zeichenfolge wie folgt:

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

Daher können Sie b nicht durch Codierung entfernen, da es kein Byte ist. Ich habe Folgendes getan, um es zu entfernen.

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

was geben wird "I posted a new photo to Facebook"

Kamol Roy
quelle
3
Nein, das wird geben "I posted a new photo to Facebook'". Darum geht es in der Frage sowieso nicht.
Tripleee