Cách Trích Xuất Dữ Liệu YouTube Quan Trọng Bằng Python

19 tháng 8 2024
9 phút đọc
Tóm tắt được tạo bởi AI:

Các nhà sáng tạo nội dung YouTube cần phân tích hiệu suất của từng video, bao gồm việc phân tích cả bình luận và nội dung của chính họ so với các video khác trong cùng hoặc khác danh mục.

Xem qua tất cả video một cách thủ công có thể rất mệt mỏi và khó khăn. Trong trường hợp này, một đoạn mã tự động sẽ rất hữu ích. Trong hướng dẫn này, chúng tôi sẽ chỉ cho bạn cách trích xuất dữ liệu từ YouTube và tạo một đoạn mã nhằm tự động hóa quá trình thu thập dữ liệu thường được thực hiện thủ công.

Hiểu Cấu Trúc Dữ Liệu Để Trích Xuất YouTube Bằng Python

Trước khi học cách trích xuất dữ liệu từ YouTube, chúng ta cần hiểu cấu trúc của nền tảng này. YouTube có rất nhiều tính năng với vô số kiểu dữ liệu liên quan đến hoạt động người dùng và thống kê video. Một số tham số quan trọng từ nền tảng bao gồm tiêu đề và mô tả video, các thẻ được thêm vào, lượt xem, lượt thích và bình luận, cũng như thông tin về kênh và danh sách phát. Những yếu tố này rất quan trọng đối với các nhà tiếp thị nội dung và nhà sáng tạo để đánh giá hiệu suất video và xây dựng chiến lược nội dung hiệu quả.

Với YouTube Data API, các lập trình viên có thể truy cập hầu hết các chỉ số một cách lập trình. API cũng cho phép truy cập số lượng người đăng ký và video trên kênh, cung cấp lượng dữ liệu tốt để phân tích và tích hợp.

Tuy nhiên, có một số yếu tố đặc biệt không thể truy cập qua API và chỉ có thể lấy được thông qua kỹ thuật web scraping. Ví dụ: để thu thập các chỉ số chi tiết về mức độ tương tác như cảm xúc trong bình luận hoặc thời điểm người dùng tương tác, bạn sẽ cần đến phương pháp scraping trực tiếp các trang YouTube. Kỹ thuật này thường phức tạp hơn và có thể gặp rủi ro do nội dung YouTube thay đổi liên tục cùng với các quy định nghiêm ngặt về trích xuất dữ liệu.

Trong các phần tiếp theo, chúng tôi sẽ hướng dẫn bạn cách xây dựng một đoạn mã và cách trích xuất dữ liệu từ YouTube bằng Python một cách hiệu quả.

Sử Dụng Proxy Để Tránh Bị Phát Hiện Khi Trích Xuất Dữ Liệu Từ YouTube

Để trích xuất video YouTube bằng Python, việc sử dụng proxy là cần thiết để tránh bị chặn IP và vượt qua các hệ thống chống bot. Dưới đây là một số loại proxy và mô tả của chúng:

  1. Proxy dân cư (Residential proxies) được kết nối với các địa chỉ IP thực và được sử dụng như các kết nối hợp pháp tới trang web. Để trích xuất dữ liệu từ YouTube, nơi yêu cầu mức độ tin cậy cao để tránh bị phát hiện, proxy là lựa chọn tốt nhất. Chúng cho phép trình trích xuất hành xử như người dùng thực, giảm thiểu khả năng bị phát hiện là bot.
  2. Proxy ISP là lựa chọn trung gian giữa proxy dân cư và proxy trung tâm dữ liệu. Chúng được cung cấp bởi các nhà cung cấp dịch vụ Internet, những người cấp địa chỉ IP hợp lệ rất khó bị đánh dấu là proxy. Điều này làm cho chúng rất hiệu quả khi cần trích xuất kết quả tìm kiếm trên YouTube, nơi đòi hỏi tính xác thực cao và hiệu suất tốt.
  3. Mặc dù proxy trung tâm dữ liệu (Datacenter proxies) có tốc độ cao nhất, nhưng chúng dễ dàng bị YouTube phát hiện vì đến từ các trung tâm dữ liệu lớn. Rủi ro bị chặn khi trích xuất khá cao dù chúng rất hiệu quả và dễ sử dụng. Loại này phù hợp khi nhu cầu xử lý dữ liệu nhanh vượt trên nguy cơ bị phát hiện.
  4. Proxy di động (Mobile proxies) là giải pháp hợp pháp nhất vì chúng định tuyến kết nối thông qua thiết bị di động trên mạng di động. Việc sử dụng chúng cho các tác vụ scraping là hiệu quả nhất vì chúng ít bị chặn hơn. Các IP di động thường được các nhà mạng xoay vòng, làm cho loại proxy này rất khó bị đánh dấu. Tuy nhiên, cần lưu ý rằng tốc độ của chúng có thể chậm hơn so với các loại khác.

