如何在python中将url编码的字符串转换为正确的unicode字符串

时间:2017-02-06 12:47:35

标签: python unicode utf-8 scrapy mojibake

我正在学习使用在python 2.x中运行的scrapinghub.com 我编写了一个使用Scrapy的脚本,我已经抓了一个字符串,如下所示:

%3Ctable%20width%3D%22100%25%22%3E%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctr%3E%3Ctd%3E%3Cp%20style%3D%22color%3A%23ff0000%3Bfont-size%3A20pt%3Btext-align%3Acenter%3Bfont-weight%3Abold%22%3E%0D%0A%09%E6%84%9B%E8%BF%AA%E9%81%94%20adidas%20Energy%20Boost%20%E8%B7%AF%E8%B7%91%20%E4%BD%8E%E7%AD%92%20%E9%81%8B%E5%8B%95%20%E4%BC%91%E9%96%92%20%E8%B7%91%E9%9E%8B%20%E8%B7%91%E6%AD%A5%20%E6%85%A2%E8%B7%91%20%E9%A6%AC%E6%8B%89%E6%9D%BE%20%E5%81%A5%E8%BA%AB%E6%88%BF%20%E6%B5%81%E8%A1%8C%20%E7%90%83%E9%9E%8B%20%E5%A5%B3%E8%A3%9D%20%E5%A5%B3%E6%AC%BE%20%E5%A5%B3%20%E5%A5%B3%E9%9E%8B%0D%0A%3C%2Fp%3E%0D%0A%3C%2Ftd%3E%3C%2Ftr%3E%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctr%3E%3Ctd%3E%3Cp%20style%3D%22color%3A%23000000%3Bfont-size%3A14pt%3Btext-align%3Acenter%22%3E%0D%0A%09%EF%BC%8A%E9%9D%88%E6%B4%BB%E3%80%81%E8%BC%95%E9%87%8F%E3%80%81%E8%88%92%E9%81%A9%E5%85%BC%E5%85%B7%E7%9A%84%E9%81%B8%E6%93%87%3Cbr%20%2F%3E%EF%BC%8A%E7%B0%A1%E7%B4%84%E7%8F%BE%E4%BB%A3%E7%9A%84%E7%94%A2%E5%93%81%E8%A8%AD%E8%A8%88%2C%E5%B9%B4%E8%BC%95%E5%A4%9A%E6%A8%A3%E5%8C%96%E7%9A%84%E9%85%8D%E8%89%B2%E6%96%B9%E6%A1%88%2C%E6%9B%B4%E7%82%BA%E7%AC%A6%E5%90%88%E5%B9%B4%E8%BC%95%E6%B6%88%E8%B2%BB%E8%80%85%E7%9A%84%E5%AF%A9%E7%BE%8E%E5%81%8F%E5%A5%BD%3Cbr%20%2F%3E%EF%BC%8A%E7%B0%A1%E5%96%AE%E7%9A%84%E7%B7%9A%E6%A2%9D%E5%92%8C%E4%B9%BE%E6%B7%A8%E7%9A%84%E8%A8%AD%E8%A8%88%2C%E6%8F%90%E4%BE%9B%E4%BA%86%E7%8D%A8%E7%89%B9%E7%9A%84%E7%A9%BF%E6%90%AD%E7%B5%84%E5%90%88%3Cbr%20%2F%3E%EF%BC%8A%E9%80%8F%E6%B0%A3%E8%88%87%E4%BF%9D%E8%AD%B7%E6%80%A7%2C%E7%B5%90%E5%90%88%E4%BA%86ADIDAS%E7%9A%84%E5%89%B5%E6%96%B0%E7%A7%91%E6%8A%80%2C%E5%89%B5%E9%80%A0%E4%BA%86%E5%AE%8C%E7%BE%8E%E7%9A%84%E7%94%A2%E5%93%81%3Cbr%20%2F%3E%0D%0A%3C%2Fp%3E%0D%0A%3C%2Ftd%3E%3C%2Ftr%3E%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctr%3E%3Ctd%3E%3Cdiv%20align%3D%22center%22%3E%3Cimg%20src%3D%22https%3A%2F%2Fs.yimg.com%2Fwb%2Fimages%2F2B558E585E39649599A9A266349EABD17A4ABC18%22%20%2F%3E%3C%2Fdiv%3E%3C%2Ftd%3E%3C%2Ftr%3E%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Ftable%3E%3Ctable%20width%3D%22100%25%22%3E%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctr%3E%3Ctd%3E%3Cp%20style%3D%22color%3A%23000000%3Bfont-size%3A12pt%3Btext-align%3Aleft%3Bfont-weight%3A100%22%3E%0D%0A%09%0D%0A%3C%2Fp%3E%0D%0A%3C%2Ftd%3E%3C%2Ftr%3E%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctr%3E%3Ctd%3E%3Cdiv%20align%3D%22center%22%3E%3Cimg%20src%3D%22https%3A%2F%2Fs.yimg.com%2Fwb%2Fimages%2F0F1A6CBFE6F6631189D491A17A2A2E7C388F194E%22%20%2F%3E%3Cdiv%3E%3C%2Ftd%3E%3C%2Ftr%3E%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctr%3E%3Ctd%3E%3C%2Ftd%3E%3C%2Ftr%3E%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Ftable%3E%3Ctable%20width%3D%22100%25%22%3E%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctr%3E%3Ctd%3E%3Cp%20style%3D%22color%3A%23000000%3Bfont-size%3A12pt%3Btext-align%3Aleft%3Bfont-weight%3A100%22%3E%0D%0A%09%0D%0A%3C%2Fp%3E%0D%0A%3C%2Ftd%3E%3C%2Ftr%3E%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctr%3E%3Ctd%3E%3Cdiv%20align%3D%22center%22%3E%3Cimg%20src%3D%22https%3A%2F%2Fs.yimg.com%2Fwb%2Fimages%2FA0C9B09CAC784E2CA81A572E8F9F2E5721812607%22%20%2F%3E%3Cdiv%3E%3C%2Ftd%3E%3C%2Ftr%3E%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctr%3E%3Ctd%3E%3C%2Ftd%3E%3C%2Ftr%3E%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Ftable%3E

