Hướng dẫn parse html python - phân tích cú pháp html python

Vietnamese (Tiếng Việt) translation by Dai Phong (you can also view the original English article) Dai Phong (you can also view the original English article)

Trong một bài viết trước, tôi đã hướng dẫn cho bạn cách sử dụng mô-đun Requests để truy cập các trang web bằng Python. Hướng dẫn đó đã đề cập đến rất nhiều chủ đề như tạo các yêu cầu GET/POST và tải về các nội dung như hình ảnh hoặc tập tin PDF bằng lập trình. Một điều còn thiếu trong hướng dẫn đó là về kỹ thuật scraping (trích xuất nội dung) trang web mà bạn đã truy cập bằng Requests để trích xuất thông tin mà bạn cần.

Trong hướng dẫn này, bạn sẽ được tìm hiểu về Beautiful Soup, một thư viện Python để trích xuất dữ liệu từ các tập tin HTML. Trọng tâm của hướng dẫn này là học các kiến ​​thức cơ bản của thư viện, và các chủ đề nâng cao sẽ được đề cập trong hướng dẫn tiếp theo. Xin lưu ý rằng hướng dẫn này sử dụng Beautiful Soup 4 cho tất cả các ví dụ.

Cài đặt

Bạn có thể cài đặt Beautiful Soup 4 bằng

$ python setup.py install
2. Tên gói là
$ python setup.py install
3. Nó sẽ làm việc trên cả Python 2 và Python 3.

$ pip install beautifulsoup4

Nếu bạn chưa cài đặt pip trên hệ thống của mình, bạn có thể trực tiếp tải về tarball nguồn của Beautiful Soup 4 và cài đặt nó bằng

$ python setup.py install
4.

$ python setup.py install

BeautifulSoup ban đầu được đóng gói như là code của Python 2. Khi bạn cài đặt nó để sử dụng với Python 3, nó sẽ tự động cập nhật sang code của Python 3. Code sẽ không được chuyển đổi trừ khi bạn cài đặt gói. Dưới đây là một số lỗi phổ biến mà bạn có thể bắt gặp:

  • $ python setup.py install
    5 "No module named HTMLParser" xảy ra khi bạn chạy phiên bản Python 2 của code Python 3.
  • $ python setup.py install
    5 "No module named html.parser" xảy ra khi bạn chạy phiên bản Python 3 của code Python 2.

Cả hai lỗi trên có thể được khắc phục bằng cách gỡ cài đặt và cài đặt lại Beautiful Soup.

Cài đặt Parser

Trước khi thảo luận về sự khác biệt giữa các parser khác nhau mà bạn có thể sử dụng cùng với Beautiful Soup, hãy viết code để tạo ra một soup.

from bs4 import BeautifulSoup

