Як позбутися префікса 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.