Devolver una cadena ASCII en minúsculas desde una cadena (posiblemente codificada) recuperada usando urllib2 o BeautifulSoup

Estoy recuperando datos de una página web usando urllib2. El contenido de todas las páginas está en el idioma inglés, por lo que no hay problema de tratar con texto que no esté en inglés. Sin embargo, las páginas están codificadas y, a veces, contienen entidades HTML como £ o el símbolo de copyright, etc.

Quiero verificar si algunas partes de una página contienen ciertas palabras clave; sin embargo, quiero hacer una verificación que no distinga mayúsculas y minúsculas (por razones obvias).

¿Cuál es la mejor manera de convertir el contenido de la página devuelta en letras minúsculas?

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 

[[Actualizar]]

No tengo que usar urllib2 para obtener los datos, de hecho puedo usar BeautifulSoup, ya que necesito recuperar datos de un elemento específico en la página, para los cuales BS es una opción mucho mejor. He cambiado el título para reflejar esto.

SIN EMBARGO, el problema sigue siendo que los datos buscados están en alguna encoding no asci (se supone que está) en utf-8. Verifiqué una de las páginas y la encoding fue iso-8859-1.

Ya que solo me preocupa el idioma inglés, quiero saber cómo puedo obtener una versión ASCII minúscula en minúscula de los datos recuperados de la página, para poder realizar una prueba de mayúsculas y minúsculas en cuanto a si se encuentra una palabra clave en el texto.

Supongo que el hecho de que me haya restringido solo al inglés (de los sitios web de habla inglesa) reduce las opciones de encoding. No sé mucho acerca de la encoding, pero supongo que las opciones válidas son:

  • ASCII
  • iso-8859-1
  • utf-8

¿Es una suposición válida y, en caso afirmativo, tal vez haya una forma de escribir una función ‘robusta’ que acepte una cadena codificada que contenga texto en inglés y devuelva una versión de la cadena ASCII en minúscula?

BeautifulSoup almacena datos como Unicode internamente, por lo que no necesita realizar manipulaciones de encoding de caracteres manualmente.

Para buscar palabras clave (que no distingan mayúsculas y minúsculas) en un texto ( no en valores de atributo o nombres de etiqueta):

 #!/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=['your', 'keywords', 'go', 'here'])) 

Ejemplo (palabras Unicode por @tchrist)

 #!/usr/bin/env python # -*- coding: utf-8 -*- import regex from BeautifulSoup import BeautifulSoup, Comment html = u'''
  1. tag names must not match
  2. Post will be found
  3. the same with post
  4. and post
  5. and poſt
  6. this is ignored
''' 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=['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'))

Salida

  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 

La búsqueda de cadenas que no distingue entre mayúsculas y minúsculas es más complicada que simplemente buscar en la variante de caja inferior. Por ejemplo, un usuario alemán esperaría relacionar tanto STRASSE como Straße con el término de búsqueda Straße , pero 'STRASSE'.lower() == 'strasse' (y no puede simplemente reemplazar una doble s con ß – hay no ß en Trasse ). Otros idiomas (en particular el turco ) también tendrán complicaciones similares.

Si desea admitir otros idiomas que no sean el inglés, debe utilizar una biblioteca que pueda manejar los casos adecuados (como la regexp Matthew Barnett ).

Dicho esto, la forma de extraer el contenido de la página es:

 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 

O con las solicitudes :

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

(Las solicitudes decodificarán automáticamente la respuesta.)

Como dice @tchrist, .lower() no hará el trabajo para texto Unicode.

Puede consultar esta implementación alternativa de expresiones regulares que implementa el plegado de casos para comparación insensible a mayúsculas y minúsculas en unicode: http://code.google.com/p/mrab-regex-hg/

También hay tablas de casos disponibles: http://unicode.org/Public/UNIDATA/CaseFolding.txt