как преобразовать символы, подобные этим, «a³ a¡ a´a§» в юникод, используя python? - PullRequest
4 голосов
/ 30 августа 2011

Я делаю сканер, чтобы получить текст HTML внутри, я использую Beautifulsoup.

Когда я открываю URL с помощью 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 ]

1 голос
/ 09 ноября 2011

Во-первых, вы должны убедиться, что ваш сканер возвращает 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")

Вывод «Bei Jing»

0 голосов
/ 30 августа 2011

У вас есть байтовые данные. Вам нужны данные Unicode. Разве библиотека не должна декодировать это для вас? Это необходимо, потому что у вас нет заголовков HTTP и, следовательно, отсутствует кодировка.

EDIT

Как это ни странно звучит, похоже, что 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::UserAgent и HTTP::Response, чем эквивалентные классы Python. Проверьте это и посмотрите, что я имею в виду.

Кроме того, с Perl вы получаете лучшую поддержку Unicode, такую ​​как полная поддержка графем, то, чего в настоящее время нет в Python. Учитывая, что вы пытались убрать диакритические знаки, похоже, это был бы еще один плюс.

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

Просто мысль.

...