总是给我以下内容:

<table width="100%"> <tr><td><p style="color:#fa6b81;font-size:18pt;text-align:center;font-weight:bold">(女) æ迪é ADIDAD ENERGY CLOUD W éæ°£ç¶²å¸ ç¾æ­ é» èè·ç¶  ä¼éé æ¢è·é</p></td></tr> <tr><td><p style="color:#000000;font-size:12pt;text-align:center"><font color="BLUE">â»æ¬è³£å ´åççºYAHOOè³¼ç©ä¸­å¿å°ç¨ï¼å¶å®å¹³å°è¥ä½¿ç¨æ¬ç«ç¸éåç~ç屬侵æ¬!!</font><BR><BR></p></td></tr> <tr><td><div align="center"><img src="https://s.yimg.com/wb/images/739F6D54CD0AA4440D67A8BF0E569B0229AB1B37" /></div></td></tr> </table><table width="100%"> <tr><td><p style="color:#000000;font-size:12pt;text-align:left;font-weight:100"></p></td></tr> <tr><td><div align="center"><img src="https://s.yimg.com/wb/images/91D28279378AF5E3C26740855775ECAD3A7F4A6B" /><div></td></tr> <tr><td></td></tr> </table><table width="100%"> <tr><td><p style="color:#000000;font-size:12pt;text-align:left;font-weight:100"></p></td></tr> <tr><td><div align="center"><img src="https://s.yimg.com/wb/images/B2237D69C0886CCF330AFA459E3C03BB4454D01B" /><div></td></tr> <tr><td></td></tr> </table><table width="100%"> <tr><td><p style="color:#000000;font-size:12pt;text-align:left;font-weight:100"></p></td></tr> <tr><td><div align="center"><img src="https://s.yimg.com/wb/images/B60D486A89EDBAFBFE824F00309D069517654050" /><div></td></tr> <tr><td></td></tr> </table><table width="100%"> <tr><td><p style="color:#000000;font-size:12pt;text-align:left;font-weight:100"></p></td></tr> <tr><td><div align="center"><img src="https://s.yimg.com/wb/images/57EAC1C8B09A019AC734F50FB51DB87D0B319002" /><div></td></tr> <tr><td></td></tr> </table><table width="100%"> <tr><td><p style="color:#000000;font-size:12pt;text-align:left;font-weight:100"></p></td></tr> <tr><td><div align="center"><img src="https://s.yimg.com/wb/images/CEC5C31984853968755AE7465BCB251C82676B0B" /><div></td></tr> <tr><td></td></tr> </table><table width="100%"> <tr><td><p style="color:#000000;font-size:12pt;text-align:left;font-weight:100"></p></td></tr> <tr><td><div align="center"><img src="https://s.yimg.com/wb/images/B065DFBACAEC5ABED898492265DEB710EA052358" /><div></td></tr> <tr><td></td></tr> </table>

