Beautiful Soup - Bắn rắc rối

Xử lý lỗi

Có hai loại lỗi chính cần được xử lý trong BeautifulSoup. Hai lỗi này không phải từ tập lệnh của bạn mà từ cấu trúc của đoạn mã vì API BeautifulSoup tạo ra một lỗi.

Hai lỗi chính như sau:

AttributeError

Nó được gây ra khi ký hiệu dấu chấm không tìm thấy thẻ anh em với thẻ HTML hiện tại. Ví dụ: bạn có thể đã gặp phải lỗi này, vì thiếu "thẻ liên kết", khóa chi phí sẽ tạo ra lỗi khi nó đi ngang qua và yêu cầu thẻ liên kết.

KeyError

Lỗi này xảy ra nếu thiếu thuộc tính thẻ HTML bắt buộc. Ví dụ: nếu chúng ta không có thuộc tính data-pid trong một đoạn mã, thì khóa pid sẽ tạo ra lỗi khóa.

Để tránh hai lỗi được liệt kê ở trên khi phân tích cú pháp một kết quả, kết quả đó sẽ được bỏ qua để đảm bảo rằng đoạn mã không đúng định dạng không được chèn vào cơ sở dữ liệu -

except(AttributeError, KeyError) as er:
pass

chẩn đoán ()

Bất cứ khi nào chúng tôi gặp bất kỳ khó khăn nào trong việc hiểu BeautifulSoup làm gì với tài liệu hoặc HTML của mình, chỉ cần chuyển nó vào hàm chẩn đoán (). Khi chuyển tệp tài liệu đến hàm chẩn đoán (), chúng tôi có thể hiển thị cách danh sách trình phân tích cú pháp khác nhau xử lý tài liệu.

Dưới đây là một ví dụ để chứng minh việc sử dụng hàm chẩn đoán () -

from bs4.diagnose import diagnose

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

Đầu ra

Lỗi phân tích cú pháp

Có hai loại lỗi phân tích cú pháp chính. Bạn có thể gặp một ngoại lệ như HTMLParseError, khi bạn cấp tài liệu của mình cho BeautifulSoup. Bạn cũng có thể nhận được một kết quả không mong muốn, trong đó cây phân tích cú pháp BeautifulSoup trông rất khác so với kết quả mong đợi từ tài liệu phân tích cú pháp.

Không có lỗi phân tích cú pháp nào là do BeautifulSoup. Đó là do trình phân tích cú pháp bên ngoài mà chúng tôi sử dụng (html5lib, lxml) vì BeautifulSoup không chứa bất kỳ mã phân tích cú pháp nào. Một cách để giải quyết lỗi phân tích cú pháp ở trên là sử dụng một trình phân tích cú pháp khác.

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

Trình phân tích cú pháp HTML tích hợp trong Python gây ra hai lỗi phân tích cú pháp phổ biến nhất, HTMLParser.HTMLParserError: thẻ bắt đầu không đúng định dạng và HTMLParser.HTMLParserError: thẻ kết thúc không hợp lệ và để giải quyết điều này, chủ yếu là sử dụng một trình phân tích cú pháp khác: lxml hoặc html5lib.

Một loại hành vi không mong muốn phổ biến khác là bạn không thể tìm thấy thẻ mà bạn biết là có trong tài liệu. Tuy nhiên, khi bạn chạy find_all () trả về [] hoặc find () trả về None.

Điều này có thể do trình phân tích cú pháp HTML tích hợp trong python đôi khi bỏ qua các thẻ mà nó không hiểu.

Lỗi phân tích cú pháp XML

Theo mặc định, gói BeautifulSoup phân tích cú pháp các tài liệu dưới dạng HTML, tuy nhiên, nó rất dễ sử dụng và xử lý XML không đúng định dạng một cách rất thanh lịch bằng cách sử dụng beautifulsoup4.

Để phân tích cú pháp tài liệu dưới dạng XML, bạn cần có trình phân tích cú pháp lxml và bạn chỉ cần chuyển “xml” làm đối số thứ hai cho hàm tạo Beautifulsoup -

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

hoặc là

soup = BeautifulSoup(markup, "xml")

Một lỗi phân tích cú pháp XML phổ biến là:

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

Điều này có thể xảy ra trong trường hợp, một số phần tử bị thiếu hoặc không được xác định khi sử dụng hàm find () hoặc findall ().

Các lỗi phân tích cú pháp khác

Dưới đây là một số lỗi phân tích cú pháp khác mà chúng ta sẽ thảo luận trong phần này -

Vấn đề môi trường

Ngoài các lỗi phân tích cú pháp được đề cập ở trên, bạn có thể gặp phải các vấn đề phân tích cú pháp khác chẳng hạn như các vấn đề môi trường trong đó tập lệnh của bạn có thể hoạt động trong một hệ điều hành nhưng không hoạt động trong một hệ điều hành khác hoặc có thể hoạt động trong một môi trường ảo nhưng không hoạt động trong môi trường ảo khác hoặc có thể không hoạt động ngoài môi trường ảo. Tất cả những vấn đề này có thể là do hai môi trường có sẵn các thư viện phân tích cú pháp khác nhau.

Bạn nên biết hoặc kiểm tra trình phân tích cú pháp mặc định của mình trong môi trường làm việc hiện tại của bạn. Bạn có thể kiểm tra trình phân tích cú pháp mặc định hiện tại có sẵn cho môi trường làm việc hiện tại hoặc nếu không thì chuyển một cách rõ ràng thư viện trình phân tích cú pháp bắt buộc làm đối số thứ hai cho hàm tạo BeautifulSoup.

Trường hợp không nhạy cảm

Vì các thẻ và thuộc tính HTML không phân biệt chữ hoa chữ thường, nên cả ba trình phân tích cú pháp HTML đều chuyển đổi tên thẻ và thuộc tính thành chữ thường. Tuy nhiên, nếu bạn muốn duy trì các thẻ và thuộc tính dạng hỗn hợp hoặc chữ hoa, thì tốt hơn nên phân tích cú pháp tài liệu dưới dạng XML.

UnicodeEncodeError

Hãy để chúng tôi xem xét phân đoạn mã bên dưới -

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

Đầu ra

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

Vấn đề trên có thể là do hai tình huống chính. Bạn có thể đang cố in ra một ký tự unicode mà bảng điều khiển của bạn không biết cách hiển thị. Thứ hai, bạn đang cố gắng ghi vào một tệp và bạn chuyển vào một ký tự Unicode không được mã hóa mặc định của bạn hỗ trợ.

Một cách để giải quyết vấn đề trên là mã hóa văn bản / ký tự phản hồi trước khi thực hiện món súp để có được kết quả mong muốn, như sau:

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

KeyError: [attr]

Nguyên nhân là do truy cập thẻ ['attr'] khi thẻ được đề cập không xác định thuộc tính attr. Các lỗi phổ biến nhất là: “KeyError: 'href'” và “KeyError: 'class'”. Sử dụng tag.get ('attr') nếu bạn không chắc chắn rằng attr được xác định.

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

Bạn có thể gặp lỗi AttributeError như sau:

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

Lỗi trên chủ yếu xảy ra vì bạn mong đợi find_all () trả về một thẻ hoặc chuỗi. Tuy nhiên, soup.find_all trả về một danh sách các phần tử trong python.

Tất cả những gì bạn cần làm là lặp lại danh sách và bắt dữ liệu từ các phần tử đó.