Nếu sử dụng những loại proxy này một cách chiến lược, bạn có thể trích xuất dữ liệu từ YouTube mà không bị phát hiện, cho phép truy cập dữ liệu liên tục trong khi vẫn tuân thủ Điều khoản Dịch vụ của nền tảng. Ngoài ra, việc hiểu rõ về các loại proxy sẽ giúp ích rất nhiều khi bạn cần tìm proxy cho scraping.

Tạo Trình Trích Xuất Dữ Liệu Từ YouTube

Hãy bắt đầu với cách trích xuất dữ liệu từ YouTube bằng cách tạo một đoạn mã. Có một số gói cần phải được cài đặt. Trước tiên, chúng ta sẽ cài đặt Selenium-wire, một phần mở rộng proxy của Selenium, đi kèm với một số lớp và mô-đun quan trọng. Hãy sử dụng chuỗi lệnh sau trong giao diện dòng lệnh của bạn để cài đặt các gói này:


pip install selenium-wire selenium blinker==1.7.0

Bây giờ, hãy chuyển sự chú ý của chúng ta đến phần nhập khẩu (imports).

Bước 1: Nhập các thư viện và gói cần thiết

Tại thời điểm này, chúng ta cần tải các thư viện và gói đã được thiết kế để làm việc với các phần tử web mà script đã được viết cho chúng. Ngoài ra, chúng ta cũng nên bao gồm các mô-đun xử lý dữ liệu và quản lý thời gian chạy để đảm bảo script được thực thi một cách hiệu quả.


from selenium.webdriver.chrome.options import Options
from seleniumwire import webdriver as wiredriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.action_chains import ActionChains
import json
import time

Mô-đun json hỗ trợ chuyển đổi dữ liệu đã trích xuất sang định dạng JSON đúng chuẩn để trình bày dễ hiểu hơn, đồng thời giúp ẩn địa chỉ IP của chúng ta. Trong khi đó, mô-đun time được sử dụng để làm mờ các hành động và thêm yếu tố ngẫu nhiên nhằm tránh hành vi quá dễ đoán bị phát hiện.

Ngoài ra, nó cũng giúp đảm bảo rằng các phần tử cần thiết để trích xuất dữ liệu đã được tải sẵn trên trang. Các phần nhập khẩu còn lại là những lớp hoặc mô-đun phụ cần thiết để xử lý những chức năng khác nhau sẽ được trình bày sau ở các phần tiếp theo của mã nguồn.

Bước 2: Thiết lập Trình điều khiển Chrome cho Selenium

Khi một thể hiện của Selenium được khởi chạy từ đoạn mã viết bằng Python, đoạn mã đó sẽ sử dụng địa chỉ IP của chúng ta để thực hiện các tác vụ cần thiết. Điều này có thể gây ra vấn đề lớn đối với một số trang web như YouTube, nơi dữ liệu bị trích xuất từ nền tảng của họ. Do đó, nên xem lại tệp robots.txt của trang web để hiểu rõ hơn các giới hạn được đặt ra. Nếu không, bạn có thể phải đối mặt với việc bị cấm tạm thời IP khi cố gắng trích xuất dữ liệu từ các kênh YouTube chẳng hạn.

Để giải quyết các thách thức này, chúng ta cần thực hiện một số bước. Đầu tiên, bạn cần lưu thông tin proxy mà bạn sẽ sử dụng vào ba biến cơ bản. Sau đó, chúng ta định nghĩa một biến tùy chọn có tên là chrome_options, biến này sẽ được truyền vào thể hiện selenium.Chrome() để chỉ định proxy nào sẽ được sử dụng trong quá trình scraping. Thông tin proxy được thiết lập bằng cách truyền các tham số cần thiết vào chrome_options. Dưới đây là cách viết đoạn script scraping YouTube sử dụng proxy:


