Bộ chọn HTML là chìa khóa để thu thập dữ liệu web, cho phép các nhà phát triển nhắm mục tiêu vào các thành phần cụ thể trên trang web. Bằng cách sử dụng các bộ chọn này, các nhà phát triển có thể trích xuất dữ liệu chính xác.
Web scraping liên quan đến việc lấy dữ liệu từ các trang web bằng cách điều hướng cấu trúc HTML của chúng. Bộ chọn HTML rất quan trọng, cho phép bạn xác định chính xác các thẻ, thuộc tính hoặc nội dung cụ thể. Cho dù trích xuất giá sản phẩm hay tiêu đề, bộ chọn chính là hướng dẫn của bạn.
Sử dụng bộ chọn HTML giúp hợp lý hóa việc trích xuất dữ liệu và giảm lỗi. Chúng giúp bạn tập trung vào các yếu tố quan trọng, tiết kiệm thời gian và công sức trong việc thu thập thông tin chi tiết từ các nguồn trực tuyến.
Trong blog này, chúng ta sẽ khám phá cách sử dụng các bộ chọn bên dưới với Python và thư viện " Beautifulsoup ":
Trong HTML, ID là các mã định danh duy nhất được gán cho các phần tử cụ thể, đảm bảo không có hai phần tử nào có cùng ID. Tính duy nhất này làm cho bộ chọn ID trở nên lý tưởng để nhắm mục tiêu đến các phần tử riêng lẻ trên một trang web. Ví dụ, nếu bạn đang thu thập dữ liệu từ một trang web có nhiều phần, mỗi phần có thể có ID riêng, cho phép bạn trích xuất dữ liệu từ một phần cụ thể mà không bị can thiệp.
Chúng ta hãy lấy ví dụ trang web này, đặc biệt là phần tử bên dưới <div id="pages"> ...</div>
Phần tử này chứa các phần tử HTML lồng nhau khác nhưng điều quan trọng nhất là phần tử này là duy nhất trên trang web này và chúng ta có thể tận dụng kịch bản này chẳng hạn khi chúng ta muốn trích xuất các phần cụ thể của trang web. Trong trường hợp này, phần tử này bao gồm một số bài viết khác mà chúng ta sẽ giải thích bằng các bộ chọn khác bên dưới. Sau đây là cách phần này trên trang trông như thế nào:
Hãy cùng khám phá một ví dụ đơn giản sử dụng thư viện "requests" và "bs4" của Python:
import requests
from bs4 import BeautifulSoup
# Step 1: Send a GET request to the website
url = "https://www.scrapethissite.com/pages/"
response = requests.get(url)
if response.status_code == 200:
# Step 2: Parse the HTML content with BeautifulSoup
soup = BeautifulSoup(response.text, 'html.parser')
# Step 3: Find the div with id="pages"
pages_div = soup.find("div", id="pages")
# Step 4: Display the content or handle it as needed
if pages_div:
print("Content of the div with id='pages':")
print(pages_div.text.strip())
else:
print("No div with id='pages' found.")
else:
print(f"Failed to retrieve the webpage. Status code: {response.status_code}")
Giải thích:
soup.find("div", id="trang")
để xác định vị trí <div>
phần tử với id="trang"
. <div>
được tìm thấy, chúng tôi sẽ in nội dung của nó. Nếu không, một thông báo sẽ cho biết nó bị thiếu.Bộ chọn ID rất mạnh nhưng có những hạn chế. ID động thay đổi theo từng lần tải trang có thể khiến việc trích xuất dữ liệu nhất quán trở nên khó khăn. Trong những tình huống này, việc sử dụng bộ chọn thay thế có thể cần thiết để có kết quả đáng tin cậy.
Bộ chọn lớp linh hoạt vì chúng cho phép bạn nhắm mục tiêu vào các nhóm phần tử có cùng lớp. Điều này làm cho chúng trở nên cần thiết cho các trang web có các phần tử lặp lại. Ví dụ, một trang web hiển thị danh sách sản phẩm có thể chỉ định cùng một lớp cho từng mục sản phẩm.
Chúng ta hãy lấy một ví dụ nữa bằng cách sử dụng trang web này. Phía trên chúng tôi đã xác định một <div id="pages">
phần tử sử dụng ID Selector và trong các phần tử div này có một số bài viết có cùng lớp.
Như bạn có thể thấy chúng ta có bốn phần tử có cùng lớp <div class="page">
Dưới đây là hình ảnh của chúng trên trang web:
Trong đoạn mã dưới đây, chúng ta sẽ chọn tất cả các phần tử có lớp "page", điều này sẽ trả về một danh sách có thể được sử dụng để phân tích cú pháp thêm.
import requests
from bs4 import BeautifulSoup
# Step 1: Send a GET request to the website
url = "https://www.scrapethissite.com/pages/"
response = requests.get(url)
if response.status_code == 200:
# Step 2: Parse the HTML content with BeautifulSoup
soup = BeautifulSoup(response.text, 'html.parser')
# Step 3: Find all elements with class="page"
page_elements = soup.find_all("div", class_="page")
# Step 4: Save each element's text content in a list
pages_list = [page.text.strip() for page in page_elements]
print("Content of elements with class 'page':")
for i, page in enumerate(pages_list, start=1):
print(f"Page {i}:")
print(page)
print("-" * 20)
else:
print(f"Failed to retrieve the webpage. Status code: {response.status_code}")
Giải thích:
soup.find_all("div", class_="trang")
để xác định vị trí tất cả <div>
các phần tử có lớp "trang", trả về chúng dưới dạng một danh sách. Khi sử dụng bộ chọn lớp, hãy lưu ý đến các vấn đề tiềm ẩn như chọn các phần tử không mong muốn. Nhiều lớp trên một phần tử duy nhất có thể yêu cầu lọc bổ sung để đạt được mục tiêu chính xác.
Bộ chọn thuộc tính cho phép bạn nhắm mục tiêu các phần tử dựa trên sự hiện diện, giá trị hoặc giá trị một phần của các thuộc tính cụ thể trong thẻ HTML. Điều này đặc biệt hữu ích khi các lớp hoặc ID không duy nhất hoặc khi bạn cần lọc các phần tử có thuộc tính động, chẳng hạn như dữ liệu-*
hoặc href
giá trị trong liên kết.
Trong ví dụ sau, chúng ta sẽ chọn tất cả hình ảnh trên trang web và trích xuất URL nguồn của chúng hoặc nguồn
thuộc tính. Đây là cách phần tử trông như thế nào trong cấu trúc html và chế độ xem trang web:
Trong đoạn mã sau, chúng tôi sử dụng BeautifulSoup để phân tích tất cả <img> các yếu tố, trích xuất của họ nguồn
thuộc tính và lưu trữ chúng trong một danh sách.
import requests
from bs4 import BeautifulSoup
# Step 1: Send a GET request to the website
url = "https://www.scrapethissite.com/pages/frames/"
response = requests.get(url)
if response.status_code == 200:
# Step 2: Parse the HTML content with BeautifulSoup
soup = BeautifulSoup(response.text, 'html.parser')
# Step 3: Find all <img> elements with a 'src' attribute
image_elements = soup.find_all("img", src=True)
# Step 4: Save the 'src' attributes in a list
images_list = [img['src'] for img in image_elements]
print("Image sources found on the page:")
for i, src in enumerate(images_list, start=1):
print(f"Image {i}: {src}")
else:
print(f"Failed to retrieve the webpage. Status code: {response.status_code}")
Bộ chọn thuộc tính chỉ có thể chọn các phần tử có thuộc tính tĩnh, khiến chúng kém hiệu quả hơn đối với nội dung động, như các phần tử được tải qua JavaScript. Chúng phụ thuộc vào các cấu trúc HTML ổn định, do đó việc thay đổi bố cục trang web thường xuyên có thể làm gián đoạn chúng. Ngoài ra, chúng không thể quản lý bộ lọc phức tạp hoặc nhiều điều kiện, điều này hạn chế độ chính xác của chúng. Chúng cũng có thể chọn các phần tử không mong muốn nếu các thuộc tính như lớp hoặc tên được chia sẻ bởi nhiều phần tử.
Bộ chọn phân cấp cho phép bạn nhắm mục tiêu các phần tử HTML dựa trên vị trí và mối quan hệ của chúng với các phần tử khác trong cấu trúc HTML. Cách tiếp cận này đặc biệt hữu ích khi làm việc với các bảng hoặc danh sách lồng nhau, trong đó dữ liệu được tổ chức theo định dạng cha-con.
Trong ví dụ này, chúng tôi đang sử dụng bộ chọn phân cấp để thu thập dữ liệu từ bảng thống kê đội khúc côn cầu được tìm thấy trên trang web này.
Bảng chứa các hàng <tr>
đại diện cho mỗi đội và mỗi hàng chứa các ô <td>
với thông tin như tên đội, năm, chiến thắng và thua cuộc. Mỗi hàng có lớp="đội"
, xác định nó là một mục nhập có liên quan trong dữ liệu của chúng tôi. Bằng cách điều hướng từ <table>
to each <tr> and then to each <td>
, chúng ta có thể thu thập dữ liệu một cách hiệu quả theo cách có cấu trúc.
Bên dưới, bạn sẽ thấy hai hình ảnh giúp bạn hình dung vị trí của bảng này trong cấu trúc HTML và cách nó xuất hiện trên trang web thực tế.
Bây giờ, chúng ta hãy xem đoạn mã bên dưới để biết cách sử dụng bộ chọn phân cấp để trích xuất dữ liệu này:
import requests
from bs4 import BeautifulSoup
url = "https://www.scrapethissite.com/pages/forms/"
# Step 1: Send a GET request to the website
response = requests.get(url)
if response.status_code == 200:
# Step 2: Parse the HTML content with BeautifulSoup
soup = BeautifulSoup(response.text, 'html.parser')
# Step 3: Find all rows in the table with class="team"
teams_data = []
team_rows = soup.find_all("tr", class_="team")
# Step 4: Extract and store each team's data
for row in team_rows:
team = {
"name": row.find("td", class_="name").text.strip(),
"year": row.find("td", class_="year").text.strip(),
"wins": row.find("td", class_="wins").text.strip(),
"losses": row.find("td", class_="losses").text.strip(),
"ot_losses": row.find("td", class_="ot-losses").text.strip(),
"win_pct": row.find("td", class_="pct").text.strip(),
"goals_for": row.find("td", class_="gf").text.strip(),
"goals_against": row.find("td", class_="ga").text.strip(),
"goal_diff": row.find("td", class_="diff").text.strip(),
}
teams_data.append(team)
# Step 5: Display the extracted data
for team in teams_data:
print(team)
else:
print(f"Failed to retrieve the webpage. Status code: {response.status_code}")
Bộ chọn phân cấp phụ thuộc vào cấu trúc HTML, do đó, những thay đổi trong bố cục có thể dễ dàng phá vỡ tập lệnh thu thập dữ liệu. Chúng cũng bị giới hạn ở nội dung tĩnh và không thể truy cập các phần tử được JavaScript tải động. Các bộ chọn này thường yêu cầu điều hướng chính xác qua các mối quan hệ cha-con, điều này có thể gây khó khăn trong các cấu trúc lồng nhau sâu. Ngoài ra, chúng có thể không hiệu quả khi trích xuất dữ liệu phân tán, vì chúng phải đi qua nhiều cấp để tiếp cận các phần tử cụ thể.
Mỗi loại bộ chọn phục vụ một mục đích riêng và việc kết hợp chúng cho phép chúng ta điều hướng và nắm bắt dữ liệu chính xác từ nội dung lồng nhau hoặc có cấu trúc. Ví dụ, sử dụng bộ chọn ID có thể giúp định vị vùng nội dung chính, bộ chọn lớp có thể cô lập các phần tử lặp lại, bộ chọn thuộc tính có thể trích xuất các liên kết hoặc hình ảnh cụ thể và bộ chọn phân cấp có thể tiếp cận các phần tử lồng nhau trong các phần cụ thể. Cùng nhau, các kỹ thuật này cung cấp một phương pháp tiếp cận mạnh mẽ để thu thập dữ liệu có cấu trúc.
import requests
from bs4 import BeautifulSoup
# Target URL
url = "https://www.scrapethissite.com/pages/"
response = requests.get(url)
if response.status_code == 200:
# Step 2: Parse the HTML content with BeautifulSoup
soup = BeautifulSoup(response.text, 'html.parser')
# Use ID selector to find the main content
main_content = soup.find(id="pages")
# Use class selector to find each "page" section
pages = main_content.find_all("div", class_="page") if main_content else []
# Extract details from each "page" section using hierarchical selectors
for page in pages:
# Use hierarchical selector to find title link and URL within each "page"
title_tag = page.find("h3", class_="page-title")
title = title_tag.text.strip() if title_tag else "No Title"
link = title_tag.find("a")["href"] if title_tag and title_tag.find("a") else "No Link"
# Use class selector to find the description
description = page.find("p", class_="lead session-desc").text.strip() if page.find("p", class_="lead session-desc") else "No Description"
print(f"Title: {title}")
print(f"Link: {link}")
print(f"Description: {description}")
print("-" * 40)
else:
print(f"Failed to retrieve the webpage. Status code: {response.status_code}")
lớp="trang"
để tìm từng khối nội dung riêng lẻ đại diện cho một phần quan tâm. trang.tìm("h3", class_="tiêu-đề-trang")
để tìm tiêu đề. thẻ tiêu đề.tìm("a")["href"]
để lấy URL liên kết từ thẻ neo trong tiêu đề. Trong việc trích xuất dữ liệu web, biết cách sử dụng bộ chọn HTML có thể cải thiện đáng kể kỹ năng trích xuất dữ liệu của bạn, cho phép bạn thu thập thông tin quan trọng một cách chính xác. Các bộ chọn như ID, lớp, thuộc tính và bộ chọn phân cấp đều có công dụng cụ thể cho các tác vụ trích xuất khác nhau. Bằng cách sử dụng các công cụ này cùng nhau, bạn có thể tự tin xử lý nhiều thách thức trích xuất dữ liệu web.
Để thực hành, các trang web như Scrape This Site và Books to Scrape cung cấp các ví dụ tuyệt vời giúp bạn cải thiện kỹ năng của mình. Và nếu bạn cần bất kỳ trợ giúp nào hoặc muốn kết nối với những người khác quan tâm đến việc thu thập dữ liệu web, hãy thoải mái tham gia kênh Discord của chúng tôi tại https://discord.com/invite/scrape .
Chúc bạn cạo vui vẻ!