MCP Server cho Web Scraping — Claude thu thập dữ liệu từ website
Điểm nổi bật
Nhấn để đến mục tương ứng
- 1 Xây dựng Custom Scraping MCP Server Khi nhu cầu thu thập dữ liệu trở nên phức tạp hoặc chuyên biệt, bạn nên xây dựng MCP server riêng thay vì dùng Playwright MCP trực tiếp.
- 2 Với MCP Server, Claude có thể trực tiếp điều khiển trình duyệt headless để thu thập dữ liệu, giúp quy trình trở nên đơn giản và linh hoạt hơn rất nhiều.
- 3 Ví dụ 2: Thu thập dữ liệu từ bảng biểu Nhiều website hiển thị dữ liệu dưới dạng bảng HTML, ví dụ giá cổ phiếu, tỷ giá ngoại tệ, bảng xếp hạng: Mở trang https://cafef.vn/thi-truong-chung-khoan.chn và thu thập bảng giá cổ phiếu hiện tại.
- 4 Thu thập dữ liệu tài chính từ CafeF Thu thập bảng giá 10 cổ phiếu vốn hóa lớn nhất trên sàn HOSE từ CafeF.
- 5 Dưới đây là cách tích hợp scraping MCP vào workflow thực tế: Workflow 1: Nghiên cứu thị trường tự động Thực hiện nghiên cứu thị trường cho ngành thương mại điện tử tại Việt Nam: 1.
Thu thập dữ liệu từ website (web scraping) là nhu cầu thực tế trong nhiều lĩnh vực: nghiên cứu thị trường, theo dõi giá cả, tổng hợp tin tức, phân tích đối thủ. Trước đây, bạn phải viết script riêng bằng Python hoặc Node.js, xử lý hàng loạt edge case. Với MCP Server, Claude có thể trực tiếp điều khiển trình duyệt headless để thu thập dữ liệu, giúp quy trình trở nên đơn giản và linh hoạt hơn rất nhiều.
Playwright MCP Server là gì?
Playwright MCP Server là một MCP server được xây dựng trên nền tảng Playwright — thư viện tự động hóa trình duyệt của Microsoft. Đây là một trong những MCP server phổ biến nhất trong hệ sinh thái, cho phép Claude điều khiển trình duyệt Chrome, Firefox hoặc WebKit để tương tác với website giống như người dùng thực.
Khi kết hợp với Claude, Playwright MCP Server mang lại khả năng:
- Điều hướng trang web: mở URL, click link, điền form, cuộn trang
- Trích xuất dữ liệu: đọc nội dung text, bảng biểu, hình ảnh, metadata
- Chụp ảnh màn hình: capture toàn trang hoặc một phần cụ thể
- Xử lý JavaScript: chờ nội dung dynamic load, tương tác với SPA
- Quản lý session: login, duy trì cookie, xử lý authentication
Cài đặt và cấu hình Playwright MCP Server
Bước đầu tiên là cài đặt Playwright MCP Server. Có hai cách phổ biến: sử dụng package chính thức từ Microsoft hoặc cài từ npm.
Cách 1: Cấu hình trong Claude Code
Thêm vào file cấu hình MCP của Claude Code (thường là claude_desktop_config.json hoặc .mcp.json trong project):
{
"mcpServers": {
"playwright": {
"command": "npx",
"args": [
"@anthropic-ai/mcp-playwright"
]
}
}
}
Cách 2: Cài đặt global
# Cài đặt package
npm install -g @anthropic-ai/mcp-playwright
# Cài đặt browser binaries cho Playwright
npx playwright install chromium
Sau khi cài đặt, khởi động lại Claude Code hoặc Claude Desktop. Bạn sẽ thấy các tool mới xuất hiện như browser_navigate, browser_click, browser_snapshot, browser_type.
Xác nhận cài đặt thành công
Yêu cầu Claude thực hiện thao tác đơn giản để kiểm tra:
Hãy mở trang https://example.com và cho tôi biết tiêu đề của trang.
Nếu Claude trả về tiêu đề trang thành công, MCP server đã hoạt động đúng.
Thu thập dữ liệu cơ bản
Bắt đầu với một tác vụ đơn giản: thu thập danh sách bài viết từ một trang tin tức.
Ví dụ 1: Lấy tiêu đề bài viết từ trang chủ
Hãy mở trang https://vnexpress.net và thu thập tất cả
tiêu đề bài viết hiển thị trên trang chủ.
Với mỗi bài viết, lấy:
- Tiêu đề
- Link bài viết
- Chuyên mục (nếu có)
Trả kết quả dạng bảng.
Claude sẽ sử dụng Playwright MCP để mở trang, đọc DOM và trích xuất thông tin theo CSS selector hoặc ARIA label. Quá trình này diễn ra tự động mà không cần bạn viết code.
Ví dụ 2: Thu thập dữ liệu từ bảng biểu
Nhiều website hiển thị dữ liệu dưới dạng bảng HTML, ví dụ giá cổ phiếu, tỷ giá ngoại tệ, bảng xếp hạng:
Mở trang https://cafef.vn/thi-truong-chung-khoan.chn
và thu thập bảng giá cổ phiếu hiện tại.
Lấy 20 mã đầu tiên với các cột:
- Mã cổ phiếu
- Giá hiện tại
- Thay đổi (%)
- Khối lượng giao dịch
Xuất kết quả dạng JSON.
Xây dựng Custom Scraping MCP Server
Khi nhu cầu thu thập dữ liệu trở nên phức tạp hoặc chuyên biệt, bạn nên xây dựng MCP server riêng thay vì dùng Playwright MCP trực tiếp. Điều này giúp đóng gói logic scraping, xử lý lỗi và rate limiting một cách có hệ thống.
Kiến trúc Custom Scraping MCP
Một custom scraping MCP server thường bao gồm các thành phần:
-
Tool definitions: các tool chuyên biệt cho từng nguồn dữ liệu (ví dụ:
scrape_vnexpress,scrape_cafef) - Browser pool: quản lý nhiều browser instance để tăng throughput
- Rate limiter: kiểm soát tốc độ request để tránh bị block
- Cache layer: lưu cache kết quả để giảm tải cho target website
- Error handler: xử lý timeout, CAPTCHA, IP block
Triển khai MCP Server với TypeScript
// scraping-mcp/src/index.ts
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { chromium, Browser, Page } from "playwright";
import { z } from "zod";
const server = new McpServer({
name: "web-scraper",
version: "1.0.0",
});
let browser: Browser | null = null;
async function getBrowser(): Promise<Browser> {
if (!browser) {
browser = await chromium.launch({ headless: true });
}
return browser;
}
// Rate limiting
const requestTimestamps: Map<string, number[]> = new Map();
function checkRateLimit(domain: string, maxPerMinute: number = 10): boolean {
const now = Date.now();
const timestamps = requestTimestamps.get(domain) || [];
const recent = timestamps.filter(t => now - t < 60000);
if (recent.length >= maxPerMinute) return false;
recent.push(now);
requestTimestamps.set(domain, recent);
return true;
}
// Tool: Thu thap bai viet tu trang tin
server.tool(
"scrape_news_articles",
"Thu thap danh sach bai viet tu trang tin tuc Viet Nam",
{
url: z.string().url().describe("URL trang can thu thap"),
selector: z.string().describe("CSS selector cho bai viet"),
limit: z.number().optional().default(20)
.describe("So bai viet toi da"),
},
async ({ url, selector, limit }) => {
const domain = new URL(url).hostname;
if (!checkRateLimit(domain)) {
return {
content: [{ type: "text",
text: "Rate limit exceeded. Thu lai sau 1 phut." }],
};
}
const b = await getBrowser();
const page = await b.newPage();
try {
await page.goto(url, { waitUntil: "networkidle" });
const articles = await page.$$eval(
selector,
(els, max) => els.slice(0, max).map(el => ({
title: el.querySelector("h2, h3, .title")?.textContent?.trim(),
link: el.querySelector("a")?.getAttribute("href"),
summary: el.querySelector("p, .description")?.textContent?.trim(),
})),
limit
);
return {
content: [{ type: "text",
text: JSON.stringify(articles, null, 2) }],
};
} finally {
await page.close();
}
}
);
const transport = new StdioServerTransport();
await server.connect(transport);
Xử lý phân trang (Pagination)
Hầu hết các website hiển thị dữ liệu qua nhiều trang. Có ba kiểu phân trang phổ biến và cách xử lý từng kiểu:
Kiểu 1: Phân trang bằng URL parameter
Đây là kiểu đơn giản nhất, URL thay đổi theo số trang: ?page=1, ?page=2.
Thu thập tất cả bài viết về "AI" từ VnExpress.
Bắt đầu từ trang tìm kiếm, duyệt qua tất cả các trang kết quả
(tối đa 5 trang). Với mỗi bài viết lấy tiêu đề, link,
ngày đăng và tóm tắt.
Lưu ý: Chờ mỗi trang load xong trước khi chuyển sang trang tiếp.
Nghỉ 2 giây giữa các request.
Kiểu 2: Infinite scroll (cuộn vô hạn)
Nhiều website hiện đại sử dụng lazy loading khi cuộn trang:
// Trong custom MCP server - xu ly infinite scroll
server.tool(
"scrape_infinite_scroll",
"Thu thap du lieu tu trang co infinite scroll",
{
url: z.string().url(),
itemSelector: z.string(),
maxItems: z.number().default(50),
scrollPauseMs: z.number().default(2000),
},
async ({ url, itemSelector, maxItems, scrollPauseMs }) => {
const b = await getBrowser();
const page = await b.newPage();
await page.goto(url, { waitUntil: "networkidle" });
let previousCount = 0;
let items: any[] = [];
while (items.length < maxItems) {
items = await page.$$eval(itemSelector, els =>
els.map(el => ({
text: el.textContent?.trim(),
href: el.querySelector("a")?.href,
}))
);
if (items.length === previousCount) break;
previousCount = items.length;
await page.evaluate(() =>
window.scrollTo(0, document.body.scrollHeight)
);
await page.waitForTimeout(scrollPauseMs);
}
await page.close();
return {
content: [{ type: "text",
text: JSON.stringify(items.slice(0, maxItems), null, 2) }],
};
}
);
Kiểu 3: Nút "Xem thêm" hoặc "Load more"
Một số website yêu cầu click nút để load thêm nội dung. Playwright MCP xử lý bằng cách tìm và click nút cho đến khi không còn nữa hoặc đạt giới hạn.
Data Extraction Patterns
Thu thập dữ liệu thô chỉ là bước đầu. Bước tiếp theo là trích xuất và cấu trúc hóa dữ liệu. Dưới đây là các pattern phổ biến:
Pattern 1: Structured Data Extraction
Trích xuất dữ liệu có cấu trúc từ các trang sản phẩm, hồ sơ doanh nghiệp:
Mở trang sản phẩm tại [URL] và trích xuất thông tin
theo cấu trúc sau:
{
"ten_san_pham": "",
"gia": "",
"mo_ta": "",
"thong_so_ky_thuat": {
"kich_thuoc": "",
"trong_luong": "",
"chat_lieu": ""
},
"danh_gia": {
"diem_trung_binh": "",
"so_luong_danh_gia": ""
},
"hinh_anh": ["url1", "url2"]
}
Nếu thông tin nào không có trên trang, ghi "N/A".
Pattern 2: Multi-page Data Aggregation
Thu thập dữ liệu từ nhiều trang liên quan và tổng hợp lại:
Thu thập thông tin giá vé máy bay Hà Nội - TP.HCM
từ 3 trang so sánh giá khác nhau.
Với mỗi trang, lấy:
- Hãng bay
- Giá vé thấp nhất
- Thời gian bay
Sau đó tổng hợp thành bảng so sánh và đưa ra
đề xuất lựa chọn tốt nhất.
Pattern 3: Monitoring và Change Detection
Theo dõi thay đổi trên website theo thời gian:
// Tool theo doi thay doi gia
server.tool(
"monitor_price",
"Theo doi gia san pham va phat hien thay doi",
{
url: z.string().url(),
priceSelector: z.string(),
productName: z.string(),
},
async ({ url, priceSelector, productName }) => {
const b = await getBrowser();
const page = await b.newPage();
await page.goto(url, { waitUntil: "domcontentloaded" });
const currentPrice = await page.$eval(
priceSelector,
el => el.textContent?.trim() || "N/A"
);
await page.close();
return {
content: [{
type: "text",
text: JSON.stringify({
product: productName,
price: currentPrice,
timestamp: new Date().toISOString(),
url: url,
}, null, 2),
}],
};
}
);
Tuân thủ robots.txt và đạo đức thu thập dữ liệu
Thu thập dữ liệu từ website cần tuân thủ các nguyên tắc đạo đức và pháp lý. Đây không chỉ là vấn đề kỹ thuật mà còn là trách nhiệm của developer.
Kiểm tra robots.txt
Trước khi scrape bất kỳ website nào, luôn kiểm tra file robots.txt:
// Kiem tra robots.txt truoc khi scrape
async function isAllowed(url: string): Promise<boolean> {
const parsedUrl = new URL(url);
const robotsUrl = parsedUrl.origin + "/robots.txt";
try {
const response = await fetch(robotsUrl);
const robotsTxt = await response.text();
// Kiem tra co bi disallow khong
const lines = robotsTxt.split("
");
const path = parsedUrl.pathname;
for (const line of lines) {
const trimmed = line.trim().toLowerCase();
if (trimmed.startsWith("disallow:")) {
const disallowedPath = trimmed.replace("disallow:", "").trim();
if (path.startsWith(disallowedPath)) {
return false;
}
}
}
return true;
} catch {
// Khong co robots.txt - mac dinh cho phep
return true;
}
}
Nguyên tắc thu thập dữ liệu có đạo đức
- Tôn trọng robots.txt: Nếu website cấm thu thập một đường dẫn, không truy cập đường dẫn đó
- Giới hạn tốc độ: Không gửi quá nhiều request trong thời gian ngắn. Quy tắc chung: tối đa 1 request mỗi 2-3 giây cho cùng một domain
- Xác định danh tính: Đặt User-Agent rõ ràng để chủ website biết ai đang truy cập
- Không thu thập dữ liệu cá nhân: Tránh thu thập email, số điện thoại, địa chỉ cá nhân trừ khi có sự đồng ý
- Lưu cache: Cache kết quả để giảm số lần truy cập lặp lại cùng một trang
- Tuân thủ Terms of Service: Đọc điều khoản sử dụng của website trước khi thu thập dữ liệu
Rate Limiting và quản lý request
Rate limiting là yếu tố quan trọng để tránh bị block và đảm bảo không gây quá tải cho website mục tiêu.
Chiến lược rate limiting
// Rate limiter nang cao voi token bucket
class RateLimiter {
private tokens: number;
private maxTokens: number;
private refillRate: number; // tokens per second
private lastRefill: number;
constructor(maxPerMinute: number) {
this.maxTokens = maxPerMinute;
this.tokens = maxPerMinute;
this.refillRate = maxPerMinute / 60;
this.lastRefill = Date.now();
}
async waitForToken(): Promise<void> {
this.refill();
while (this.tokens < 1) {
const waitTime = (1 - this.tokens) / this.refillRate * 1000;
await new Promise(r => setTimeout(r, waitTime));
this.refill();
}
this.tokens -= 1;
}
private refill(): void {
const now = Date.now();
const elapsed = (now - this.lastRefill) / 1000;
this.tokens = Math.min(
this.maxTokens,
this.tokens + elapsed * this.refillRate
);
this.lastRefill = now;
}
}
// Su dung: toi da 10 request/phut cho moi domain
const limiters = new Map<string, RateLimiter>();
function getLimiter(domain: string): RateLimiter {
if (!limiters.has(domain)) {
limiters.set(domain, new RateLimiter(10));
}
return limiters.get(domain)!;
}
Ví dụ thực tế: Thu thập dữ liệu website Việt Nam
Dưới đây là các ví dụ thực tế áp dụng cho các website phổ biến tại Việt Nam.
Thu thập tin tức từ VnExpress
Hãy thu thập 10 bài viết mới nhất từ chuyên mục
Kinh doanh trên VnExpress.
Với mỗi bài viết, lấy:
1. Tiêu đề
2. URL bài viết
3. Tóm tắt (description)
4. Thời gian đăng
5. Tác giả (nếu có)
Kiểm tra robots.txt trước khi bắt đầu.
Nghỉ 3 giây giữa mỗi request.
Trả kết quả dạng JSON.
Thu thập dữ liệu tài chính từ CafeF
Thu thập bảng giá 10 cổ phiếu vốn hóa lớn nhất
trên sàn HOSE từ CafeF.
Lấy các thông tin:
- Mã cổ phiếu
- Giá tham chiếu
- Giá trần / Giá sàn
- Giá hiện tại
- Thay đổi so với phiên trước
- Khối lượng giao dịch
Tuân thủ robots.txt và rate limit.
Xuất dữ liệu dạng bảng.
Xử lý các tình huống phức tạp
Website yêu cầu đăng nhập
Một số dữ liệu chỉ hiển thị sau khi đăng nhập. Playwright MCP có thể tự động điền form login:
Mở trang [URL đăng nhập].
Điền email: [email] và mật khẩu: [password].
Click nút đăng nhập.
Chờ trang dashboard load xong.
Sau đó truy cập [URL dữ liệu] và thu thập bảng báo cáo.
Lưu ý quan trọng: Không bao giờ chia sẻ thông tin đăng nhập trong prompt công khai. Sử dụng biến môi trường hoặc secret management để bảo vệ credentials.
Website render bằng JavaScript (SPA)
Nhiều website hiện đại sử dụng React, Vue hoặc Angular. Nội dung không có sẵn trong HTML mà được render bằng JavaScript. Playwright xử lý tốt trường hợp này vì nó chạy browser thực sự, chờ JavaScript thực thi xong rồi mới đọc DOM.
Xử lý CAPTCHA và anti-bot
Nếu website có cơ chế chống bot, bạn nên:
- Giảm tốc độ request xuống mức thấp hơn
- Sử dụng User-Agent thực tế
- Cân nhắc liên hệ chủ website để xin phép hoặc sử dụng API chính thức nếu có
- Không cố gắng bypass CAPTCHA vì vi phạm điều khoản sử dụng
Tích hợp scraping vào workflow
Thu thập dữ liệu thường chỉ là bước đầu trong một quy trình lớn hơn. Dưới đây là cách tích hợp scraping MCP vào workflow thực tế:
Workflow 1: Nghiên cứu thị trường tự động
Thực hiện nghiên cứu thị trường cho ngành thương mại điện tử
tại Việt Nam:
1. Thu thập top 10 sản phẩm bán chạy từ 3 sàn TMDT
2. So sánh giá giữa các sàn
3. Phân tích xu hướng giá (nếu có dữ liệu lịch sử)
4. Tổng hợp thành báo cáo với biểu đồ so sánh
Tuân thủ rate limiting và robots.txt cho mỗi website.
Workflow 2: Theo dõi đối thủ cạnh tranh
Theo dõi hoạt động content marketing của đối thủ:
1. Thu thập 5 bài blog mới nhất từ website đối thủ [URL]
2. Phân tích chủ đề, từ khóa chính của mỗi bài
3. So sánh với chiến lược content hiện tại của chúng tôi
4. Đề xuất các chủ đề chúng tôi nên viết
Tối ưu hiệu suất scraping
Khi thu thập dữ liệu ở quy mô lớn, hiệu suất trở thành yếu tố quan trọng:
- Reuse browser context: Thay vì tạo browser mới cho mỗi request, tái sử dụng browser instance và chỉ tạo page mới
- Block tài nguyên không cần thiết: Chặn hình ảnh, CSS, font để trang load nhanh hơn khi chỉ cần dữ liệu text
- Sử dụng cache: Cache kết quả scraping với TTL phù hợp để tránh truy cập lặp lại cùng một trang
- Parallel scraping: Thu thập nhiều trang đồng thời nhưng vẫn giữ rate limit cho mỗi domain
// Block tai nguyen khong can thiet de tang toc
const page = await browser.newPage();
await page.route("**/*.{png,jpg,jpeg,gif,svg,css,woff,woff2}", route =>
route.abort()
);
await page.goto(url, { waitUntil: "domcontentloaded" });
Bước tiếp theo
Bạn đã nắm được cách sử dụng Playwright MCP Server để thu thập dữ liệu từ website một cách tự động và có đạo đức. Từ đây, bạn có thể xây dựng custom MCP server cho các nguồn dữ liệu chuyên biệt, tích hợp vào quy trình làm việc hàng ngày. Hãy luôn tuân thủ robots.txt, áp dụng rate limiting và tôn trọng điều khoản sử dụng của các website. Khám phá thêm các MCP server khác tại Thư viện Ứng dụng Claude.
Bai viet co huu ich khong?
Bản quyền thuộc về tác giả. Vui lòng dẫn nguồn khi chia sẻ.