# Chỉ định địa chỉ máy chủ proxy với tên người dùng và mật khẩu
proxy_address = ""
proxy_username = ""
proxy_password = ""
# Thiết lập các tùy chọn Chrome với proxy và xác thực
chrome_options = Options()
chrome_options.add_argument(f'--proxy-server={proxy_address}')
chrome_options.add_argument(f'--proxy-auth={proxy_username}:{proxy_password}')
# Tạo một thể hiện webdriver với Selenium-Wire
driver = wiredriver.Chrome(options=chrome_options)

Bước 3: Cách Trích Xuất Các Trang Video Trên YouTube

Tạo một biến có tên “youtube_url_to_scrape” để lưu địa chỉ trang chủ của YouTube. Biến này sẽ được sử dụng trong phương thức “driver.get()” của Selenium, giúp chương trình biết cần truy cập trang web cụ thể nào để tiến hành trích xuất dữ liệu. Hành động này sẽ khiến một cửa sổ Chrome mới được mở ra khi đoạn mã được thực thi.


youtube_url_to_scrape = ""
# Thực hiện tự động hóa selen của bạn với các khả năng nâng cao của dây selen
driver.get(youtube_url_to_scrape)

Tiếp theo, chúng tôi sẽ mô tả hàm “extract_information()”, hàm này thực hiện việc trích xuất thông tin từ trang theo đúng như tên gọi của nó.

Chúng tôi đã đảm bảo rằng tất cả các phần tử trên trang đã được tải đầy đủ. Điều này được thực hiện bằng cách sử dụng WebDriver API kết hợp với WebDriverWait để tạm dừng script cho đến khi phần tử đại diện là nút “more” xuất hiện và được nhấp vào. Khi có sẵn, Selenium sẽ thực hiện hành động nhấp bằng JavaScript để hiển thị toàn bộ mô tả của video.

Vấn Đề Bình Luận Động

Để khắc phục vấn đề này, chúng tôi đang triển khai một giải pháp nhằm loại bỏ bất kỳ sự cố nào liên quan. Sử dụng lớp Actions và mô-đun Time, chúng tôi cuộn xuống hai lần mỗi 10 giây, đảm bảo thu thập được càng nhiều bình luận YouTube càng tốt. Điều này giúp tránh được các rắc rối liên quan đến nội dung được tải động.


def extract_information() -> dict:
   try:
       element = WebDriverWait(driver, 15).until(
           EC.presence_of_element_located((By.XPATH, '//*[@id="expand"]'))
       )

       element.click()

       time.sleep(10)
       actions = ActionChains(driver)
       actions.send_keys(Keys.END).perform()
       time.sleep(10)
       actions.send_keys(Keys.END).perform()
       time.sleep(10)

Khi sử dụng Selenium WebDriver, có nhiều cách khác nhau để tìm kiếm các phần tử. Bạn có thể tìm theo ID, theo CLASS_NAME, theo XPATH, v.v. Trong hướng dẫn Python về cách trích xuất dữ liệu từ YouTube này, chúng tôi sẽ kết hợp các cách thay vì chỉ dùng một phương pháp duy nhất.

XPATH là một hệ thống phức tạp hơn để tìm các biến cần trích xuất vì nó có xu hướng dựa trên mẫu. Nó được coi là khó nhất, nhưng ít nhất không phải khi sử dụng với Chrome.

Khi xem mã nguồn, bạn chỉ cần nhấp chuột phải vào phần tử trong công cụ kiểm tra của Chrome và chọn tùy chọn sao chép XPATH. Sau khi có được XPATH, phương thức ‘find_elements’ có thể dễ dàng được sử dụng để tìm tất cả các thành phần chứa thông tin cần thiết như tiêu đề video, mô tả, v.v.

Cần lưu ý rằng một số tính năng trên trang web có thể có thuộc tính trùng lặp, vì vậy việc sử dụng kỹ thuật ‘find_elements()’ cơ bản sẽ trả về một danh sách thay vì một chuỗi. Trong trường hợp này, bạn cần kiểm tra danh sách và xác định chỉ số nào chứa thông tin cần thiết và đoạn văn bản nào cần được trích xuất.

