Python'da bir dizedeki b önekinden nasıl kurtulurum?


90

İçe aktardığım tweetlerin bir kısmı okudukları yerde bu sorunu yaşıyor

b'I posted a new photo to Facebook'

Bunun bbir bayt olduğunu gösterir. Ancak bu sorunlu oluyor çünkü yazmakta olduğum CSV dosyalarımda, dosyalar bkaybolmuyor ve gelecekteki koda müdahale ediyor.

Bu böneki metin satırlarımdan kaldırmanın basit bir yolu var mı ?

Unutmayın, utf-8'de kodlanmış metinlere ihtiyacım var gibi görünüyor veya tweepy bunları web'den çekerken sorun yaşıyor.


İşte analiz ettiğim bağlantı içeriği:

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

new_tweets = 'content in the link'

Kod Denemesi

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

Hata

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>

bu metin satırlarının en azından bir kısmını gösterebilir misin ?
RomanPerekhrest

@RomanPerekhrest Özür dilerim, daha çok ne istersiniz? Kod mu çıktı mı?
Stan Shunpike

Dosyaları açarken daima kodlamayı belirtin.
MKesper

Yanıtlar:


146

Gerekirse deşifrebytes senin bir dize istiyorum:

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

Soruyu güncelledim. Bu yöntemin işe yaradığını düşünmüyorum. Varsa, nedenini açıklar mısınız?
Stan Shunpike

4
.encode("utf-8").decode("utf-8")kesinlikle hiçbir şey yapmaz (eğer çalışırsa) ... python 3'tesiniz, değil mi? py3'ün bytesve arasında güçlü bir ayrım vardır str. kodunuzdaki bir şey cp1252kodlamayı kullanıyor gibi görünüyor ... dosyanızı ile açmayı deneyebilir open(..., mode='w', encoding='utf-8')ve yalnızca strdosyaya yazabilirsiniz ; veya tüm kodlamayı unutup dosyayı ikili olarak yazarsınız: open(..., mode='wb')(not edin b) ve yalnızca yazın bytes. bu yardımcı olur mu?
hiro kahramanı

Hayır, bu onu düzeltmez. Ben var"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'"
Shunpike

Cp1252 olarak kodladığını nasıl anlarsınız? Ben de bir .encode("utf-8").decode("utf-8")şey yapacağımı düşünmedim , ama buradaki insanlar bunun doğru cevap olduğunu düşünüyor gibiydi, bu benim görebildiğim kadarıyla değil.
Stan Shunpike

Ben traceback sende bu yolu lekeli: C:\Users\Stan Shunpike\Anaconda3\lib\encodings\cp1252.py. muhtemelen bunun nasıl / nerede kullanıldığını bulmaya çalışmalısınız. oh, ve kullanıyorsunuz csv.writer; bu durumda strgerçekten bir not yazmanız gerekir bytes. Eğer bir şeyler alıyorsanız requests? bir web kaynağından aldığınız kodlama farklı olabilir utf-8.
hiro kahramanı

19

Sadece yazdırdığınız nesnenin bir dize olmadığını, bayt değişmezi olarak bir bayt nesnesi olduğunu bilmenizi sağlar . İnsanlar bunu eksik bir şekilde açıklıyor, işte benim düşüncem.

Bir bayt değişmezi yazarak (gerçekten bir bayt nesnesi kullanmadan bir bayt nesnesini tam anlamıyla tanımlayarak, örneğin b '' yazarak) ve onu utf-8'de kodlanmış bir dizgi nesnesine dönüştürerek bir bayt nesnesi oluşturmayı düşünün . (Burada dönüştürmenin kod çözme anlamına geldiğini unutmayın )

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

Sadece .decode(utf8)işlevi uyguladığımızı görüyorsunuz .

Python'da Bayt

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

Dize değişmezleri aşağıdaki sözcük tanımlarıyla açıklanır:

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>

6

Bir dizgeye dönüştürmek için kodunu çözmeniz gerekir. Python3'teki bayt değişmez değeri hakkındaki cevabı burada kontrol edin .

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

