Bagaimana cara menghilangkan awalan-b dalam string di python?

90

Sekelompok tweet yang saya impor mengalami masalah ini di mana mereka membaca

b'I posted a new photo to Facebook'

Saya mengumpulkan yang bmenunjukkan itu adalah byte. Tetapi ini terbukti bermasalah karena dalam file CSV saya yang akhirnya saya tulis, btidak hilang dan mengganggu kode di masa mendatang.

Apakah ada cara sederhana untuk menghapus bawalan ini dari baris teks saya?

Perlu diingat, saya tampaknya perlu memiliki teks yang dikodekan dalam utf-8 atau tweepy mengalami masalah saat menariknya dari web.


Berikut konten tautan yang saya analisis:

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

new_tweets = 'content in the link'

Upaya Kode

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

Kesalahan

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
sumber
dapatkah Anda menunjukkan setidaknya sebagian dari baris teks itu ?
RomanPerekhrest
@RomanPerekhrest Maaf, apa yang lebih Anda inginkan? Kode atau keluaran?
Stan Shunpike
Selalu tentukan pengkodean saat membuka file.
MKesper

Jawaban:

146

Anda perlu men-decode yang bytesAnda inginkan string:

b = b'1234'
print(b.decode('utf-8'))  # '1234'
hiro protagonis
sumber
Saya telah memperbarui pertanyaan tersebut. Saya tidak berpikir metode ini berhasil. Jika ya, dapatkah Anda menjelaskan alasannya?
Stan Shunpike
4
.encode("utf-8").decode("utf-8")tidak apa-apa (jika berfungsi sama sekali) ... Anda menggunakan python 3, bukan? py3 memiliki perbedaan yang kuat antara bytesdan str. sesuatu dalam kode Anda tampaknya menggunakan cp1252pengkodean ... Anda dapat mencoba membuka file Anda dengan open(..., mode='w', encoding='utf-8')dan hanya menulis strke file; atau Anda lupa tentang semua encoding dan menulis file dalam biner: open(..., mode='wb')(perhatikan b) dan hanya menulis bytes. Apakah itu membantu?
protagonis hiro
Tidak, itu tidak memperbaikinya. Saya mendapat"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
Bagaimana Anda tahu itu mengkodekan sebagai cp1252? Saya juga tidak berpikir .encode("utf-8").decode("utf-8")akan melakukan apa-apa, tetapi orang-orang di sini tampaknya berpikir bahwa itu adalah jawaban yang benar, yang sejauh ini tidak saya lihat.
Stan Shunpike
i melihat jalan ini di Anda traceback: C:\Users\Stan Shunpike\Anaconda3\lib\encodings\cp1252.py. Anda mungkin harus mencoba mencari tahu bagaimana / di mana itu digunakan. oh, dan Anda menggunakan csv.writer; dalam hal ini Anda harus menulis strmemang bukan bytes. apakah kamu mendapatkan sesuatu dari requests? pengkodean yang Anda dapatkan dari sumber daya web mungkin berbeda dari utf-8.
protagonis hiro
19

Ini hanya memberi tahu Anda bahwa objek yang Anda cetak bukanlah string, melainkan objek byte sebagai literal byte . Orang-orang menjelaskan ini dengan cara yang tidak lengkap, jadi inilah pendapat saya.

Pertimbangkan untuk membuat objek byte dengan mengetik literal byte (secara harfiah mendefinisikan objek byte tanpa benar-benar menggunakan objek byte misalnya dengan mengetik b '') dan mengubahnya menjadi objek string yang dikodekan dalam utf-8. (Perhatikan bahwa mengubah di sini berarti decoding )

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

Anda lihat bahwa kami hanya menerapkan .decode(utf8)fungsinya.

Byte dengan Python

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

Literal string dijelaskan oleh definisi leksikal berikut:

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
sumber
5

Anda perlu memecahkan kode untuk mengubahnya menjadi string. Cek jawabannya di sini tentang byte literal di python3 .