Cuối cùng, một biến từ điển (dictionary) có tên là “data” sẽ được trả về, chứa toàn bộ thông tin đã thu thập được trong quá trình trích xuất, và sẽ là thành phần quan trọng cho phần tiếp theo.


    video_title = driver.find_elements(By.XPATH, '//*[@id="title"]/h1')[0].text

   owner = driver.find_elements(By.XPATH, '//*[@id="text"]/a')[0].text

   total_number_of_subscribers = \
       driver.find_elements(By.XPATH, "//div[@id='upload-info']//yt-formatted-string[@id='owner-sub-count']")[
           0].text

   video_description = driver.find_elements(By.XPATH,                                  '//*[@id="description-inline-expander"]/yt-attributed-string/span/span')
   result = []
   for i in video_description:
       result.append(i.text)
   description = ''.join(result)

   publish_date = driver.find_elements(By.XPATH, '//*[@id="info"]/span')[2].text
   total_views = driver.find_elements(By.XPATH, '//*[@id="info"]/span')[0].text

   number_of_likes = driver.find_elements(By.XPATH,                                   '//*[@id="top-level-buttons-computed"]/segmented-like-dislike-button-view-model/yt-smartimation/div/div/like-button-view-model/toggle-button-view-model/button-view-model/button/div')[
       1].text

   comment_names = driver.find_elements(By.XPATH, '//*[@id="author-text"]/span')
   comment_content = driver.find_elements(By.XPATH, '//*[@id="content-text"]/span')
   comment_library = []

   for each in range(len(comment_names)):
       name = comment_names[each].text
       content = comment_content[each].text
       indie_comment = {
           'name': name,
           'comment': content
       }
       comment_library.append(indie_comment)

   data = {
       'owner': owner,
       'subscribers': total_number_of_subscribers,
       'video_title': video_title,
       'description': description,
       'date': publish_date,
       'views': total_views,
       'likes': number_of_likes,
       'comments': comment_library
   }

   return data

except Exception as err:
   print(f"Error: {err}")

Bước 4: Ghi Dữ Liệu Đã Thu Thập Vào Tệp JSON


def organize_write_data(data:dict):
    output = json.dumps(data, indent=2, ensure_ascii=False).encode("ascii", "ignore").decode("utf-8")
    try:
        with open("output.json", 'w', encoding='utf-8') as file:
            file.write(output)
    except Exception as err:
        print(f"Error encountered: {err}")

Một hàm do người dùng định nghĩa có tên là “organize_write_data” được thiết kế để nhận đầu ra “data” từ thao tác trước đó. Nhiệm vụ chính của nó là định dạng dữ liệu theo chuẩn JSON và ghi vào một tệp có tên là output.json, đồng thời đảm bảo rằng các bước ghi dữ liệu vào tệp được thực hiện đúng cách.

Mã Nguồn Hoàn Chỉnh

Bây giờ chúng ta đã hiểu cách trích xuất dữ liệu từ YouTube một cách chính xác. Dưới đây là toàn bộ mã nguồn của chương trình scraping mà chúng ta đã xây dựng:


from selenium.webdriver.chrome.options import Options
from seleniumwire import webdriver as wiredriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.action_chains import ActionChains
import json
import time

# Chỉ định địa chỉ máy chủ proxy với tên người dùng và mật khẩu
proxy_address = ""
proxy_username = ""
proxy_password = ""

# Thiết lập các tùy chọn Chrome với proxy và xác thực
chrome_options = Options()
chrome_options.add_argument(f'--proxy-server={proxy_address}')
chrome_options.add_argument(f'--proxy-auth={proxy_username}:{proxy_password}')

# Tạo một thể hiện webdriver với Selenium-Wire
driver = wiredriver.Chrome(options=chrome_options)

youtube_url_to_scrape = ""

# Thực hiện tự động hóa selen của bạn với các khả năng nâng cao của dây selen
driver.get(youtube_url_to_scrape)


