Cách thu thập dữ liệu từ kho lưu trữ công khai GitHub bằng Python?

Bình luận: 0

Trong bài viết này, chúng ta sẽ phân tích cách thu thập dữ liệu từ các kho lưu trữ GitHub bằng Python. Chúng ta sẽ xem xét các thư viện phổ biến như BeautifulSoup và Requests và giải thích chi tiết trong quá trình xây dựng một script thu thập dữ liệu từ GitHub để bạn có thể dễ dàng làm theo.

Tại sao nên thu thập dữ liệu từ kho lưu trữ GitHub?

Thu thập dữ liệu GitHub là gì và nhằm mục đích gì? Có nhiều mục đích sử dụng nó, nhưng phổ biến nhất bao gồm:

  • Theo dõi sự phát triển công nghệ. Theo dõi số sao và kho lưu trữ là một cách tuyệt vời để nắm bắt xu hướng của các ngôn ngữ lập trình, framework và thư viện. Thông tin này rất quan trọng trong việc ra quyết định liên quan đến việc triển khai công nghệ, phát triển kỹ năng hoặc phân bổ tài nguyên.
  • Tận dụng kho mã lập trình. Trên GitHub có vô số dự án mã nguồn mở, ví dụ và giải pháp. Do đó, một lượng lớn kiến thức và kỹ thuật lập trình hữu ích cho mục đích học tập, cải thiện kỹ năng lập trình và hiểu cách triển khai công nghệ đều có sẵn trên nền tảng này.

GitHub không chỉ cung cấp dịch vụ lưu trữ kho mã mà còn có cơ sở người dùng rất lớn, cùng với danh tiếng tốt khiến nó trở thành một lựa chọn đáng tin cậy.

Thông tin được lưu trữ trên GitHub rất hữu ích trong việc theo dõi xu hướng phát triển công nghệ cũng như cải thiện quy trình phát triển phần mềm. Đây là thông tin quan trọng để bắt kịp các đối thủ trong lĩnh vực công nghệ thông tin.

Các thư viện và công cụ cần thiết để thu thập dữ liệu từ GitHub

Khi nói đến việc thu thập dữ liệu từ một trang web, ngôn ngữ dễ sử dụng nhất là Python vì nó có rất nhiều thư viện và mô-đun. Để thu thập dữ liệu từ GitHub bằng Python, bạn cần thêm các mô-đun sau:

  • requests: thư viện client dùng để gửi và nhận các yêu cầu HTTP, và cũng là thư viện được sử dụng nhiều nhất.
  • BeautifulSoup: mạnh mẽ trong việc trích xuất thông tin từ HTML, hỗ trợ nhiều tính năng nâng cao trong việc duyệt và truy xuất dữ liệu.
  • Selenium: khởi chạy một trình duyệt thực tế và cho phép tương tác như nhấp chuột và nhập liệu vào các phần tử trên trang.

Việc này có thể thực hiện rất dễ dàng bằng cách sử dụng các công cụ thu thập dữ liệu từ GitHub. Tuy nhiên, chúng ta hãy đi sâu vào cách thực hiện cụ thể.

Xây dựng script thu thập dữ liệu từ kho GitHub bằng Beautiful Soup

Phần này sẽ hướng dẫn cách thu thập dữ liệu từ các kho GitHub. Các bước quan trọng để tạo trình thu thập bao gồm:

  1. Tạo nền tảng ban đầu – bao gồm việc cài đặt Python và các thư viện liên quan.
  2. Lưu mã HTML của trang GitHub.
  3. Phân tích bố cục của trang để xác định các thành phần cần thiết.
  4. Thu thập thông tin như tên tài khoản, mô tả, số lượng sao và các dữ liệu khác.
  5. Lưu trữ dữ liệu vào hệ thống tệp.

Từ đây, chúng tôi sẽ chia sẻ chi tiết cho tất cả các bước trên cùng với một script hoàn chỉnh để thu thập dữ liệu từ GitHub.

Bước 1: Thiết lập môi trường dự án Python của bạn

Đảm bảo rằng bạn đã cài đặt Python trên máy tính của mình. Tiếp theo, hãy tạo một môi trường ảo Python mới để bắt đầu quá trình thu thập dữ liệu từ GitHub.


python -m venv github_scraper
source github_scraper/bin/activate  # Cho macOS và Linux
github_scraper\Scripts\activate     # Cho Windows

Bước 2: Cài đặt các thư viện Python cần thiết

Như đã đề cập trước đó, BeautifulSoup và Requests sẽ hỗ trợ bạn trong việc thu thập dữ liệu từ các kho GitHub. Trong môi trường ảo hiện đang được kích hoạt, hãy chạy lệnh sau để thêm chúng vào các thư viện phụ thuộc của dự án:


pip install beautifulsoup4 requests

Bước 3: Truy cập và tải trang GitHub mục tiêu

Chọn bất kỳ kho lưu trữ nào mà bạn muốn thu thập dữ liệu từ GitHub. Trước tiên, hãy khai báo liên kết trong một biến, sau đó gửi yêu cầu HTTP để lấy mã của trang.


