Sopa hermosa - Solución de problemas
Manejo de errores
Hay dos tipos principales de errores que deben manejarse en BeautifulSoup. Estos dos errores no son de su script sino de la estructura del fragmento porque la API de BeautifulSoup arroja un error.
Los dos errores principales son los siguientes:
AttributeError
Se produce cuando la notación de puntos no encuentra una etiqueta hermana en la etiqueta HTML actual. Por ejemplo, es posible que haya encontrado este error, debido a que falta una "etiqueta de anclaje", la clave de costo arrojará un error a medida que atraviesa y requiere una etiqueta de anclaje.
KeyError
Este error se produce si falta el atributo de etiqueta HTML necesario. Por ejemplo, si no tenemos el atributo data-pid en un fragmento, la clave pid arrojará key-error.
Para evitar los dos errores enumerados anteriormente al analizar un resultado, ese resultado se omitirá para asegurarse de que no se inserte un fragmento con formato incorrecto en las bases de datos:
except(AttributeError, KeyError) as er:
pass
diagnosticar()
Siempre que encontremos alguna dificultad para entender lo que BeautifulSoup hace con nuestro documento o HTML, simplemente páselo a la función diagnostose (). Al pasar el archivo de documento a la función diagnostose (), podemos mostrar cómo la lista de diferentes analizadores maneja el documento.
A continuación se muestra un ejemplo para demostrar el uso de la función diagnosticar ():
from bs4.diagnose import diagnose
with open("20 Books.html",encoding="utf8") as fp:
data = fp.read()
diagnose(data)
Salida
Error de sintáxis
Hay dos tipos principales de errores de análisis. Es posible que obtenga una excepción como HTMLParseError, cuando alimenta su documento a BeautifulSoup. También puede obtener un resultado inesperado, donde el árbol de análisis de BeautifulSoup se ve muy diferente del resultado esperado del documento de análisis.
Ninguno de los errores de análisis se debe a BeautifulSoup. Es debido al analizador externo que usamos (html5lib, lxml) ya que BeautifulSoup no contiene ningún código de analizador. Una forma de resolver el error de análisis anterior es utilizar otro analizador.
from HTMLParser import HTMLParser
try:
from HTMLParser import HTMLParseError
except ImportError, e:
# From python 3.5, HTMLParseError is removed. Since it can never be
# thrown in 3.5, we can just define our own class as a placeholder.
class HTMLParseError(Exception):
pass
El analizador HTML incorporado de Python causa dos errores de análisis más comunes, HTMLParser.HTMLParserError: etiqueta de inicio mal formada y HTMLParser.HTMLParserError: etiqueta final incorrecta y para resolver esto, es usar otro analizador principalmente: lxml o html5lib.
Otro tipo común de comportamiento inesperado es que no puede encontrar una etiqueta que sabe que está en el documento. Sin embargo, cuando ejecuta find_all () devuelve [] o find () devuelve None.
Esto puede deberse a que el analizador HTML incorporado de Python a veces omite etiquetas que no comprende.
Error del analizador XML
Por defecto, el paquete BeautifulSoup analiza los documentos como HTML, sin embargo, es muy fácil de usar y maneja XML mal formado de una manera muy elegante usando beautifulsoup4.
Para analizar el documento como XML, necesita tener un analizador lxml y solo necesita pasar el "xml" como segundo argumento al constructor Beautifulsoup -
soup = BeautifulSoup(markup, "lxml-xml")
o
soup = BeautifulSoup(markup, "xml")
Un error común de análisis de XML es:
AttributeError: 'NoneType' object has no attribute 'attrib'
Esto puede suceder en caso de que falte algún elemento o no esté definido mientras se usa la función find () o findall ().
Otros errores de análisis
A continuación se muestran algunos de los otros errores de análisis que vamos a discutir en esta sección:
Problema medioambiental
Además de los errores de análisis mencionados anteriormente, puede encontrar otros problemas de análisis, como problemas ambientales, en los que su script puede funcionar en un sistema operativo pero no en otro sistema operativo o puede funcionar en un entorno virtual pero no en otro entorno virtual o puede no funcionar fuera del entorno virtual. Todos estos problemas pueden deberse a que los dos entornos tienen diferentes bibliotecas de analizadores disponibles.
Se recomienda conocer o verificar su analizador predeterminado en su entorno de trabajo actual. Puede verificar el analizador predeterminado actual disponible para el entorno de trabajo actual o bien pasar explícitamente la biblioteca del analizador requerida como segundos argumentos al constructor BeautifulSoup.
No distingue entre mayúsculas y minúsculas
Como las etiquetas y atributos HTML no distinguen entre mayúsculas y minúsculas, los tres analizadores HTML convierten los nombres de etiquetas y atributos a minúsculas. Sin embargo, si desea conservar las etiquetas y los atributos en mayúsculas o minúsculas, es mejor analizar el documento como XML.
UnicodeEncodeError
Veamos el siguiente segmento de código:
soup = BeautifulSoup(response, "html.parser")
print (soup)
Salida
UnicodeEncodeError: 'charmap' codec can't encode character '\u011f'
El problema anterior puede deberse a dos situaciones principales. Es posible que esté intentando imprimir un carácter Unicode que su consola no sabe cómo mostrar. En segundo lugar, está intentando escribir en un archivo y pasa un carácter Unicode que no es compatible con su codificación predeterminada.
Una forma de resolver el problema anterior es codificar el texto / carácter de respuesta antes de preparar la sopa para obtener el resultado deseado, de la siguiente manera:
responseTxt = response.text.encode('UTF-8')
KeyError: [attr]
Se debe al acceso a la etiqueta ['attr'] cuando la etiqueta en cuestión no define el atributo attr. Los errores más comunes son: “KeyError: 'href'” y “KeyError: 'class'”. Utilice tag.get ('attr') si no está seguro de que attr esté definido.
for item in soup.fetch('a'):
try:
if (item['href'].startswith('/') or "tutorialspoint" in item['href']):
(...)
except KeyError:
pass # or some other fallback action
AttributeError
Puede encontrar AttributeError de la siguiente manera:
AttributeError: 'list' object has no attribute 'find_all'
El error anterior se produce principalmente porque esperaba que find_all () devolviera una sola etiqueta o cadena. Sin embargo, soup.find_all devuelve una lista de elementos de Python.
Todo lo que necesita hacer es recorrer la lista y capturar datos de esos elementos.