soup = BeautifulSoup("

This is invalid HTML

", "html.parser")

Đối tượng

$ python setup.py install
7 có thể nhận hai đối số. Đối số đầu tiên là markup thật sự, và đối số thứ hai là parser mà bạn muốn sử dụng. Các parser khác nhau là:
$ python setup.py install
8, lxml và html5lib.
$ python setup.py install
9 có hai phiên bản, một HTML parser và một XML parser.

$ python setup.py install
8 là một parser được tích hợp sẵn, và nó không hoạt động tốt trong các phiên bản cũ của Python. Bạn có thể cài đặt các parser khác bằng các lệnh sau:

$ pip install lxml
$ pip install html5lib

Parser

$ python setup.py install
9 rất nhanh và có thể được sử dụng để nhanh chóng phân tích HTML. Mặt khác, parser
from bs4 import BeautifulSoup

soup = BeautifulSoup("

This is invalid HTML

", "html.parser")
2 rất chậm, nhưng nó cũng cực kỳ dễ dùng. Dưới đây là một ví dụ về việc sử dụng từng parser này:

soup = BeautifulSoup("

This is invalid HTML

", "html.parser") print(soup) #

This is invalid HTML

soup = BeautifulSoup("

This is invalid HTML

", "lxml") print(soup) #

This is invalid HTML

soup = BeautifulSoup("

This is invalid HTML

", "xml") print(soup) # #

This is invalid HTML

soup = BeautifulSoup("

This is invalid HTML

", "html5lib") print(soup) #

This is invalid HTML

Những sự khác biệt được chỉ ra trong ví dụ trên chỉ có vấn đề khi bạn phân tích HTML không hợp lệ. Tuy nhiên, hầu hết HTML trên web không đúng định dạng, và nắm được những khác biệt này sẽ giúp bạn gỡ lỗi một số lỗi phân tích và quyết định parser nào bạn muốn sử dụng trong một dự án. Nói chung, parser

$ python setup.py install
9 là một lựa chọn rất tốt.

Các Đối tượng trong Beautiful Soup

Beautiful Soup phân tích tài liệu HTML đã cho thành một cây các đối tượng Python. Có bốn đối tượng Python chính mà bạn cần biết:

from bs4 import BeautifulSoup

soup = BeautifulSoup("

This is invalid HTML

", "html.parser")
4,
from bs4 import BeautifulSoup

soup = BeautifulSoup("

This is invalid HTML

", "html.parser")
5,
$ python setup.py install
7 và
from bs4 import BeautifulSoup

soup = BeautifulSoup("

This is invalid HTML

", "html.parser")
7.

Đối tượng

from bs4 import BeautifulSoup

soup = BeautifulSoup("

This is invalid HTML

", "html.parser")
4 chỉ về một thẻ XML hoặc HTML thật sự trong tài liệu. Bạn có thể truy cập vào tên của thẻ bằng
from bs4 import BeautifulSoup

soup = BeautifulSoup("

This is invalid HTML

", "html.parser")
9. Bạn cũng có thể đặt tên thành một cái gì đó khác. Thay đổi tên sẽ được hiển thị trong markup do Beautiful Soup tạo ra.

Bạn có thể truy cập các thuộc tính khác nhau như class và id của thẻ bằng

$ pip install lxml
$ pip install html5lib
0 và
$ pip install lxml
$ pip install html5lib
1 tương ứng. Bạn cũng có thể truy cập vào toàn bộ từ điển của các thuộc tính bằng
$ pip install lxml
$ pip install html5lib
2. Bạn cũng có thể thêm, xóa hoặc sửa đổi các thuộc tính của thẻ. Các thuộc tính như
$ pip install lxml
$ pip install html5lib
3 của một phần tử có thể lấy nhiều giá trị được lưu trữ dưới dạng một danh sách.

Văn bản bên trong một thẻ được lưu trữ như là một

from bs4 import BeautifulSoup

soup = BeautifulSoup("

This is invalid HTML

", "html.parser")
5 trong Beautiful Soup. Nó có một vài phương thức hữu ích như
$ pip install lxml
$ pip install html5lib
5 để thay thế văn bản trong một thẻ. Bạn cũng có thể chuyển đổi một
from bs4 import BeautifulSoup

soup = BeautifulSoup("

This is invalid HTML

", "html.parser")
5 thành unicode bằng cách sử dụng
$ pip install lxml
$ pip install html5lib
7.

Beautiful Soup cũng cho phép bạn truy cập các comment trong một trang web. Các comment này được lưu trữ dưới dạng một đối tượng

from bs4 import BeautifulSoup

soup = BeautifulSoup("

This is invalid HTML

", "html.parser")
7, về cơ bản cũng là
from bs4 import BeautifulSoup

soup = BeautifulSoup("

This is invalid HTML

", "html.parser")
5.

Bạn đã học về đối tượng

$ python setup.py install
7 trong phần trước. Nó được sử dụng để đại diện cho toàn bộ tài liệu. Vì nó không phải là một đối tượng thực tế, nên nó không có bất kỳ tên hoặc thuộc tính nào.

Lấy Tiêu đề, Heading và Liên kết

Bạn có thể trích xuất tiêu đề trang và dữ liệu khác rất dễ dàng bằng Beautiful Soup. Hãy trích xuất trang Wikipedia về Python. Trước tiên, bạn sẽ phải lấy cho được markup của trang web bằng cách sử dụng code sau đây dựa trên hướng dẫn về mô-đun Requests để truy xuất các trang web.

import requests
from bs4 import BeautifulSoup

req = requests.get('https://en.wikipedia.org/wiki/Python_(programming_language)')
soup = BeautifulSoup(req.text, "lxml")

Bây giờ bạn đã tạo ra soup, bạn có thể lấy tiêu đề của trang web bằng cách sử dụng code sau:

soup.title
# Python (programming language) - Wikipedia

soup.title.name
# 'title'

soup.title.string
# 'Python (programming language) - Wikipedia'

Bạn cũng có thể trích xuất các thông tin khác của trang web như heading hoặc đoạn văn đầu tiên, các lớp của chúng, hoặc thuộc tính

soup = BeautifulSoup("

This is invalid HTML

", "html.parser") print(soup) #

This is invalid HTML

soup = BeautifulSoup("

This is invalid HTML

", "lxml") print(soup) #

This is invalid HTML

soup = BeautifulSoup("

This is invalid HTML

", "xml") print(soup) # #

This is invalid HTML

soup = BeautifulSoup("

This is invalid HTML

", "html5lib") print(soup) #

This is invalid HTML

1.

soup.h2
# 

Python (programming language)

soup.h2.string # 'Python (programming language)' soup.h2['class'] # ['firstHeading'] soup.h2['id'] # 'firstHeading' soup.h2.attrs # {'class': ['firstHeading'], 'id': 'firstHeading', 'lang': 'en'} soup.h2['class'] = 'firstHeading, mainHeading' soup.h2.string.replace_with("Python - Programming Language") del soup.h2['lang'] del soup.h2['id'] soup.h2 #

Python - Programming Language

Tương tự, bạn có thể lặp qua tất cả các liên kết hoặc heading con trong một tài liệu bằng code sau:

for sub_heading in soup.find_all('h2'):
    print(sub_heading.text)
    
# all the sub-headings like Contents, History[edit]...

Điều hướng trên DOM

Bạn có thể điều hướng trên cây DOM bằng các tên thẻ thông thường. Việc móc nối các tên thẻ có thể giúp bạn điều hướng cây được sâu hơn. Ví dụ, bạn có thể lấy được liên kết đầu tiên trong đoạn đầu của trang Wikipedia cho trước bằng

soup = BeautifulSoup("

This is invalid HTML

", "html.parser") print(soup) #

This is invalid HTML

soup = BeautifulSoup("

This is invalid HTML

", "lxml") print(soup) #

This is invalid HTML

soup = BeautifulSoup("

This is invalid HTML

", "xml") print(soup) # #

This is invalid HTML

soup = BeautifulSoup("

This is invalid HTML

", "html5lib") print(soup) #

This is invalid HTML

2. Tất cả các liên kết trong đoạn văn đầu tiên có thể được truy cập bằng
soup = BeautifulSoup("

This is invalid HTML

", "html.parser") print(soup) #

This is invalid HTML

soup = BeautifulSoup("

This is invalid HTML

", "lxml") print(soup) #

This is invalid HTML

soup = BeautifulSoup("

This is invalid HTML

", "xml") print(soup) # #

This is invalid HTML

soup = BeautifulSoup("

This is invalid HTML

", "html5lib") print(soup) #

This is invalid HTML

3.

Bạn cũng có thể truy xuất tất cả các con của một thẻ thành một danh sách sử dụng

soup = BeautifulSoup("

This is invalid HTML

", "html.parser") print(soup) #

This is invalid HTML

soup = BeautifulSoup("

This is invalid HTML

", "lxml") print(soup) #

This is invalid HTML

soup = BeautifulSoup("

This is invalid HTML

", "xml") print(soup) # #

This is invalid HTML

soup = BeautifulSoup("

This is invalid HTML

", "html5lib") print(soup) #

This is invalid HTML

4. Để có được các con tại một chỉ mục cụ thể, bạn có thể sử dụng
soup = BeautifulSoup("

This is invalid HTML

", "html.parser") print(soup) #

This is invalid HTML

soup = BeautifulSoup("

This is invalid HTML

", "lxml") print(soup) #

This is invalid HTML

soup = BeautifulSoup("

This is invalid HTML

", "xml") print(soup) # #

This is invalid HTML

soup = BeautifulSoup("

This is invalid HTML

", "html5lib") print(soup) #

This is invalid HTML

5. Bạn cũng có thể lặp qua các con của một thẻ bằng thuộc tính
soup = BeautifulSoup("

This is invalid HTML

", "html.parser") print(soup) #

This is invalid HTML

soup = BeautifulSoup("

This is invalid HTML

", "lxml") print(soup) #

This is invalid HTML

soup = BeautifulSoup("

This is invalid HTML

", "xml") print(soup) # #

This is invalid HTML

soup = BeautifulSoup("

This is invalid HTML

", "html5lib") print(soup) #

This is invalid HTML

6.

Cả

soup = BeautifulSoup("

This is invalid HTML

", "html.parser") print(soup) #

This is invalid HTML

soup = BeautifulSoup("

This is invalid HTML

", "lxml") print(soup) #

This is invalid HTML

soup = BeautifulSoup("

This is invalid HTML

", "xml") print(soup) # #

This is invalid HTML

soup = BeautifulSoup("

This is invalid HTML

", "html5lib") print(soup) #

This is invalid HTML

6 và
soup = BeautifulSoup("

This is invalid HTML

", "html.parser") print(soup) #

This is invalid HTML

soup = BeautifulSoup("

This is invalid HTML

", "lxml") print(soup) #

This is invalid HTML

soup = BeautifulSoup("

This is invalid HTML

", "xml") print(soup) # #

This is invalid HTML

soup = BeautifulSoup("

This is invalid HTML

", "html5lib") print(soup) #

This is invalid HTML

8 chỉ hữu ích khi bạn muốn truy cập con trực tiếp hoặc cấp đầu tiên của một thẻ. Để có được tất cả các con, bạn có thể sử dụng thuộc tính
soup = BeautifulSoup("

This is invalid HTML

", "html.parser") print(soup) #

This is invalid HTML

soup = BeautifulSoup("

This is invalid HTML

", "lxml") print(soup) #

This is invalid HTML

soup = BeautifulSoup("

This is invalid HTML

", "xml") print(soup) # #

This is invalid HTML

soup = BeautifulSoup("

This is invalid HTML

", "html5lib") print(soup) #

This is invalid HTML

9.

print(soup.p.contents)
# [Python, ' is a widely used ',.....the full list]

print(soup.p.contents[10])
# readability

for child in soup.p.children:
    print(child.name)
# b
# None
# a
# None
# a
# None
# ... and so on.

Bạn cũng có thể truy cập vào phần tử cha của một phần tử bằng thuộc tính

import requests
from bs4 import BeautifulSoup

req = requests.get('https://en.wikipedia.org/wiki/Python_(programming_language)')
soup = BeautifulSoup(req.text, "lxml")
0. Tương tự, bạn có thể truy cập vào tất cả các phần tử cha của một phần tử bằng cách sử dụng thuộc tính
import requests
from bs4 import BeautifulSoup

req = requests.get('https://en.wikipedia.org/wiki/Python_(programming_language)')
soup = BeautifulSoup(req.text, "lxml")
1. Phần tử cha của thẻ cấp cao nhất
import requests
from bs4 import BeautifulSoup

req = requests.get('https://en.wikipedia.org/wiki/Python_(programming_language)')
soup = BeautifulSoup(req.text, "lxml")
2 chính là đối tượng
$ python setup.py install
7, và cha của nó là None.

$ python setup.py install
0

Bạn có thể truy cập phần tử anh chị em trước và sau của một phần tử bằng các thuộc tính

import requests
from bs4 import BeautifulSoup

req = requests.get('https://en.wikipedia.org/wiki/Python_(programming_language)')
soup = BeautifulSoup(req.text, "lxml")
4 và
import requests
from bs4 import BeautifulSoup

req = requests.get('https://en.wikipedia.org/wiki/Python_(programming_language)')
soup = BeautifulSoup(req.text, "lxml")
5.

Đối với hai phần tử để được là anh chị em, chúng cần phải có cùng một phần tử cha. Điều này có nghĩa là con đầu tiên của một phần tử sẽ không có anh chị em trước. Tương tự, phần tử con cuối cùng của một phần tử sẽ không có anh chị em kế tiếp. Trong các trang web thật sự, các anh chị em trước và tiếp theo của một phần tử có lẽ sẽ là một ký tự xuống dòng.

Bạn cũng có thể lặp qua tất cả các anh chị em của một phần tử bằng

import requests
from bs4 import BeautifulSoup

req = requests.get('https://en.wikipedia.org/wiki/Python_(programming_language)')
soup = BeautifulSoup(req.text, "lxml")
6 và
import requests
from bs4 import BeautifulSoup

req = requests.get('https://en.wikipedia.org/wiki/Python_(programming_language)')
soup = BeautifulSoup(req.text, "lxml")
7.

$ python setup.py install
1

Bạn có thể tìm thấy phần tử ngay sau phần tử hiện tại bằng thuộc tính

import requests
from bs4 import BeautifulSoup

req = requests.get('https://en.wikipedia.org/wiki/Python_(programming_language)')
soup = BeautifulSoup(req.text, "lxml")
8. Để truy cập vào phần tử xuất hiện ngay trước phần tử hiện tại, sử dụng thuộc tính
import requests
from bs4 import BeautifulSoup

req = requests.get('https://en.wikipedia.org/wiki/Python_(programming_language)')
soup = BeautifulSoup(req.text, "lxml")
9.

Tương tự, bạn có thể lặp qua tất cả các phần tử trước và sau phần tử hiện tại bằng cách sử dụng

soup.title
# Python (programming language) - Wikipedia

soup.title.name
# 'title'

soup.title.string
# 'Python (programming language) - Wikipedia'
0 và
soup.title
# Python (programming language) - Wikipedia

soup.title.name
# 'title'

soup.title.string
# 'Python (programming language) - Wikipedia'
1 tương ứng.

Tóm tắt

Sau khi đọc xong hướng dẫn này, bạn đã hiểu rõ hơn về sự khác biệt chính giữa các parser HTML khác nhau. Bây giờ bạn còn có thể điều hướng trên một trang web và trích xuất các dữ liệu quan trọng. Điều này có thể hữu ích khi bạn muốn phân tích tất cả các đề mục hoặc liên kết trên một trang web nhất định.

Trong phần tiếp theo của loạt bài này, bạn sẽ được học cách sử dụng thư viện Beautiful Soup để tìm kiếm và sửa đổi DOM.