def extract_information() -> dict:
   try:
       element = WebDriverWait(driver, 15).until(
           EC.presence_of_element_located((By.XPATH, '//*[@id="expand"]'))
       )
       element.click()

       time.sleep(10)
       actions = ActionChains(driver)
       actions.send_keys(Keys.END).perform()
       time.sleep(10)
       actions.send_keys(Keys.END).perform()
       time.sleep(10)

       video_title = driver.find_elements(By.XPATH, '//*[@id="title"]/h1')[0].text

       owner = driver.find_elements(By.XPATH, '//*[@id="text"]/a')[0].text
       total_number_of_subscribers = \
           driver.find_elements(By.XPATH, "//div[@id='upload-info']//yt-formatted-string[@id='owner-sub-count']")[
               0].text

       video_description = driver.find_elements(By.XPATH,
                                                '//*[@id="description-inline-expander"]/yt-attributed-string/span/span')
       result = []
       for i in video_description:
           result.append(i.text)
       description = ''.join(result)

       publish_date = driver.find_elements(By.XPATH, '//*[@id="info"]/span')[2].text
       total_views = driver.find_elements(By.XPATH, '//*[@id="info"]/span')[0].text

       number_of_likes = driver.find_elements(By.XPATH,
                                              '//*[@id="top-level-buttons-computed"]/segmented-like-dislike-button-view-model/yt-smartimation/div/div/like-button-view-model/toggle-button-view-model/button-view-model/button/div')[
           1].text

       comment_names = driver.find_elements(By.XPATH, '//*[@id="author-text"]/span')
       comment_content = driver.find_elements(By.XPATH,
                                              '//*[@id="content-text"]/span')
       comment_library = []

       for each in range(len(comment_names)):
           name = comment_names[each].text
           content = comment_content[each].text
           indie_comment = {
               'name': name,
               'comment': content
           }
           comment_library.append(indie_comment)

       data = {
           'owner': owner,
           'subscribers': total_number_of_subscribers,
           'video_title': video_title,
           'description': description,
           'date': publish_date,
           'views': total_views,
           'likes': number_of_likes,
           'comments': comment_library
       }

       return data

   except Exception as err:
       print(f"Error: {err}")


# Ghi lại dữ liệu vào JSON
def organize_write_data(data: dict):
   output = json.dumps(data, indent=2, ensure_ascii=False).encode("ascii", "ignore").decode("utf-8")
   try:
       with open("output.json", 'w', encoding='utf-8') as file:
           file.write(output)
   except Exception as err:
       print(f"Error encountered: {err}")


organize_write_data(extract_information())
driver.quit()

Kết Quả

Bây giờ chúng ta cũng đã biết cách trích xuất bình luận YouTube bằng Python. Kết quả đầu ra sẽ trông như sau:


{
  "owner": "Suzie Taylor",
  "subscribers": "165K subscribers",
  "video_title": "I Spent $185,000 From MrBeast",
  "description": "@MrBeast blessed me with $185,000, after SURVIVING 100 DAYS trapped with a STRANGER. Now I want to bless you!\nGive This A Like if you Enjoyed :))\n-\nTo Enter The Giveaway: \nFollow me on Instagram: https://www.instagram.com/sooztaylor/...\nSubscribe to me on Youtube: \n   / @suzietaylor  \nI am picking winners for the giveaway ONE WEEK from today (December 23rd) \n-\nThank you everyone for all of your love already. This is my dream!",
  "date": "Dec 16, 2023",
  "views": "4,605,785 ",
  "likes": "230K",
  "comments": [
    {
      "name": "",
      "comment": "The right person got the money "
    },
    {
      "name": "@Scottster",
      "comment": "Way to go Suzie, a worthy winner! Always the thought that counts and you put a lot into it!"
    },
    {
      "name": "@cidsx",
      "comment": "I'm so glad that she's paying it forward! She 100% deserved the reward"
    },
    {
      "name": "@Basicskill720",
      "comment": "This is amazing Suzie. Way to spread kindness in this dark world. It is much needed !"
    },
    {
      "name": "@eliasnull",
      "comment": "You are such a blessing Suzie! The world needs more people like you."
    },
    {
      "name": "@iceline22",
      "comment": "That's so awesome you're paying it forward! You seem so genuine, and happy to pass along your good fortune! Amazing! Keep it up!"
    },
    {
      "name": "",
      "comment": "Always nice to see a Mr. Beast winner turn around and doing nice things for others. I know this was but a small portion of what you won and nobody expects you to not take care of yourself with that money, but to give back even in small ways can mean so much. Thank you for doing this."
    }
  ]
}

Cách Trích Xuất Dữ Liệu YouTube: Tổng Kết Cuối

Khả năng tận dụng dữ liệu từ cơ sở dữ liệu của YouTube là vô cùng quý giá khi sử dụng các script tự động hoặc proxy nhằm đảm bảo tuân thủ đúng các quy định của nền tảng. Phương pháp chính về cách trích xuất dữ liệu YouTube mà chúng tôi đã trình bày ở trên sẽ rất hữu ích để thu thập dữ liệu một cách có trách nhiệm, đồng thời tránh bị nền tảng chặn hoặc giới hạn quyền truy cập.

Nội dung của bài viết:

Các bài viết gần đây

Quay lại blog
Quay lại blog