Как мне избавиться от префикса b в строке в Python?

88

У нескольких твитов, которые я импортирую, возникает проблема, когда они читают

b'I posted a new photo to Facebook'

Я понял, что bэто байт. Но это оказывается проблематичным, потому что в моих файлах CSV, которые я в конечном итоге пишу, bони не исчезают и мешают будущему коду.

Есть ли простой способ удалить этот bпрефикс из моих строк текста?

Имейте в виду, мне кажется, что мне нужно закодировать текст в utf-8, иначе tweepy не может извлечь их из Интернета.


Вот содержание ссылки, которое я анализирую:

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

new_tweets = 'content in the link'

Попытка кода

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

ошибка

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>
Стэн Шунпайк
источник
вы можете показать хотя бы часть этих строк текста ?
RomanPerekhrest
@RomanPerekhrest Извините, чего бы вы хотели еще? Код или вывод?
Stan Shunpike
Всегда указывайте кодировку при открытии файлов.
MKesper
1
Возможный дубликат Suppress / print без префикса b 'для байтов в Python 3
wesinat0r

Ответы:

136

вам нужно декодироватьbytes вам нужна строка:

b = b'1234'
print(b.decode('utf-8'))  # '1234'
Хиро главный герой
источник
Я обновил вопрос. Я не думаю, что этот метод работает. Если да, не могли бы вы объяснить, почему?
Stan Shunpike
4
.encode("utf-8").decode("utf-8")абсолютно ничего не делает (если вообще работает) ... вы ведь на Python 3, верно? py3 имеет четкое различие между bytesи str. что-то в вашем коде, кажется, использует cp1252кодировку ... вы можете попытаться открыть файл с помощью open(..., mode='w', encoding='utf-8')и только записать strв файл; или вы забываете обо всей кодировке и пишете файл в двоичном формате: open(..., mode='wb')(обратите внимание на b) и только пишите bytes. это помогает?
Хиро, главный герой,
Нет, это не исправит. Я получил"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'"
Стэн Шунпайк
Как узнать, что он кодируется как cp1252? Я тоже не думал, .encode("utf-8").decode("utf-8")что что- то сделаю, но люди здесь, похоже, думали, что это правильный ответ, а это далеко не так, насколько я могу судить.
Stan Shunpike
я заметил этот путь в вас отслеживающий: C:\Users\Stan Shunpike\Anaconda3\lib\encodings\cp1252.py. вам, вероятно, следует попытаться выяснить, как / где это используется. о, и вы используете csv.writer; в этом случае вам strдействительно нужно написать не bytes. ты что-то берешь requests? кодировка веб-ресурса может отличаться от utf-8.
Хиро, главный герой,
19

Он просто сообщает вам, что печатаемый вами объект не является строкой, а является байтовым объектом в виде байтового литерала . Люди объясняют это неполно, так что вот мой вывод.

Рассмотрите возможность создания байтового объекта , набрав байтовый литерал (буквально определяя байтовый объект без фактического использования байтового объекта, например, набрав b '') и преобразовав его в строковый объект, закодированный в utf-8. (Обратите внимание, что преобразование здесь означает декодирование )

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

Вы видите, что мы просто применяем .decode(utf8)функцию.

Байты в Python

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

Строковые литералы описываются следующими лексическими определениями:

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

Вам нужно декодировать его, чтобы преобразовать в строку. Проверьте здесь ответ о байтах буквально в python3 .

In [1]: b'I posted a new photo to Facebook'.decode('utf-8')
Out[1]: 'I posted a new photo to Facebook'
Салманвахед
источник
1
проблема в том, что когда я пытаюсь загрузить твиты без сообщения, encode("utf-8")я получаю ошибки. И, как я уже упоминал, удаление stackoverflow.com/q/41915383/4422095 не решило проблему. Даже если я использую декодирование, как вы предлагаете, я все равно получаю сообщение об ошибке. Я отправлю это в свой пост.
Stan Shunpike
сделанный. это не совсем то же самое, потому что для этого вам нужны коды Twitter OAuth. но если вы просто выполните приведенный мной пример, у вас возникнет та же проблема. это не решается предложенным вами методом. он просто отменяет UTF-8. но это не работает, потому что он не будет обрабатывать символы в твитах без кодировки utf-8
Стэн Шунпайк,
Конечно, вы должны использовать правильную кодировку. utf-8был примером.
salmanwahed
4

**** Как удалить символы b '', которые являются декодированной строкой в ​​python ****

import base64
a='cm9vdA=='
b=base64.b64decode(a).decode('utf-8')
print(b)
Авинаш Чугул
источник
2

В python 3.6 с django 2.0 декодирование байтового литерала не работает должным образом. Да, я получаю правильный результат, когда распечатываю его, но b'value все еще там, даже если вы распечатываете его правильно.

Это то, что я кодирую

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

Вот что я декодирую:

uid = force_text(urlsafe_base64_decode(uidb64))

Вот что говорит django 2.0:

urlsafe_base64_encode(s)[source]

Кодирует строку байтов в base64 для использования в URL-адресах, удаляя все конечные знаки равенства.

urlsafe_base64_decode(s)[source]

Декодирует строку в кодировке base64, добавляя любые конечные знаки равенства, которые могли быть удалены.


Это мой файл 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 %}

Это мой ответ консоли:

Content-Type: текст / простой; charset = "utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: Activate Your MySite Account From: webmaster @ localhost To: testuser@yahoo.com Дата: Пт, 20 апреля 2018 г. 06:26:46 - 0000 Идентификатор сообщения: <152420560682.16725.4597194169307598579@Dash-U>

Привет, тестировщик,

Щелкните ссылку ниже, чтобы подтвердить регистрацию:

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

как вы видете uid = b'MjU'

ожидается uid = MjU


тест в консоли:

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

После исследования выяснилось, что это связано с python 3. Мое решение было довольно простым:

'uid': user.pk,

Я получаю его как uidb64 в своей функции активации:

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

и вуаля:

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/

теперь работает нормально. :)

Фернандо Д Хайме
источник
Я считаю, что проблема не в декодировании, а в автоматическом экранировании в шаблоне, который не может разделить байтовый литерал в строку, как это делает декодирование.
Fernando D Jaime
1

Я сделал это, только закодировав вывод с помощью utf-8. Вот пример кода

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)

т.е.: не кодировать при сборе данных из api, кодировать только вывод (печать или запись).

DevJoe
источник
0

Предполагая, что вы не хотите немедленно декодировать его снова, как предлагают здесь другие, вы можете проанализировать его до строки, а затем просто удалить начало 'bи конец '.

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

Хотя вопрос очень старый, я думаю, он может быть полезен тем, кто сталкивается с той же проблемой. Здесь тексты представляют собой строку, как показано ниже:

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

Таким образом, вы не можете удалить b, закодировав его, потому что это не байт. Я сделал следующее, чтобы удалить его.

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

что даст "I posted a new photo to Facebook"

Камол Рой
источник
3
Нет, это даст "I posted a new photo to Facebook'". Во всяком случае, вопрос не в этом.
Tripleee