0
0
Lập trình
Sơn Tùng Lê
Sơn Tùng Lê103931498422911686980

Xử Lý Song Song với Mage AI: Hướng Dẫn Chi Tiết

Đăng vào 1 ngày trước

• 8 phút đọc

Giới Thiệu

Trong ngành du lịch, nhiều người vẫn bị lừa bởi các công ty lừa đảo. Điều này xảy ra rất nhiều với các gói umrah, hướng dẫn viên du lịch và các công ty du lịch. Tại sao? Bởi vì không dễ dàng để kiểm tra xem một công ty có hợp pháp hay không.

Chính phủ có các trang web chính thức với danh sách các tên bị cấm, đen hoặc đã đăng ký. Có một chức năng tìm kiếm, nhưng vấn đề là dữ liệu được chia thành nhiều danh sách khác nhau. Ví dụ, một danh sách cho hướng dẫn viên du lịch, một danh sách cho umrah, một danh sách cho các công ty du lịch. Bạn phải chọn đúng danh sách trước, và sau đó tìm kiếm. Hơn nữa, mỗi danh sách sử dụng phân trang. Điều này có nghĩa là bạn vẫn phải nhấp từng trang, điều này chậm và không thân thiện.

Tôi bắt đầu nghĩ, tại sao không tạo một trang web đơn giản, nơi mọi người chỉ cần nhập một từ khóa và nó sẽ hiển thị nếu tên đó tồn tại trong bất kỳ danh sách nào? Cách này, du khách có thể nhanh chóng kiểm tra xem một công ty có thực sự hay là lừa đảo. Nhân tiện, tôi làm điều này vì thú vị, vì tôi không thể đi đâu trong kỳ nghỉ học khi mà các con đường đều đông đúc, vì vậy tôi chỉ dành thời gian cho một dự án nhỏ cho vui.

Thách Thức

Phần khó khăn nhất thực sự là thu thập tất cả dữ liệu liên quan. Sao chép và dán bằng tay là một cách có thể và dễ dàng, nhưng đó là quá nhiều công việc, nó sẽ trở thành một dự án căng thẳng sau này haha. Vậy tại sao không sử dụng Mage AI, tôi đã sử dụng nó cho dự án trước đó liên quan đến dữ liệu.

Ban đầu, tôi tạo một block bình thường với một vòng lặp. Nó hoạt động, nhưng quá chậm vì nó đi từng bước qua mỗi trang (ít nhất đối với trang không có nhiều trang). Sau đó, tôi nhận ra, tại sao không thử một dynamic block? Với dynamic blocks, tôi có thể chạy nhiều yêu cầu cùng một lúc với xử lý song song. Nhanh hơn, thông minh hơn.

Dynamic Blocks của Mage AI

Đây là nơi Mage AI giúp đỡ. Mage AI có dynamic blocks. Với tính năng này, chúng ta có thể thu thập nhiều trang cùng một lúc. Điều này có nghĩa là nhanh hơn và dễ dàng hơn. Để tìm hiểu thêm về Dynamic Blocks của Mage AI, hãy truy cập đây.

Cách Thức Hoạt Động

  1. Tạo một danh sách URL bao gồm tham số phân trang bằng cách sử dụng một loader block. Lưu ý rằng một dynamic block phải trả về một danh sách gồm 2 danh sách từ điển.
  2. Thu thập dữ liệu từ trang dựa trên URL được lưu trong danh sách từ điển và giảm dữ liệu vào một tập hợp duy nhất.
  3. Xuất dữ liệu đến đích.

Ví Dụ

Bước Đầu Tiên

Tạo một loader block. Đảm bảo bạn đặt block này là dynamic.

python Copy
from typing import Dict, List
import requests
from bs4 import BeautifulSoup

@data_loader
def load_data(*args, **kwargs) -> List[List[Dict]]:
    """
    Loader này chuẩn bị các tác vụ để thu thập nhiều trang MOTAC.
    Mỗi mục trong 'urls' trở thành một block chạy riêng biệt nếu sử dụng với dynamic blocks.
    """
    url = "https://the-targeted-url"

    response = requests.get(url, timeout=20)
    response.raise_for_status()
    soup = BeautifulSoup(response.text, "html.parser")

    record_tag = soup.select_one("li.uk-disabled span")
    jumlah_rekod = None

    if record_tag:
        text = record_tag.get_text(strip=True)  
        jumlah_rekod = int(text.split(":")[-1].strip())  

    urls = []
    for offset in range(0, jumlah_rekod, 20):  
        if offset == 0:
            urls.append(url)
        else:
            urls.append(f"{url}?s=&n=&v={offset}")

    tasks = []
    metadata = []

    for idx, url in enumerate(urls, start=1):
        tasks.append(dict(id=idx, url=url))
        metadata.append(dict(block_uuid=f"scrape_page_{idx}"))

    return [
        tasks,
        metadata
    ]

Bước Thứ Hai

Tạo một transformer. Transformer này sẽ thực hiện việc thu thập dữ liệu và lấy tất cả dữ liệu từ trang. Điều này sẽ tự động được đặt là dynamic nếu bạn đặt block đầu tiên là dynamic. Điều duy nhất chúng ta cần làm là giảm cho đầu ra. Lý do chúng ta giảm là vì chúng ta muốn xuất trong một bước, để không tạo thêm một block xuất dư thừa.

