Piękna zupa - rozwiązywanie problemów

Obsługa błędów

W BeautifulSoup trzeba obsłużyć dwa główne rodzaje błędów. Te dwa błędy nie pochodzą z Twojego skryptu, ale ze struktury fragmentu kodu, ponieważ interfejs API BeautifulSoup zgłasza błąd.

Dwa główne błędy są następujące -

AttributeError

Dzieje się tak, gdy notacja kropkowa nie znajduje tagu równorzędnego z bieżącym znacznikiem HTML. Na przykład mógł wystąpić ten błąd z powodu braku „tagu kotwicy”, klucz kosztu zgłosi błąd, gdy przechodzi i wymaga tagu kotwicy.

KeyError

Ten błąd występuje, jeśli brakuje wymaganego atrybutu tagu HTML. Na przykład, jeśli nie mamy atrybutu data-pid we fragmencie, klucz pid zgłosi błąd klucza.

Aby uniknąć wymienionych powyżej dwóch błędów podczas analizowania wyniku, ten wynik zostanie pominięty, aby upewnić się, że źle sformułowany fragment nie zostanie wstawiony do baz danych -

except(AttributeError, KeyError) as er:
pass

rozpoznać chorobę()

Ilekroć napotkamy trudności w zrozumieniu, co robi BeautifulSoup z naszym dokumentem lub HTML, po prostu przekaż to do funkcji diagnose (). Przekazując plik dokumentu do funkcji diagnose (), możemy pokazać, jak lista różnych parserów obsługuje dokument.

Poniżej znajduje się przykład ilustrujący użycie funkcji diagnose () -

from bs4.diagnose import diagnose

with open("20 Books.html",encoding="utf8") as fp:
   data = fp.read()
   
diagnose(data)

Wynik

Błąd analizy

Istnieją dwa główne typy błędów analizy. Możesz otrzymać wyjątek, taki jak HTMLParseError, podczas przesyłania dokumentu do BeautifulSoup. Możesz również otrzymać nieoczekiwany wynik, w którym drzewo analizy BeautifulSoup wygląda znacznie inaczej niż oczekiwany wynik z dokumentu analizy.

Żaden z błędów analizy nie jest spowodowany przez BeautifulSoup. Dzieje się tak z powodu zewnętrznego parsera, którego używamy (html5lib, lxml), ponieważ BeautifulSoup nie zawiera żadnego kodu parsera. Jednym ze sposobów rozwiązania powyższego błędu analizy jest użycie innego parsera.

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

Wbudowany parser HTML w Pythonie powoduje dwa najczęściej występujące błędy parsowania, HTMLParser.HTMLParserError: nieprawidłowy tag początkowy i HTMLParser.HTMLParserError: zły tag końcowy. Aby rozwiązać ten problem, należy użyć innego parsera, głównie: lxml lub html5lib.

Innym częstym typem nieoczekiwanego zachowania jest to, że nie możesz znaleźć znacznika, o którym wiesz, że znajduje się w dokumencie. Jednak po uruchomieniu find_all () zwraca [] lub find () zwraca None.

Może to być spowodowane tym, że wbudowany w Python parser HTML czasami pomija tagi, których nie rozumie.

Błąd parsera XML

Domyślnie pakiet BeautifulSoup analizuje dokumenty jako HTML, jednak jest bardzo łatwy w użyciu i obsługuje źle sformułowany XML w bardzo elegancki sposób, używając beautifulsoup4.

Aby przeanalizować dokument jako XML, musisz mieć parser lxml i wystarczy przekazać „xml” jako drugi argument do konstruktora Beautifulsoup -

soup = BeautifulSoup(markup, "lxml-xml")

lub

soup = BeautifulSoup(markup, "xml")

Jednym z typowych błędów analizy XML jest -

AttributeError: 'NoneType' object has no attribute 'attrib'

Może się to zdarzyć w przypadku, gdy brakuje jakiegoś elementu lub nie jest on zdefiniowany podczas korzystania z funkcji find () lub findall ().

Inne błędy analizy

Poniżej podano kilka innych błędów analizy, które omówimy w tej sekcji -

Problem środowiskowy

Oprócz wyżej wymienionych błędów analizy, możesz napotkać inne problemy z analizą, takie jak problemy środowiskowe, w których twój skrypt może działać w jednym systemie operacyjnym, ale nie w innym systemie operacyjnym lub może działać w jednym środowisku wirtualnym, ale nie w innym środowisku wirtualnym lub może nie działać poza środowiskiem wirtualnym. Wszystkie te problemy mogą wynikać z faktu, że oba środowiska mają dostępne różne biblioteki parserów.

Zaleca się poznanie lub sprawdzenie domyślnego parsera w bieżącym środowisku pracy. Możesz sprawdzić bieżący domyślny parser dostępny dla bieżącego środowiska pracy lub przekazać jawnie wymaganą bibliotekę parsera jako drugie argumenty do konstruktora BeautifulSoup.

Bez rozróżniania wielkości liter

Ponieważ w znacznikach i atrybutach HTML wielkość liter nie jest rozróżniana, wszystkie trzy parsery HTML konwertują nazwy znaczników i atrybutów na małe litery. Jeśli jednak chcesz zachować znaczniki i atrybuty pisane wielkimi lub dużymi literami, lepiej przeanalizować dokument jako XML.

UnicodeEncodeError

Przyjrzyjmy się poniższemu segmentowi kodu -

soup = BeautifulSoup(response, "html.parser")
   print (soup)

Wynik

UnicodeEncodeError: 'charmap' codec can't encode character '\u011f'

Powyższy problem może wynikać z dwóch głównych sytuacji. Być może próbujesz wydrukować znak Unicode, którego Twoja konsola nie potrafi wyświetlić. Po drugie, próbujesz pisać do pliku i przekazujesz znak Unicode, który nie jest obsługiwany przez domyślne kodowanie.

Jednym ze sposobów rozwiązania powyższego problemu jest zakodowanie tekstu / znaku odpowiedzi przed przygotowaniem zupy, aby uzyskać pożądany rezultat, w następujący sposób -

responseTxt = response.text.encode('UTF-8')

KeyError: [atr]

Jest to spowodowane dostępem do tagu ['attr'], gdy dany tag nie definiuje atrybutu attr. Najczęstsze błędy to: „KeyError: 'href'” i „KeyError: 'class'”. Użyj tag.get ('attr'), jeśli nie jesteś pewien, czy attr jest zdefiniowany.

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

Możesz napotkać AttributeError w następujący sposób -

AttributeError: 'list' object has no attribute 'find_all'

Powyższy błąd występuje głównie dlatego, że oczekiwano, że funkcja find_all () zwróci pojedynczy tag lub ciąg. Jednak soup.find_all zwraca listę elementów w języku Python.

Wszystko, co musisz zrobić, to powtórzyć listę i złapać dane z tych elementów.