【问题标题】:how to convert characters like these,"a³ a¡ a´a§" in unicode, using python?如何使用python在unicode中转换像这样的字符,“a³ a¡ a´a§”?
【发布时间】:2011-11-06 10:12:17
【问题描述】:

我正在制作一个爬虫来获取文本 html,我正在使用 beautifulsoup。

当我使用 urllib2 打开 url 时,该库会自动将使用葡萄牙口音(如“ã ó é õ”)的 html 转换为其他字符(如“a³ a¡ a´a§”)

我想要的只是得到没有重音的单词

contrã¡rio -> 对比

我尝试使用这个算法,但是当文本使用“olá coração contrário”之类的词时,这个算法才有效

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

【问题讨论】:

  • 您的问题是自动转换不正确,还是您想将完全重音字符减少到最接近的ASCII 等效字符?还是两者兼而有之?
  • 问题中显示的规范化技巧是去除重音的好方法。唯一的问题一定是转换不起作用——如果 OP 对输出的渲染有点近似,问题可能是数据是 UTF-8 但被解释为 latin-1。
  • 我意识到,对于其他网站,我所做的正是我正在解决的问题。问题是这个网站。对我来说听起来很奇怪,因为当我看到网页的源代码时,看到的和其他网页的源代码一样。

标签: python string unicode utf-8 urllib


【解决方案1】:

首先,您必须确保您的爬虫返回的 HTML 是 unicode 文本(例如,Scrapy 有一个方法 response.body_as_unicode() 可以做到这一点)

一旦你有你无法理解的 unicode 文本,从 unicode 文本到等效 ascii 文本的步骤就在这里 - http://pypi.python.org/pypi/Unidecode/0.04.1

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

输出是“北京”

【讨论】:

    【解决方案2】:

    你有字节数据。您需要 Unicode 数据。图书馆不应该为你解码吗?必须这样做,因为您没有 HTTP 标头,因此缺少编码。

    编辑

    虽然这听起来很奇怪,但 Python 似乎不支持其 Web 库中的内容解码。如果你运行这个程序:

    #!/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() 正在返回原始字节而不是真正的字符串。也许你可以在doc for the urllib.request class 中看到一些我看不到的东西。我不敢相信他们真的希望你在.info() return 和&lt;meta&gt; 标签中扎根,自己找出愚蠢的编码,然后解码它,这样你就有了一个真正的字符串。那将是完全蹩脚的!我希望我是错的,但我花了很长时间寻找,在这里找不到任何有用的东西。

    比较在 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;
    

    只是一个想法。

    【讨论】:

    • 您是否尝试过使用 content.decode("utf-8") 将检索到的内容转换为字符串,然后再对其进行正则表达式搜索?如果你这样做 re.search(".*r\xe9sum\xe9.*", content.decode("utf-8"), re.I | re.U) 它工作正常
    • @wberry:我完全清楚我在做什么:你没读过“这意味着.read() 正在返回原始字节而不是真正的字符串。”? ??关键是 Python 类中没有 decoded_content 方法可以像 Perl 类中那样生成正确解码的字符串。 应该有。让用户自己做是不可接受的。
    • 如果 HTTP 只应该能够传递字符数据,那将是“完全蹩脚的”。但是 HTTP 可以很容易地传递图像等字节流,因此urllib API 为您提供字节。 Beautifulsoup 包旨在弥补这一差距。请不要急于对技术做出判断,除非问题要求这样做。
    • @tchrist 无论 python 和 perl 之间有什么区别,你认为 perl 有多方便都无关紧要。这是一个关于python而不是perl的问题,这种类型的讨论应该在其他地方进行。
    • @tchrist 如果您查看我的第一条评论,您将看到答案。我从来没有说过 python 是完美的,也没有说答案是错误的,你只是继续说在 perl 中它有多方便,在我看来,这不是这里所要求的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-10
    • 1970-01-01
    • 2017-11-21
    相关资源
    最近更新 更多