url = "https://github.com/TheKevJames/coveralls-python"
response = requests.get(url)

Bước 4: Hiểu và phân tích cấu trúc HTML

Để phân tích HTML của bạn, hãy đưa nó vào trong BeautifulSoup.


soup = BeautifulSoup(page.text, 'html.parser')

Hàm khởi tạo BeautifulSoup() cần được cung cấp hai tham số.

  1. Một chuỗi chứa nội dung HTML, được lưu trong biến page.text.
  2. Bộ phân tích cú pháp (parser) mà Beautiful Soup sẽ sử dụng: “html.parser” là tên của trình phân tích HTML tích hợp sẵn trong Python.

HTML sẽ được phân tích bởi BeautifulSoup và một cấu trúc dạng cây sẽ được tạo ra. Cụ thể hơn, biến soup chứa tất cả các phương thức cần thiết để chọn các phần tử liên quan từ cây DOM, chẳng hạn như:

  • find(): trả về phần tử HTML đầu tiên tương ứng với chiến lược chọn đã cung cấp.
  • find_all(): trả về danh sách các phần tử HTML khớp với chiến lược chọn đầu vào.
  • select_one(): trả về phần tử HTML đầu tiên khớp với bộ chọn CSS đầu vào.
  • select(): trả về danh sách các phần tử HTML khớp với bộ chọn CSS đã chỉ định.

Bước 5: Phân tích trang mục tiêu để lấy dữ liệu liên quan

Đây là một bước quan trọng khác: chọn các phần tử HTML đơn giản và thu thập dữ liệu từ GitHub thông qua chúng. Bước này thực hiện trước khi bạn viết script Python cho kho lưu trữ GitHub.

Trước khi thu thập dữ liệu từ GitHub, bạn nên làm quen với chính trang web đó. Sau đó, mở công cụ dành cho nhà phát triển bằng cách nhấn phím F12. Khi bạn đã mở mã nguồn, bạn sẽ thấy rằng nhiều phần tử trên trang không có các lớp hoặc thuộc tính riêng biệt, điều này gây khó khăn cho việc điều hướng đến phần tử cần thiết. Hãy xem kỹ toàn bộ trang và chuẩn bị trích xuất dữ liệu.

Bước 6: Trích xuất thông tin kho lưu trữ

Bây giờ chúng ta đã sẵn sàng để tạo một script Python giúp thu thập dữ liệu từ các kho GitHub. Script này có thể trích xuất các thông tin hữu ích được lưu trên GitHub như số sao (stars), mô tả, lần commit cuối cùng, v.v. Để thực hiện điều này, chúng ta cần xác định các thuộc tính cần thiết và truy xuất các giá trị văn bản tương ứng.

  • Tên kho lưu trữ:
    
    repo_title = soup.select_one('[itemprop="name"]').text.strip()
    

    Thuộc tính itemprop="name" có một giá trị duy nhất, vì vậy chúng ta sẽ lấy nó ra. Các trường văn bản trên GitHub thường có khoảng trắng và ký tự xuống dòng, có thể được làm sạch bằng cách sử dụng hàm strip().

  • Nhánh hiện tại:
    
    git_branch_icon_html_element = soup.select_one('[class="Box-sc-g0xbh4-0 ffLUq ref-selector-button-text-container"]').text.split()
    

    Hãy lưu ý rằng không có cách đơn giản nào hơn để chọn thành phần HTML chứa tiêu đề của nhánh chính. Vậy bạn nên làm gì? Hãy chọn một lớp (class) duy nhất và lấy nội dung văn bản từ đó.

  • Lần commit cuối:
    
    relative_time_html_element = soup.select_one('relative-time')
    latest_commit = relative_time_html_element['datetime']
    

    Chúng tôi đã nhận thấy rằng thẻ relative-time, nơi lưu trữ lần commit cuối cùng của người dùng, đã được chọn từ trước, và ngày tháng được lấy thông qua thuộc tính datetime.

Thu thập các thông tin nằm ở phía bên trái: mô tả, số sao, lượt xem, số lần fork.

  • Mô tả:
    
    bordergrid_html_element = soup.select_one('.BorderGrid')
    about_html_element = bordergrid_html_element.select_one('h2')
    description_html_element = about_html_element.find_next_sibling('p')
    description = description_html_element.get_text().strip()
    
  • Số sao:
    
    star_icon_html_element = bordergrid_html_element.select_one('.octicon-star')
    stars_html_element = star_icon_html_element.find_next_sibling('strong')
    stars = stars_html_element.get_text().strip().replace(',', '')
    
  • Lượt xem:
    
    eye_icon_html_element = bordergrid_html_element.select_one('.octicon-eye')
    watchers_html_element = eye_icon_html_element.find_next_sibling('strong')
    watchers = watchers_html_element.get_text().strip().replace(',', '')
    
  • Số lần fork:
    
    fork_icon_html_element = bordergrid_html_element.select_one('.octicon-repo-forked')
    forks_html_element = fork_icon_html_element.find_next_sibling('strong')
    forks = forks_html_element.get_text().strip().replace(',', '')
    

Bước 7: Thu thập và phân tích các tệp Readme