python Copy
import requests
from bs4 import BeautifulSoup

@transformer
def scrape_page(row, *args, **kwargs):
    url = row["url"]
    response = requests.get(url, timeout=30)
    response.raise_for_status()

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

    results = []
    table = soup.find("table")

    if table:
        headers = [th.get_text(strip=True) for th in table.find_all("th")]
        for tr in table.find_all("tr")[1:]:  # bỏ qua hàng tiêu đề
            cells = [td.get_text(strip=True) for td in tr.find_all("td")]
            if cells:
                results.append(dict(zip(headers, cells)))

    return {
        "page_id": row["id"],
        "url": url,
        "records": results,
    }

Bước Thứ Ba

Thêm một block khác để làm sạch định dạng dữ liệu, tên cột, vv trước khi xuất.

python Copy
if 'transformer' not in globals():
    from mage_ai.data_preparation.decorators import transformer
if 'test' not in globals():
    from mage_ai.data_preparation.decorators import test

import pandas as pd

@transformer
def transform(data, *args, **kwargs):
    df = data

    if '#' in df.columns:
        df = df.drop(columns=['#'])

    df = df.rename(columns={
        'Nama': 'nama',
        'No. TG': 'no_tg',
        'Tempoh Sah': 'tempoh_sah',
        'Tarikh Batal': 'tarikh_batal',
        'Seksyen': 'seksyen'
    })

    for col in ['tempoh_sah', 'tarikh_batal']:
        if col in df.columns:
            df[col] = pd.to_datetime(df[col], format='%d/%m/%y', errors='coerce')

    return df

@test
def test_output(output, *args) -> None:
    # Đảm bảo các cột cần thiết tồn tại
    required_cols = ['nama', 'no_tg', 'tempoh_sah', 'tarikh_batal', 'seksyen']
    for col in required_cols:
        assert col in output.columns, f'Missing column: {col}'

Bước Thứ Tư

Hiện tại, vì đây chỉ là một dự án hàng ngày, tôi sẽ xuất đầu tiên và sử dụng tải đầy đủ trước. Không lo lắng, nếu tôi có tâm trạng, tôi sẽ viết một cách tiếp cận tốt hơn cho điều này :)

python Copy
from mage_ai.settings.repo import get_repo_path
from mage_ai.io.config import ConfigFileLoader
from mage_ai.io.postgres import Postgres
from pandas import DataFrame
from os import path

if 'data_exporter' not in globals():
    from mage_ai.data_preparation.decorators import data_exporter

@data_exporter
def export_data_to_postgres(df: DataFrame, **kwargs) -> None:
    """
    Mẫu để xuất dữ liệu vào cơ sở dữ liệu PostgreSQL.
    Xác định các cài đặt cấu hình của bạn trong 'io_config.yaml'.
    """
    schema_name = 'public'  
    table_name = 'pemandu_pelancong'  
    config_path = path.join(get_repo_path(), 'io_config.yaml')
    config_profile = 'default'

    with Postgres.with_config(ConfigFileLoader(config_path, config_profile)) as loader:
        loader.export(
            df,
            schema_name,
            table_name,
            index=False,  
            if_exists='replace',  
        )

Tại Sao Nên Sử Dụng Dynamic Blocks Để Thu Thập Dữ Liệu?

Dynamic blocks rất mạnh mẽ vì chúng giúp việc thu thập dữ liệu lớn nhanh hơn rất nhiều. Thay vì một yêu cầu sau yêu cầu khác, bạn có thể chạy nhiều yêu cầu cùng một lúc. Đối với các trang web có hàng trăm trang, điều này tiết kiệm rất nhiều thời gian.

Nhưng cũng có một số điều cần lưu ý

  1. Tôn trọng giới hạn tốc độ: Một số trang web có thể chặn bạn nếu bạn gửi quá nhiều yêu cầu cùng một lúc.
  2. Xử lý lỗi: Luôn thêm các lần thử lại trong trường hợp một số yêu cầu bị thất bại.
  3. Đảm bảo tính đồng nhất của dữ liệu: Đảm bảo làm sạch và xác thực dữ liệu trước khi lưu.
  4. Đạo đức và tính hợp pháp: Luôn kiểm tra xem việc thu thập dữ liệu từ trang web có được phép hay không.

Kết Luận

Dự án nhỏ này đã cho tôi thấy được sự hữu ích của các dynamic blocks trong Mage AI. Chỉ với một vài block, tôi đã biến một quy trình thủ công chậm chạp thành một quy trình tự động nhanh chóng. Dữ liệu được thu thập giờ đây có thể được sử dụng để xây dựng một thư mục tìm kiếm đơn giản, giúp mọi người nhanh chóng kiểm tra xem một công ty có thực sự hay là lừa đảo.

Dynamic blocks không chỉ thú vị, chúng còn thực tế, mạnh mẽ và là công cụ tuyệt vời cho bất kỳ ai làm việc với phân trang hoặc gọi API lớn.

Vậy nên hãy nhớ, khi bạn đối mặt với hàng trăm trang, đừng chịu đựng như Anakin, hãy để các block đồng hành cùng bạn.

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào