Як позбутися префікса b у рядку в python?


88

Багато твітів, які я імпортую, мають цю проблему там, де вони читають

b'I posted a new photo to Facebook'

Я розумію, що bце байт. Але це виявляється проблематичним, оскільки в моїх файлах CSV, які я в кінцевому підсумку пишу, файл bне зникає і втручається в майбутній код.

Чи є простий спосіб видалити цей bпрефікс із моїх рядків тексту?

Майте на увазі, мені здається, що мені потрібно закодувати текст в utf-8, або у Твіпі виникають проблеми з витягуванням їх з Інтернету.


Ось вміст посилання, який я аналізую:

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 Вибачте, чого б Ви хотіли більше? Код чи вихід?
Stan Shunpike

Завжди вказуйте кодування під час відкриття файлів.
MKesper

Відповіді:


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"), що щось зроблю, але люди тут, здавалося, вважали, що це правильна відповідь, яка, наскільки я бачу, не така.
Стен Шанпайк,

я помітив цей шлях в вас відслідковує: 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

зроблено. це не зовсім однаково, тому що для цього вам потрібні коди OAuth у Twitter. але якщо ти просто зробиш приклад, який я наводив, ти отримаєш ту саму проблему. це не вирішується запропонованим методом u. він просто скасовує 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 %}

Це моя відповідь на консолі:

Тип вмісту: текст / звичайний; charset = "utf-8" MIME-версія: 1.0 Передача вмісту-кодування: 7 біт Тема: Активуйте свій акаунт MySite Від: webmaster @ localhost До: 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/

тепер це працює нормально. :)


Я вважаю, що проблема полягає не в декодуванні, а натомість у вимкненні автовиходу в шаблоні, який не може вилучити байтовий літерал у рядок так само, як це робить декодування.
Фернандо Д Хайме,

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, кодувати лише вихідні дані (друк або запис).


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'". У всякому разі, не в цьому питання.
триплеє
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.