如何使用Python将这些字符转换为Unicode,"a³ a¡ a´a§"?

5 投票
2 回答
1444 浏览
提问于 2025-04-17 00:35

我正在制作一个爬虫程序,用来获取网页中的文本内容,我使用的是BeautifulSoup这个库。

当我用urllib2打开网址时,这个库会自动把原本带有葡萄牙语重音符的HTML内容,比如“ã ó é õ”,转换成其他字符,比如“a³ a¡ a´a§”。

我想要的只是去掉重音符的单词。

比如“contrã¡rio”要变成“contrario”。

我试过一个算法,但这个算法只适用于像“olá coração contrário”这样的文本。

   def strip_accents(s):
      return ''.join((c for c in unicodedata.normalize('NFD', s) if unicodedata.category(c) != 'Mn'))

2 个回答

-2

你有一些字节数据,但你需要的是Unicode数据。这个库不是应该帮你解码吗?它应该能做到,因为你没有HTTP头信息,所以不知道编码方式。

编辑

听起来有点奇怪,但似乎Python的网络库不支持内容解码。如果你运行这个程序:

#!/usr/bin/env python    
import re
import urllib.request
import io
import sys

for s in ("stdin","stdout","stderr"):
    setattr(sys, s, io.TextIOWrapper(getattr(sys, s).detach(), encoding="utf8"))

print("Seeking r\xe9sum\xe9s")

response = urllib.request.urlopen('http://nytimes.com/')
content  = response.read()

match    = re.search(".*r\xe9sum\xe9.*", content, re.I | re.U)
if match:
    print("success: " + match.group(0))
else:
    print("failure")

你会得到以下结果:

Seeking résumés
Traceback (most recent call last):
  File "ur.py", line 16, in <module>
    match    = re.search(".*r\xe9sum\xe9.*", content, re.I | re.U)
  File "/usr/local/lib/python3.2/re.py", line 158, in search
    return _compile(pattern, flags).search(string)
TypeError: can't use a string pattern on a bytes-like object

这意味着 .read() 返回的是原始字节,而不是一个真正的字符串。也许你能在这个urllib.request类的文档中找到我看不到的东西。我真不敢相信他们居然希望你自己去查 .info() 的返回值和 <meta> 标签,自己搞清楚那个烦人的编码,然后再解码,得到一个真正的字符串。这实在太糟糕了!我希望我错了,但我花了不少时间找,也没找到什么有用的信息。

再看看在Perl中做同样事情是多么简单:

#!/usr/bin/env perl    
use strict;
use warnings;    
use LWP::UserAgent;

binmode(STDOUT, "utf8");    
print("Seeking r\xe9sum\xe9s\n");

my $agent = LWP::UserAgent->new();
my $response = $agent->get("http://nytimes.com/");

if ($response->is_success) {
    my $content = $response->decoded_content;
    if ($content =~ /.*r\xe9sum\xe9.*/i) {
        print("search success: $&\n");
    } else {
        print("search failure\n");
    } 
} else {
    print "request failed: ", $response->status_line, "\n";
} 

运行后会得到:

Seeking résumés
search success: <li><a href="http://hiring.nytimes.monster.com/products/resumeproducts.aspx">Search Résumés</a></li>

你确定在Python中必须这样做吗?看看Perl的LWP::UserAgentHTTP::Response类,比起Python的对应类,它们要丰富和用户友好多了。去看看,你会明白我在说什么。

而且在Perl中,你会得到更好的Unicode支持,比如完整的字形支持,而这些Python目前还不具备。考虑到你想去掉变音符号,这似乎也是一个额外的好处。

 use Unicode::Normalize;
 ($unaccented = NFD($original)) =~ s/\pM//g;

只是个想法。

1

首先,你得确保你的爬虫程序返回的是unicode格式的HTML文本(比如,Scrapy有一个方法叫response.body_as_unicode(),就是用来做这个的)。

当你得到的unicode文本看起来很复杂,无法理解时,你需要把它转换成对应的ascii文本,这里有个步骤可以帮助你 - http://pypi.python.org/pypi/Unidecode/0.04.1

from unidecode import unidecode
print unidecode(u"\u5317\u4EB0")

输出结果是“Bei Jing”

撰写回答