我总是得到垃圾文本(女) æ迪é ADIDAD ENERGY CLOUD W é氣網å¸

从url编码文本到unicode的转换代码如下所示

special_text = re.sub("<.*?>", "", special_text)
special_text = re.sub("<!--", "", special_text)
special_text = re.sub("-->", "", special_text)
special_text = re.sub("\n", "", special_text)
special_text = special_text.strip()
special_text = unquote(special_text)
special_text = re.sub("\n", "", special_text)
special_text = re.sub("\r", "", special_text)
special_text = re.sub("\t", "", special_text)
special_text = u' '.join((special_text, '')).encode('utf-8').strip()

我尝试过很多不同的代码,比如

special_text = special_text.encode('utf-8')
special_text = special_text.decode('utf-8')

哪个给我错误或者仍然是垃圾文本

不确定转换为unicode的正确方法是什么?

2 个答案:

答案 0 :(得分:4)

您的数据是完全有效的UTF-8,编码为URL(因此URLEncoded)。您的输出表明您正在查看Mojibake,您自己的软件(控制台,终端,文本编辑器)正在使用不同的编解码器来解释UTF-8数据。我怀疑你的设置是使用CP-1254:

>>> print text.encode('utf8').decode('sloppy-cp1254')  # codec from the ftfy project
æ„›è¿ªé” adidas Energy Boost 路跑 ä½ç­’ é‹å‹• 休閒 è·‘é‹ è·‘æ­¥ 慢跑 é¦¬æ‹‰æ¾ å¥èº«æˆ¿ æµè¡Œ çƒé‹ å¥³è£ å¥³æ¬¾ 女 女é‹
*éˆæ´»ã€è¼•é‡ã€èˆ’é©å…¼å…·çš„é¸æ“‡
*簡約ç¾ä»£çš„產å“設計,年輕多樣化的é…色方案,更為符åˆå¹´è¼•æ¶ˆè²»è€…的審ç¾å好
*簡單的線æ¢å’Œä¹¾æ·¨çš„設計,æ供了ç¨ç‰¹çš„ç©¿æ­çµ„åˆ
*é€æ°£èˆ‡ä¿è­·æ€§,çµåˆäº†ADIDAS的創新科技,創造了完ç¾çš„產å“

如果您不知道如何修复终端,我建议您将数据写入文件,并使用编辑器告诉您使用哪种编解码器来读取数据:

import io
with io.open('somefilename.txt', encoding='utf8') as f:
    f.write(unicode_value)

我还强烈建议您使用实际的HTML解析器来处理数据,而不是依赖正则表达式。以下Python 2和3代码使用URL中的文本信息生成Unicode值:

