【问题标题】:How do I get rid of the b-prefix in a string in python?如何摆脱python字符串中的b前缀?
【发布时间】:2017-06-14 14:27:51
【问题描述】:

我正在导入的一堆推文在阅读时遇到了这个问题

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>

【问题讨论】:

标签: python


【解决方案1】:

你需要decodebytes你想要一个字符串:

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

【讨论】:

  • 我已经更新了问题。我认为这种方法行不通。如果有,您能详细说明原因吗?
  • .encode("utf-8").decode("utf-8") 绝对什么都不做(如果它确实有效的话)......你在 python 3 上,对吧? py3 在bytesstr 之间有很大的区别。您的代码中的某些内容似乎使用了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 不同。
【解决方案2】:

它只是让您知道您正在打印的对象不是字符串,而是作为 字节文字 的字节对象。人们以不完整的方式解释这一点,所以这是我的看法。

考虑通过键入字节文字(实际上定义字节对象而不实际使用字节对象,例如通过键入 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>

【讨论】:

    【解决方案3】:

    您需要对其进行解码以将其转换为字符串。在这里检查答案 about bytes literal in python3.

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

    【讨论】:

    • 这个问题是,当我尝试下载没有encode("utf-8") 的推文时,我得到了错误。而且,正如我在这里提到的,stackoverflow.com/q/41915383/4422095 删除并没有解决它。即使我按照您的建议使用解码,我仍然会收到错误消息。我将在帖子中发布。
    • 完成。这并不完全相同,因为您需要 twitter OAuth 代码来执行此操作。但如果你只是做我给出的例子,你会遇到同样的问题。你建议的方法没有解决。它只是撤消了 utf-8。 但这不起作用,因为它不会处理没有 utf-8 编码的推文中的字符
    • 您当然必须使用正确的编码。 utf-8 就是一个例子。
    【解决方案4】:

    ****如何删除python中解码字符串的b''字符****

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

    【讨论】:

      【解决方案5】:

      在带有 django 2.0 的 python 3.6 上,对字节文字的解码无法按预期工作。 是的,当我打印它时,我得到了正确的结果,但是即使您打印正确,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 %}
      

      这是我的控制台回复:

      内容类型:文本/纯文本;字符集="utf-8" MIME 版本:1.0 内容传输编码:7bit 主题:激活您的 MySite 帐户 来自:网站管理员@localhost 至:testuser@yahoo.com 日期:2018 年 4 月 20 日星期五 06:26:46 -0000 消息 ID:

      您好,测试用户,

      请点击以下链接确认您的注册:

      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/
      

      现在它工作正常。 :)

      【讨论】:

      • 我认为问题不在于解码,而是模板中的自动转义功能无法像解码一样将字节文字剥离成字符串。
      【解决方案6】:

      我通过仅使用 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 收集数据时不编码,仅编码输出(打印或写入)。

      【讨论】:

        【解决方案7】:

        假设您不想像其他人在这里建议的那样立即再次对其进行解码,您可以将其解析为一个字符串,然后去掉前导 '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"   
        

        【讨论】:

          【解决方案8】:

          虽然这个问题很老了,但我认为它可能对面临同样问题的人有所帮助。这里的文本是一个字符串,如下所示:

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

          因此,您不能通过编码来删除 b,因为它不是一个字节。我做了以下操作来删除它。

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

          这将给"I posted a new photo to Facebook"

          【讨论】:

          • 不,这将提供"I posted a new photo to Facebook'"。无论如何,这不是问题所在。
          猜你喜欢
          • 2019-01-17
          • 2012-11-19
          • 1970-01-01
          • 2011-04-22
          • 2020-06-01
          • 2014-03-24
          • 2011-01-19
          • 1970-01-01
          • 2011-02-05
          相关资源
          最近更新 更多