Tệp readme rất quan trọng. Nó cung cấp mô tả về kho lưu trữ và hướng dẫn cách triển khai mã nguồn. Nếu bạn kiểm tra tệp readme.md, bạn sẽ thấy liên kết của nó như sau:


https://raw.githubusercontent.com///readme.md

Vì chúng ta đã có thông tin này, nên có thể tạo URL một cách lập trình bằng cách dùng f-string, sau đó gửi yêu cầu HTTP để lấy mã của tệp.


readme_url = f'https://github.com/TheKevJames/coveralls-python/blob/{main_branch}/readme.rst'
readme_page = requests.get(readme_url)

readme = None
if readme_page.status_code != 404:
    readme = readme_page.text

Đừng quên kiểm tra lỗi 404 để tránh lưu nội dung từ trang lỗi GitHub nếu kho lưu trữ không có tệp readme.

Bước 8: Tổ chức và lưu trữ dữ liệu đã thu thập một cách hiệu quả

Tất cả thông tin sẽ được lưu trong một từ điển (dictionary) duy nhất để có thể dễ dàng ghi chúng vào tệp JSON.


repo = {}
repo['name'] = repo_title
repo['latest_commit'] = latest_commit
repo['main_branch'] = main_branch
repo['description'] = description
repo['stars'] = stars
repo['watchers'] = watchers
repo['forks'] = forks
repo['readme'] = readme

Bước 9: Xuất dữ liệu đã thu thập sang định dạng JSON

Chúng ta sẽ tận dụng thư viện tích hợp sẵn của Python để phân tích dữ liệu và lưu nó dưới định dạng JSON, rất phù hợp với các cấu trúc lồng nhau như trường hợp của chúng ta với các danh sách bài viết.


with open('github_data.json', 'w', encoding='utf-8') as json_file:
  json.dump(repo, json_file, ensure_ascii=False, indent=4)

Bước 10: Tích hợp tất cả các bước vào một script hoàn chỉnh


import json
import requests
from bs4 import BeautifulSoup

url = "https://github.com/TheKevJames/coveralls-python"
response = requests.get(url)
soup = BeautifulSoup(response.text, "lxml")

repo_title = soup.select_one('[itemprop="name"]').text.strip()

# chi nhánh
main_branch = soup.select_one(
   '[class="Box-sc-g0xbh4-0 ffLUq ref-selector-button-text-container"]').text.split()

# cam kết mới nhất
relative_time_html_element = soup.select_one('relative-time')
latest_commit = relative_time_html_element['datetime']

# sự miêu tả
bordergrid_html_element = soup.select_one('.BorderGrid')
about_html_element = bordergrid_html_element.select_one('h2')
description_html_element = about_html_element.find_next_sibling('p')
description = description_html_element.get_text().strip()

# sao
star_icon_html_element = bordergrid_html_element.select_one('.octicon-star')
stars_html_element = star_icon_html_element.find_next_sibling('strong')
stars = stars_html_element.get_text().strip().replace(',', '')

# người theo dõi
eye_icon_html_element = bordergrid_html_element.select_one('.octicon-eye')
watchers_html_element = eye_icon_html_element.find_next_sibling('strong')
watchers = watchers_html_element.get_text().strip().replace(',', '')

# phuộc
fork_icon_html_element = bordergrid_html_element.select_one('.octicon-repo-forked')
forks_html_element = fork_icon_html_element.find_next_sibling('strong')
forks = forks_html_element.get_text().strip().replace(',', '')

# readme
readme_url = f'https://github.com/TheKevJames/coveralls-python/blob/{main_branch}/readme.rst'
readme_page = requests.get(readme_url)

readme = None
if readme_page.status_code != 404:
   readme = readme_page.text

repo = {}
repo['name'] = repo_title
repo['latest_commit'] = latest_commit
repo['main_branch'] = main_branch
repo['description'] = description
repo['stars'] = stars
repo['watchers'] = watchers
repo['forks'] = forks
repo['readme'] = readme

with open('github_data.json', 'w', encoding='utf-8') as json_file:
   json.dump(repo, json_file, ensure_ascii=False, indent=4)

Thu thập dữ liệu từ GitHub: Kết luận

Chúng ta đã tìm hiểu quá trình xây dựng một script thu thập dữ liệu từ GitHub cho các kho lưu trữ bằng cách sử dụng BeautifulSoup và Requests. Giờ đây, bạn đã biết cách truy cập các trang web, trích xuất dữ liệu liên quan và xử lý chúng theo cách thân thiện với người dùng. Những kỹ năng này rất hữu ích trong việc phân tích các dự án nổi tiếng, theo dõi thay đổi trong mã nguồn hoặc tạo báo cáo.

Tuy nhiên, hãy sử dụng một cách hợp lý. Phần lớn thời gian, GitHub đã cung cấp một API giúp làm việc dễ dàng và hiệu quả hơn. Nếu bạn quyết định sử dụng web scraping, hãy đảm bảo tuân thủ các nguyên tắc của trang web và đừng gửi quá nhiều yêu cầu tới máy chủ cùng lúc.

Bình luận:

0 Bình luận