1
bununla ilgili sorun şu ki, encode("utf-8")ben hata almadan tweet indirmeye çalıştığımda . Ve burada bahsettiğim gibi, stackoverflow.com/q/41915383/4422095 kaldırmak sorunu çözmedi. Kod çözmeyi önerdiğiniz gibi kullansam bile, yine de bir hata alıyorum. Bunu gönderide yayınlayacağım.
Stan Shunpike

bitti. tam olarak aynı değil çünkü bunu yapmak için twitter OAuth kodlarına ihtiyacınız var. ama sadece verdiğim örneği yaparsanız, aynı sorunu yaşarsınız. önerilen yöntemle çözülmedi. sadece utf-8'i geri alır. ama iş o utf-8 kodlama olmadan tweetler karakterleri işlemek olmaz çünkü o
Shunpike

Elbette doğru kodlamayı kullanmalısınız. utf-8bir örnekti.
salmanwahed

5

**** Python'da kodu çözülmüş b '' karakterleri nasıl kaldırılır ****

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

2

Django 2.0 ile python 3.6'da, bir bayt değişmezindeki kod çözme beklendiği gibi çalışmaz. Evet, yazdırdığımda doğru sonucu alıyorum, ancak doğru yazdırsanız bile b'value 'hala orada.

Bu, kodladığım şey

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

Kod çözme işlemi budur:

uid = force_text(urlsafe_base64_decode(uidb64))

Django 2.0 şöyle diyor:

urlsafe_base64_encode(s)[source]

URL'lerde kullanılmak üzere base64'te bir bytestring'i kodlayarak, sondaki eşit işaretleri kaldırır.

urlsafe_base64_decode(s)[source]

Base64 kodlu bir dizenin kodunu çözerek, soyulmuş olabilecek sondaki eşit işaretleri geri ekler.


Bu benim account_activation_email_test.html dosyam

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

Bu benim konsol cevabım:

İçerik Türü: metin / düz; charset = "utf-8" MIME-Sürümü: 1.0 Content-Transfer-Encoding: 7bit Konu: MySite Hesabınızı Etkinleştirin Gönderen: webmaster @ localhost Kime: testuser@yahoo.com Tarih: Cum, 20 Nisan 2018 06:26:46 - 0000 İleti Kimliği: <152420560682.16725.4597194169307598579@Dash-U>

Merhaba testuser,

Kaydınızı onaylamak için lütfen aşağıdaki bağlantıya tıklayın:

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

gördüğün gibi uid = b'MjU'

beklenen uid = MjU


konsolda test edin:

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

İnceledikten sonra python 3 ile ilgili gibi görünüyor. Çözümüm oldukça basitti:

'uid': user.pk,

Etkinleştirme işlevimde bunu uidb64 olarak alıyorum:

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

ve işte:

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/

şimdi iyi çalışıyor. :)


Sorunun kod çözme olmadığına inanıyorum, bunun yerine şablondaki bayt değişmezini kod çözme gibi bir dizeye ayıramayan otomatik görünüm kapalı.
Fernando D Jaime

1

Sadece çıktıyı utf-8 kullanarak kodlayarak yaptım. İşte kod örneği

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)

yani: api'den veri toplarken kodlamayın, yalnızca çıktıyı kodlayın (yazdır veya yazın).


0

Başkalarının burada önerdiği gibi kodunu hemen çözmek istemediğinizi varsayarsak, onu bir dizeye ayrıştırabilir ve ardından sadece 'bbaştaki ve sondaki kısımları ayırabilirsiniz '.

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

Soru çok eski olmasına rağmen, aynı problemle kimlerin karşı karşıya olduğuna yardımcı olabileceğini düşünüyorum. Burada metinler aşağıdaki gibi bir dizedir:

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

Böylece, bir bayt olmadığı için kodlayarak b'yi kaldıramazsınız. Kaldırmak için aşağıdakileri yaptım.

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

hangisi verecek "I posted a new photo to Facebook"


3
Hayır, verecek "I posted a new photo to Facebook'". Zaten sorunun konusu bu değil.
üçlü
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.