from bs4 import BeautifulSoup
try:
    from urllib import unquote
except ImportError:
    from urllib.parse import unquote

soup = BeautifulSoup(unquote(special_text), 'html.parser')  # consider installing lxml instead
text = soup.get_text('\n', strip=True)  # put newlines between sections
print(text)

对于您的输入,在配置为将Unicode文本处理为UTF-8的Mac OSX终端上,我看到:

愛迪達 adidas Energy Boost 路跑 低筒 運動 休閒 跑鞋 跑步 慢跑 馬拉松 健身房 流行 球鞋 女裝 女款 女 女鞋
*靈活、輕量、舒適兼具的選擇
*簡約現代的產品設計,年輕多樣化的配色方案,更為符合年輕消費者的審美偏好
*簡單的線條和乾淨的設計,提供了獨特的穿搭組合
*透氣與保護性,結合了ADIDAS的創新科技,創造了完美的產品

答案 1 :(得分:0)

我不知道为什么,但出于某种原因,我让它在下面的scrapinghub.com上工作。

假设我有一个HTML文本:

<html>
<div class="a">
   Some chinese text
</div>
<div class="b">
   QUOTED text got chinese in it
   %3Ctable%20width%3D%22100%25%22%3E%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctr%3E%3Ctd%3E%3Cp%20style%3D%22color%3A%23ff0000%3Bfont-size%3A20pt%3Btext-align%3Acenter%3Bfont-weight%3Abold%22%3E%0D%0A%09%E6%84%9B%E8%BF%AA%E9%81%94%20adidas%20Energy%20Boost%20%E8%B7%AF%E8%B7%91%20%E4%BD%8E%E7%AD%92%20%E9%81%8B%E5%8B%95%20%E4%BC%91%E9%96%92%20%E8%B7%91%E9%9E%8B%20%E8%B7%91%E6%AD%A5%20%E6%85%A2%E8%B7%91%20%E9%A6%AC%E6%8B%89%E6%9D%BE%20%E5%81%A5%E8%BA%AB%E6%88%BF%20%E6%B5%81%E8%A1%8C%20%E7%90%83%E9%9E%8B%20%E5%A5%B3%E8%A3%9D%20%E5%A5%B3%E6%AC%BE%20%E5%A5%B3%20%E5%A5%B3%E9%9E%8B%0D%0A%3C%2Fp%3E%0D%0A%3C%2Ftd%3E%3C%2Ftr%3E%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctr%3E%3Ctd%3E%3Cp%20style%3D%22color%3A%23000000%3Bfont-size%3A14pt%3Btext-align%3Acenter%22%3E%0D%0A%09%EF%BC%8A%E9%9D%88%E6%B4%BB%E3%80%81%E8%BC%95%E9%87%8F%E3%80%81%E8%88%92%E9%81%A9%E5%85%BC%E5%85%B7%E7%9A%84%E9%81%B8%E6%93%87%3Cbr%20%2F%3E%EF%BC%8A%E7%B0%A1%E7%B4%84%E7%8F%BE%E4%BB%A3%E7%9A%84%E7%94%A2%E5%93%81%E8%A8%AD%E8%A8%88%2C%E5%B9%B4%E8%BC%95%E5%A4%9A%E6%A8%A3%E5%8C%96%E7%9A%84%E9%85%8D%E8%89%B2%E6%96%B9%E6%A1%88%2C%E6%9B%B4%E7%82%BA%E7%AC%A6%E5%90%88%E5%B9%B4%E8%BC%95%E6%B6%88%E8%B2%BB%E8%80%85%E7%9A%84%E5%AF%A9%E7%BE%8E%E5%81%8F%E5%A5%BD%3Cbr%20%2F%3E%EF%BC%8A%E7%B0%A1%E5%96%AE%E7%9A%84%E7%B7%9A%E6%A2%9D%E5%92%8C%E4%B9%BE%E6%B7%A8%E7%9A%84%E8%A8%AD%E8%A8%88%2C%E6%8F%90%E4%BE%9B%E4%BA%86%E7%8D%A8%E7%89%B9%E7%9A%84%E7%A9%BF%E6%90%AD%E7%B5%84%E5%90%88%3Cbr%20%2F%3E%EF%BC%8A%E9%80%8F%E6%B0%A3%E8%88%87%E4%BF%9D%E8%AD%B7%E6%80%A7%2C%E7%B5%90%E5%90%88%E4%BA%86ADIDAS%E7%9A%84%E5%89%B5%E6%96%B0%E7%A7%91%E6%8A%80%2C%E5%89%B5%E9%80%A0%E4%BA%86%E5%AE%8C%E7%BE%8E%E7%9A%84%E7%94%A2%E5%93%81%3Cbr%20%2F%3E%0D%0A%3C%2Fp%3E%0D%0A%3C%2Ftd%3E%3C%2Ftr%3E%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctr%3E%3Ctd%3E%3Cdiv%20align%3D%22center%22%3E%3Cimg%20src%3D%22https%3A%2F%2Fs.yimg.com%2Fwb%2Fimages%2F2B558E585E39649599A9A266349EABD17A4ABC18%22%20%2F%3E%3C%2Fdiv%3E%3C%2Ftd%3E%3C%2Ftr%3E%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Ftable%3E%3Ctable%20width%3D%22100%25%22%3E%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctr%3E%3Ctd%3E%3Cp%20style%3D%22color%3A%23000000%3Bfont-size%3A12pt%3Btext-align%3Aleft%3Bfont-weight%3A100%22%3E%0D%0A%09%0D%0A%3C%2Fp%3E%0D%0A%3C%2Ftd%3E%3C%2Ftr%3E%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctr%3E%3Ctd%3E%3Cdiv%20align%3D%22center%22%3E%3Cimg%20src%3D%22https%3A%2F%2Fs.yimg.com%2Fwb%2Fimages%2F0F1A6CBFE6F6631189D491A17A2A2E7C388F194E%22%20%2F%3E%3Cdiv%3E%3C%2Ftd%3E%3C%2Ftr%3E%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctr%3E%3Ctd%3E%3C%2Ftd%3E%3C%2Ftr%3E%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Ftable%3E%3Ctable%20width%3D%22100%25%22%3E%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctr%3E%3Ctd%3E%3Cp%20style%3D%22color%3A%23000000%3Bfont-size%3A12pt%3Btext-align%3Aleft%3Bfont-weight%3A100%22%3E%0D%0A%09%0D%0A%3C%2Fp%3E%0D%0A%3C%2Ftd%3E%3C%2Ftr%3E%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctr%3E%3Ctd%3E%3Cdiv%20align%3D%22center%22%3E%3Cimg%20src%3D%22https%3A%2F%2Fs.yimg.com%2Fwb%2Fimages%2FA0C9B09CAC784E2CA81A572E8F9F2E5721812607%22%20%2F%3E%3Cdiv%3E%3C%2Ftd%3E%3C%2Ftr%3E%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3Ctr%3E%3Ctd%3E%3C%2Ftd%3E%3C%2Ftr%3E%0D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3C%2Ftable%3E
</div>
</html>

所以我解析它来分配class =&#34; a&#34;到变量AAA,class =&#34; b&#34;变量BBB

如果我想取消引用BBB并正确显示中文字符,请执行以下操作:

BBB = u' '.join((BBB, ''))
BBB = BBB.encode('ascii')
BBB = unquote(BBB)

所以当我输出AAA和amp;在scrapinghub上BBB,它将正确显示中文文本。

我只是想指出,当我在MAC上本地做这个时,Martijn Pieters的回答也是正确的。但是我不确定在scrapinghub中我需要做什么。