In [1]: b'I posted a new photo to Facebook'.decode('utf-8')
Out[1]: 'I posted a new photo to Facebook'
salmanwahed
sumber
1
masalah dengan ini adalah, ketika saya mencoba mengunduh tweet tanpa encode("utf-8")saya mendapatkan kesalahan. Dan, seperti yang saya sebutkan di sini, stackoverflow.com/q/41915383/4422095 menghapus itu tidak menyelesaikannya. Bahkan jika saya menggunakan decode seperti yang Anda sarankan, saya masih mendapatkan kesalahan. Saya akan mempostingnya di postingan.
Stan Shunpike
selesai. itu tidak persis sama karena Anda memerlukan kode OAuth twitter untuk melakukannya. tetapi jika Anda hanya melakukan contoh yang saya berikan, Anda akan mendapatkan masalah yang sama. itu tidak diselesaikan dengan metode yang u sarankan. itu hanya membatalkan utf-8. tetapi itu tidak berhasil karena tidak akan memproses karakter di tweet tanpa pengkodean utf-8
Stan Shunpike
Anda harus menggunakan pengkodean yang benar tentunya. utf-8adalah sebuah contoh.
salmanwahed
5

**** Cara menghapus b '' chars yang merupakan decode string dalam python ****

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

Pada python 3.6 dengan django 2.0, decode pada literal byte tidak bekerja seperti yang diharapkan. Ya saya mendapatkan hasil yang benar ketika saya mencetaknya, tetapi b'value 'masih ada meskipun Anda mencetaknya dengan benar.

Inilah yang saya encoding

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

Inilah yang saya decoding:

uid = force_text(urlsafe_base64_decode(uidb64))

Inilah yang dikatakan django 2.0:

urlsafe_base64_encode(s)[source]

Mengkodekan bytestring di base64 untuk digunakan di URL, menghilangkan tanda yang sama di belakangnya.

urlsafe_base64_decode(s)[source]

Mendekode string yang dienkode base64, menambahkan kembali tanda yang sama di belakangnya yang mungkin telah dilucuti.


Ini adalah file account_activation_email_test.html saya

{% 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 %}

Ini adalah tanggapan konsol saya:

Jenis-Konten: teks / biasa; charset = "utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: Aktifkan Akun MySite Anda Dari: webmaster @ localhost Kepada: [email protected] Tanggal: Jum, 20 Apr 2018 06:26:46 - 0000 ID-Pesan: <152420560682.16725.4597194169307598579@Dash-U>

Hai penguji,

Silakan klik tautan di bawah ini untuk mengonfirmasi pendaftaran Anda:

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

seperti yang dapat Anda lihat uid = b'MjU'

diharapkan uid = MjU


uji di konsol:

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

Setelah menyelidiki, sepertinya ini terkait dengan python 3. Solusi saya cukup sederhana:

'uid': user.pk,

saya menerimanya sebagai uidb64 pada fungsi aktivasi saya:

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

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

sekarang berfungsi dengan baik. :)

Fernando D Jaime
sumber
Saya percaya bahwa masalahnya bukan decode tetapi autoescape mati di template yang tidak dapat menghapus byte literal menjadi string seperti yang dilakukan decode.
Fernando D Jaime
1

Saya menyelesaikannya hanya dengan mengkodekan output menggunakan utf-8. Berikut adalah contoh kodenya

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)

yaitu: jangan menyandikan saat mengumpulkan data dari api, hanya menyandikan keluaran (cetak atau tulis).

DevJoe
sumber
0

Dengan asumsi Anda tidak ingin segera mendekodekannya lagi seperti yang disarankan orang lain di sini, Anda dapat menguraikannya menjadi string dan kemudian hanya menghapus bagian depan 'bdan belakang '.

>>> 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
sumber
-2

Meskipun pertanyaannya sudah sangat lama, saya pikir mungkin berguna bagi siapa yang menghadapi masalah yang sama. Berikut teksnya adalah string seperti di bawah ini:

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

Dengan demikian Anda tidak dapat menghapus b dengan mengkodekannya karena ini bukan byte. Saya melakukan hal berikut untuk menghapusnya.

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

yang akan memberi "I posted a new photo to Facebook"

Kamol Roy
sumber
3
Tidak, itu akan memberi "I posted a new photo to Facebook'". Bagaimanapun, ini bukanlah tentang pertanyaannya.
tripleee