Возврат строки ASCII в нижнем регистре из строки (возможно, закодированной), выбранной с помощью urllib2 или BeautifulSoup - PullRequest
2 голосов
/ 26 января 2012

Я получаю данные с веб-страницы, используя urllib2. Содержание всех страниц написано на английском языке, поэтому нет проблем с неанглийским текстом. Однако страницы закодированы, и они иногда содержат элементы HTML, такие как £ или символ авторского права и т. Д.

Я хочу проверить, содержат ли части страницы определенные ключевые слова, однако я хочу сделать проверку без учета регистра (по очевидным причинам).

Каков наилучший способ преобразования содержимого возвращаемой страницы во все строчные буквы?

def get_page_content_as_lower_case(url):
    request = urllib2.Request(url)
    page = urllib2.urlopen(request)
    temp = page.read()

    return str(temp).lower() # this dosen't work because page contains utf-8 data

[[Обновить]]

Мне не нужно использовать urllib2 для получения данных, на самом деле я могу вместо этого использовать BeautifulSoup, поскольку мне нужно извлекать данные из определенного элемента (элементов) на странице - для которого BS является гораздо лучшим выбором. Я изменил название, чтобы отразить это.

ОДНАКО, проблема все еще остается в том, что извлеченные данные находятся в некотором кодировке, отличном от asci (который должен быть) в utf-8. Я проверил одну из страниц, и кодировка была iso-8859-1.

Поскольку меня интересует только английский язык, я хочу знать, как я могу получить строковую версию ASCII строчных букв данных, извлеченных со страницы, чтобы я мог выполнить чувствительный к регистру тест на предмет того, является ли ключевое слово встречается в тексте.

Я предполагаю, что тот факт, что я ограничился только английским (с англоязычных веб-сайтов), уменьшает выбор кодировки ?. Я не знаю много о кодировании, но я предполагаю, что допустимыми являются следующие варианты:

  • ASCII
  • ISO-8859-1
  • UTF-8

Является ли это допустимым предположением, и если да, возможно, есть способ написать «надежную» функцию, которая принимает закодированную строку, содержащую текст на английском языке, и возвращает строковую версию ASCII в нижнем регистре?

Ответы [ 3 ]

3 голосов
/ 26 января 2012

Поиск строки без учета регистра более сложен, чем простой поиск в строчном варианте.Например, немецкий пользователь может ожидать совпадения как STRASSE, так и Straße с поисковым термином Straße, но 'STRASSE'.lower() == 'strasse' (и вы не можете просто заменить двойной s на ß - в ß нет ß Trasse ).Другие языки (в частности, Turkish ) также будут иметь аналогичные сложности.

Если вы хотите поддерживать другие языки, кроме английского, вам следует использовать библиотеку, которая может обрабатывать правильные регистры (такие как Мэтью Барнетта regexp).

При этом способ извлечения содержимого страницы:

import contextlib
def get_page_content(url):
  with contextlib.closing(urllib2.urlopen(url)) as uh:
    content = uh.read().decode('utf-8')
  return content
  # You can call .lower() on the result, but that won't work in general
2 голосов
/ 26 января 2012

Или с Запросами :

page_text = requests.get(url).text
lowercase_text = page_text.lower()

(Запросы автоматически декодируют ответ.)

Как говорит @tchrist, .lower() не выполнит работудля текста в Unicode.

Вы можете проверить эту альтернативную реализацию регулярного выражения, которая реализует свертывание регистра для сравнения без учета регистра: Unicode: http://code.google.com/p/mrab-regex-hg/

Доступны также таблицы с регистрами: http://unicode.org/Public/UNIDATA/CaseFolding.txt

1 голос
/ 27 января 2012

BeautifulSoup хранит данные как Unicode внутри, поэтому вам не нужно выполнять манипуляции с кодировкой символов вручную.

Чтобы найти ключевые слова (без учета регистра) в тексте (, а не в значениях атрибутов)или имена тегов):

#!/usr/bin/env python
import urllib2
from contextlib import closing 

import regex # pip install regex
from BeautifulSoup import BeautifulSoup

with closing(urllib2.urlopen(URL)) as page:
     soup = BeautifulSoup(page)
     print soup(text=regex.compile(ur'(?fi)\L<keywords>',
                                   keywords=['your', 'keywords', 'go', 'here']))

Пример (слова Unicode от @tchrist)

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import regex
from BeautifulSoup import BeautifulSoup, Comment

html = u'''<div attr="PoSt in attribute should not be found">
<!-- it must not find post inside a comment either -->
<ol> <li> tag names must not match
<li> Post will be found
<li> the same with post
<li> and post
<li> and poſt
<li> this is ignored
</ol>
</div>'''

soup = BeautifulSoup(html)

# remove comments
comments = soup.findAll(text=lambda t: isinstance(t, Comment))
for comment in comments: comment.extract()

# find text with keywords (case-insensitive)
print ''.join(soup(text=regex.compile(ur'(?fi)\L<opts>', opts=['post', 'li'])))
# compare it with '.lower()'
print '.lower():'
print ''.join(soup(text=lambda t: any(k in t.lower() for k in ['post', 'li'])))
# or exact match
print 'exact match:'
print ''.join(soup(text=' the same with post\n'))

Вывод

 Post will be found
 the same with post
 and post
 and poſt

.lower():
 Post will be found
 the same with post

exact match:
 the same with post
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...