{"product_id":"mcp-server-cho-web-scraping-claude-thu-thập-dữ-liệu-từ-website","title":"MCP Server cho Web Scraping — Claude thu thập dữ liệu từ website","description":"\n\u003cp\u003eThu 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.\u003c\/p\u003e\n\n\u003ch2\u003ePlaywright MCP Server là gì?\u003c\/h2\u003e\n\u003cp\u003ePlaywright 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.\u003c\/p\u003e\n\u003cp\u003eKhi kết hợp với Claude, Playwright MCP Server mang lại khả năng:\u003c\/p\u003e\n\u003cul\u003e\n  \u003cli\u003e\n\u003cstrong\u003eĐiều hướng trang web:\u003c\/strong\u003e mở URL, click link, điền form, cuộn trang\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eTrích xuất dữ liệu:\u003c\/strong\u003e đọc nội dung text, bảng biểu, hình ảnh, metadata\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eChụp ảnh màn hình:\u003c\/strong\u003e capture toàn trang hoặc một phần cụ thể\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eXử lý JavaScript:\u003c\/strong\u003e chờ nội dung dynamic load, tương tác với SPA\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eQuản lý session:\u003c\/strong\u003e login, duy trì cookie, xử lý authentication\u003c\/li\u003e\n\u003c\/ul\u003e\n\n\u003ch2\u003eCài đặt và cấu hình Playwright MCP Server\u003c\/h2\u003e\n\u003cp\u003eBướ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.\u003c\/p\u003e\n\n\u003ch3\u003eCách 1: Cấu hình trong Claude Code\u003c\/h3\u003e\n\u003cp\u003eThêm vào file cấu hình MCP của Claude Code (thường là \u003ccode\u003eclaude_desktop_config.json\u003c\/code\u003e hoặc \u003ccode\u003e.mcp.json\u003c\/code\u003e trong project):\u003c\/p\u003e\n\u003cpre\u003e\u003ccode\u003e{\n  \"mcpServers\": {\n    \"playwright\": {\n      \"command\": \"npx\",\n      \"args\": [\n        \"@anthropic-ai\/mcp-playwright\"\n      ]\n    }\n  }\n}\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch3\u003eCách 2: Cài đặt global\u003c\/h3\u003e\n\u003cpre\u003e\u003ccode\u003e# Cài đặt package\nnpm install -g @anthropic-ai\/mcp-playwright\n\n# Cài đặt browser binaries cho Playwright\nnpx playwright install chromium\u003c\/code\u003e\u003c\/pre\u003e\n\u003cp\u003eSau 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ư \u003ccode\u003ebrowser_navigate\u003c\/code\u003e, \u003ccode\u003ebrowser_click\u003c\/code\u003e, \u003ccode\u003ebrowser_snapshot\u003c\/code\u003e, \u003ccode\u003ebrowser_type\u003c\/code\u003e.\u003c\/p\u003e\n\n\u003ch3\u003eXác nhận cài đặt thành công\u003c\/h3\u003e\n\u003cp\u003eYêu cầu Claude thực hiện thao tác đơn giản để kiểm tra:\u003c\/p\u003e\n\u003cpre\u003e\u003ccode\u003eHãy mở trang https:\/\/example.com và cho tôi biết tiêu đề của trang.\u003c\/code\u003e\u003c\/pre\u003e\n\u003cp\u003eNếu Claude trả về tiêu đề trang thành công, MCP server đã hoạt động đúng.\u003c\/p\u003e\n\n\u003ch2\u003eThu thập dữ liệu cơ bản\u003c\/h2\u003e\n\u003cp\u003eBắ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.\u003c\/p\u003e\n\n\u003ch3\u003eVí dụ 1: Lấy tiêu đề bài viết từ trang chủ\u003c\/h3\u003e\n\u003cpre\u003e\u003ccode\u003eHãy mở trang https:\/\/vnexpress.net và thu thập tất cả\ntiêu đề bài viết hiển thị trên trang chủ.\n\nVới mỗi bài viết, lấy:\n- Tiêu đề\n- Link bài viết\n- Chuyên mục (nếu có)\n\nTrả kết quả dạng bảng.\u003c\/code\u003e\u003c\/pre\u003e\n\u003cp\u003eClaude 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.\u003c\/p\u003e\n\n\u003ch3\u003eVí dụ 2: Thu thập dữ liệu từ bảng biểu\u003c\/h3\u003e\n\u003cp\u003eNhiề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:\u003c\/p\u003e\n\u003cpre\u003e\u003ccode\u003eMở trang https:\/\/cafef.vn\/thi-truong-chung-khoan.chn\nvà thu thập bảng giá cổ phiếu hiện tại.\n\nLấy 20 mã đầu tiên với các cột:\n- Mã cổ phiếu\n- Giá hiện tại\n- Thay đổi (%)\n- Khối lượng giao dịch\n\nXuất kết quả dạng JSON.\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch2\u003eXây dựng Custom Scraping MCP Server\u003c\/h2\u003e\n\u003cp\u003eKhi 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.\u003c\/p\u003e\n\n\u003ch3\u003eKiến trúc Custom Scraping MCP\u003c\/h3\u003e\n\u003cp\u003eMột custom scraping MCP server thường bao gồm các thành phần:\u003c\/p\u003e\n\u003cul\u003e\n  \u003cli\u003e\n\u003cstrong\u003eTool definitions:\u003c\/strong\u003e các tool chuyên biệt cho từng nguồn dữ liệu (ví dụ: \u003ccode\u003escrape_vnexpress\u003c\/code\u003e, \u003ccode\u003escrape_cafef\u003c\/code\u003e)\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eBrowser pool:\u003c\/strong\u003e quản lý nhiều browser instance để tăng throughput\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eRate limiter:\u003c\/strong\u003e kiểm soát tốc độ request để tránh bị block\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eCache layer:\u003c\/strong\u003e lưu cache kết quả để giảm tải cho target website\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eError handler:\u003c\/strong\u003e xử lý timeout, CAPTCHA, IP block\u003c\/li\u003e\n\u003c\/ul\u003e\n\n\u003ch3\u003eTriển khai MCP Server với TypeScript\u003c\/h3\u003e\n\u003cpre\u003e\u003ccode\u003e\/\/ scraping-mcp\/src\/index.ts\nimport { McpServer } from \"@modelcontextprotocol\/sdk\/server\/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol\/sdk\/server\/stdio.js\";\nimport { chromium, Browser, Page } from \"playwright\";\nimport { z } from \"zod\";\n\nconst server = new McpServer({\n  name: \"web-scraper\",\n  version: \"1.0.0\",\n});\n\nlet browser: Browser | null = null;\n\nasync function getBrowser(): Promise\u0026lt;Browser\u0026gt; {\n  if (!browser) {\n    browser = await chromium.launch({ headless: true });\n  }\n  return browser;\n}\n\n\/\/ Rate limiting\nconst requestTimestamps: Map\u0026lt;string, number[]\u0026gt; = new Map();\n\nfunction checkRateLimit(domain: string, maxPerMinute: number = 10): boolean {\n  const now = Date.now();\n  const timestamps = requestTimestamps.get(domain) || [];\n  const recent = timestamps.filter(t =\u0026gt; now - t \u0026lt; 60000);\n  if (recent.length \u0026gt;= maxPerMinute) return false;\n  recent.push(now);\n  requestTimestamps.set(domain, recent);\n  return true;\n}\n\n\/\/ Tool: Thu thap bai viet tu trang tin\nserver.tool(\n  \"scrape_news_articles\",\n  \"Thu thap danh sach bai viet tu trang tin tuc Viet Nam\",\n  {\n    url: z.string().url().describe(\"URL trang can thu thap\"),\n    selector: z.string().describe(\"CSS selector cho bai viet\"),\n    limit: z.number().optional().default(20)\n      .describe(\"So bai viet toi da\"),\n  },\n  async ({ url, selector, limit }) =\u0026gt; {\n    const domain = new URL(url).hostname;\n    if (!checkRateLimit(domain)) {\n      return {\n        content: [{ type: \"text\",\n          text: \"Rate limit exceeded. Thu lai sau 1 phut.\" }],\n      };\n    }\n    const b = await getBrowser();\n    const page = await b.newPage();\n    try {\n      await page.goto(url, { waitUntil: \"networkidle\" });\n      const articles = await page.$$eval(\n        selector,\n        (els, max) =\u0026gt; els.slice(0, max).map(el =\u0026gt; ({\n          title: el.querySelector(\"h2, h3, .title\")?.textContent?.trim(),\n          link: el.querySelector(\"a\")?.getAttribute(\"href\"),\n          summary: el.querySelector(\"p, .description\")?.textContent?.trim(),\n        })),\n        limit\n      );\n      return {\n        content: [{ type: \"text\",\n          text: JSON.stringify(articles, null, 2) }],\n      };\n    } finally {\n      await page.close();\n    }\n  }\n);\n\nconst transport = new StdioServerTransport();\nawait server.connect(transport);\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch2\u003eXử lý phân trang (Pagination)\u003c\/h2\u003e\n\u003cp\u003eHầ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:\u003c\/p\u003e\n\n\u003ch3\u003eKiểu 1: Phân trang bằng URL parameter\u003c\/h3\u003e\n\u003cp\u003eĐây là kiểu đơn giản nhất, URL thay đổi theo số trang: \u003ccode\u003e?page=1\u003c\/code\u003e, \u003ccode\u003e?page=2\u003c\/code\u003e.\u003c\/p\u003e\n\u003cpre\u003e\u003ccode\u003eThu thập tất cả bài viết về \"AI\" từ VnExpress.\n\nBắt đầu từ trang tìm kiếm, duyệt qua tất cả các trang kết quả\n(tối đa 5 trang). Với mỗi bài viết lấy tiêu đề, link,\nngày đăng và tóm tắt.\n\nLưu ý: Chờ mỗi trang load xong trước khi chuyển sang trang tiếp.\nNghỉ 2 giây giữa các request.\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch3\u003eKiểu 2: Infinite scroll (cuộn vô hạn)\u003c\/h3\u003e\n\u003cp\u003eNhiều website hiện đại sử dụng lazy loading khi cuộn trang:\u003c\/p\u003e\n\u003cpre\u003e\u003ccode\u003e\/\/ Trong custom MCP server - xu ly infinite scroll\nserver.tool(\n  \"scrape_infinite_scroll\",\n  \"Thu thap du lieu tu trang co infinite scroll\",\n  {\n    url: z.string().url(),\n    itemSelector: z.string(),\n    maxItems: z.number().default(50),\n    scrollPauseMs: z.number().default(2000),\n  },\n  async ({ url, itemSelector, maxItems, scrollPauseMs }) =\u0026gt; {\n    const b = await getBrowser();\n    const page = await b.newPage();\n    await page.goto(url, { waitUntil: \"networkidle\" });\n\n    let previousCount = 0;\n    let items: any[] = [];\n\n    while (items.length \u0026lt; maxItems) {\n      items = await page.$$eval(itemSelector, els =\u0026gt;\n        els.map(el =\u0026gt; ({\n          text: el.textContent?.trim(),\n          href: el.querySelector(\"a\")?.href,\n        }))\n      );\n      if (items.length === previousCount) break;\n      previousCount = items.length;\n      await page.evaluate(() =\u0026gt;\n        window.scrollTo(0, document.body.scrollHeight)\n      );\n      await page.waitForTimeout(scrollPauseMs);\n    }\n\n    await page.close();\n    return {\n      content: [{ type: \"text\",\n        text: JSON.stringify(items.slice(0, maxItems), null, 2) }],\n    };\n  }\n);\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch3\u003eKiểu 3: Nút \"Xem thêm\" hoặc \"Load more\"\u003c\/h3\u003e\n\u003cp\u003eMộ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.\u003c\/p\u003e\n\n\u003ch2\u003eData Extraction Patterns\u003c\/h2\u003e\n\u003cp\u003eThu 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:\u003c\/p\u003e\n\n\u003ch3\u003ePattern 1: Structured Data Extraction\u003c\/h3\u003e\n\u003cp\u003eTrích xuất dữ liệu có cấu trúc từ các trang sản phẩm, hồ sơ doanh nghiệp:\u003c\/p\u003e\n\u003cpre\u003e\u003ccode\u003eMở trang sản phẩm tại [URL] và trích xuất thông tin\ntheo cấu trúc sau:\n\n{\n  \"ten_san_pham\": \"\",\n  \"gia\": \"\",\n  \"mo_ta\": \"\",\n  \"thong_so_ky_thuat\": {\n    \"kich_thuoc\": \"\",\n    \"trong_luong\": \"\",\n    \"chat_lieu\": \"\"\n  },\n  \"danh_gia\": {\n    \"diem_trung_binh\": \"\",\n    \"so_luong_danh_gia\": \"\"\n  },\n  \"hinh_anh\": [\"url1\", \"url2\"]\n}\n\nNếu thông tin nào không có trên trang, ghi \"N\/A\".\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch3\u003ePattern 2: Multi-page Data Aggregation\u003c\/h3\u003e\n\u003cp\u003eThu thập dữ liệu từ nhiều trang liên quan và tổng hợp lại:\u003c\/p\u003e\n\u003cpre\u003e\u003ccode\u003eThu thập thông tin giá vé máy bay Hà Nội - TP.HCM\ntừ 3 trang so sánh giá khác nhau.\n\nVới mỗi trang, lấy:\n- Hãng bay\n- Giá vé thấp nhất\n- Thời gian bay\n\nSau đó tổng hợp thành bảng so sánh và đưa ra\nđề xuất lựa chọn tốt nhất.\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch3\u003ePattern 3: Monitoring và Change Detection\u003c\/h3\u003e\n\u003cp\u003eTheo dõi thay đổi trên website theo thời gian:\u003c\/p\u003e\n\u003cpre\u003e\u003ccode\u003e\/\/ Tool theo doi thay doi gia\nserver.tool(\n  \"monitor_price\",\n  \"Theo doi gia san pham va phat hien thay doi\",\n  {\n    url: z.string().url(),\n    priceSelector: z.string(),\n    productName: z.string(),\n  },\n  async ({ url, priceSelector, productName }) =\u0026gt; {\n    const b = await getBrowser();\n    const page = await b.newPage();\n    await page.goto(url, { waitUntil: \"domcontentloaded\" });\n\n    const currentPrice = await page.$eval(\n      priceSelector,\n      el =\u0026gt; el.textContent?.trim() || \"N\/A\"\n    );\n\n    await page.close();\n    return {\n      content: [{\n        type: \"text\",\n        text: JSON.stringify({\n          product: productName,\n          price: currentPrice,\n          timestamp: new Date().toISOString(),\n          url: url,\n        }, null, 2),\n      }],\n    };\n  }\n);\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch2\u003eTuân thủ robots.txt và đạo đức thu thập dữ liệu\u003c\/h2\u003e\n\u003cp\u003eThu 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.\u003c\/p\u003e\n\n\u003ch3\u003eKiểm tra robots.txt\u003c\/h3\u003e\n\u003cp\u003eTrước khi scrape bất kỳ website nào, luôn kiểm tra file \u003ccode\u003erobots.txt\u003c\/code\u003e:\u003c\/p\u003e\n\u003cpre\u003e\u003ccode\u003e\/\/ Kiem tra robots.txt truoc khi scrape\nasync function isAllowed(url: string): Promise\u0026lt;boolean\u0026gt; {\n  const parsedUrl = new URL(url);\n  const robotsUrl = parsedUrl.origin + \"\/robots.txt\";\n\n  try {\n    const response = await fetch(robotsUrl);\n    const robotsTxt = await response.text();\n\n    \/\/ Kiem tra co bi disallow khong\n    const lines = robotsTxt.split(\"\n\");\n    const path = parsedUrl.pathname;\n\n    for (const line of lines) {\n      const trimmed = line.trim().toLowerCase();\n      if (trimmed.startsWith(\"disallow:\")) {\n        const disallowedPath = trimmed.replace(\"disallow:\", \"\").trim();\n        if (path.startsWith(disallowedPath)) {\n          return false;\n        }\n      }\n    }\n    return true;\n  } catch {\n    \/\/ Khong co robots.txt - mac dinh cho phep\n    return true;\n  }\n}\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch3\u003eNguyên tắc thu thập dữ liệu có đạo đức\u003c\/h3\u003e\n\u003cul\u003e\n  \u003cli\u003e\n\u003cstrong\u003eTôn trọng robots.txt:\u003c\/strong\u003e Nếu website cấm thu thập một đường dẫn, không truy cập đường dẫn đó\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eGiới hạn tốc độ:\u003c\/strong\u003e 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\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eXác định danh tính:\u003c\/strong\u003e Đặt User-Agent rõ ràng để chủ website biết ai đang truy cập\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eKhông thu thập dữ liệu cá nhân:\u003c\/strong\u003e Tránh thu thập email, số điện thoại, địa chỉ cá nhân trừ khi có sự đồng ý\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eLưu cache:\u003c\/strong\u003e Cache kết quả để giảm số lần truy cập lặp lại cùng một trang\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eTuân thủ Terms of Service:\u003c\/strong\u003e Đọc điều khoản sử dụng của website trước khi thu thập dữ liệu\u003c\/li\u003e\n\u003c\/ul\u003e\n\n\u003ch2\u003eRate Limiting và quản lý request\u003c\/h2\u003e\n\u003cp\u003eRate 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.\u003c\/p\u003e\n\n\u003ch3\u003eChiến lược rate limiting\u003c\/h3\u003e\n\u003cpre\u003e\u003ccode\u003e\/\/ Rate limiter nang cao voi token bucket\nclass RateLimiter {\n  private tokens: number;\n  private maxTokens: number;\n  private refillRate: number; \/\/ tokens per second\n  private lastRefill: number;\n\n  constructor(maxPerMinute: number) {\n    this.maxTokens = maxPerMinute;\n    this.tokens = maxPerMinute;\n    this.refillRate = maxPerMinute \/ 60;\n    this.lastRefill = Date.now();\n  }\n\n  async waitForToken(): Promise\u0026lt;void\u0026gt; {\n    this.refill();\n    while (this.tokens \u0026lt; 1) {\n      const waitTime = (1 - this.tokens) \/ this.refillRate * 1000;\n      await new Promise(r =\u0026gt; setTimeout(r, waitTime));\n      this.refill();\n    }\n    this.tokens -= 1;\n  }\n\n  private refill(): void {\n    const now = Date.now();\n    const elapsed = (now - this.lastRefill) \/ 1000;\n    this.tokens = Math.min(\n      this.maxTokens,\n      this.tokens + elapsed * this.refillRate\n    );\n    this.lastRefill = now;\n  }\n}\n\n\/\/ Su dung: toi da 10 request\/phut cho moi domain\nconst limiters = new Map\u0026lt;string, RateLimiter\u0026gt;();\n\nfunction getLimiter(domain: string): RateLimiter {\n  if (!limiters.has(domain)) {\n    limiters.set(domain, new RateLimiter(10));\n  }\n  return limiters.get(domain)!;\n}\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch2\u003eVí dụ thực tế: Thu thập dữ liệu website Việt Nam\u003c\/h2\u003e\n\u003cp\u003eDướ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.\u003c\/p\u003e\n\n\u003ch3\u003eThu thập tin tức từ VnExpress\u003c\/h3\u003e\n\u003cpre\u003e\u003ccode\u003eHãy thu thập 10 bài viết mới nhất từ chuyên mục\nKinh doanh trên VnExpress.\n\nVới mỗi bài viết, lấy:\n1. Tiêu đề\n2. URL bài viết\n3. Tóm tắt (description)\n4. Thời gian đăng\n5. Tác giả (nếu có)\n\nKiểm tra robots.txt trước khi bắt đầu.\nNghỉ 3 giây giữa mỗi request.\nTrả kết quả dạng JSON.\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch3\u003eThu thập dữ liệu tài chính từ CafeF\u003c\/h3\u003e\n\u003cpre\u003e\u003ccode\u003eThu thập bảng giá 10 cổ phiếu vốn hóa lớn nhất\ntrên sàn HOSE từ CafeF.\n\nLấy các thông tin:\n- Mã cổ phiếu\n- Giá tham chiếu\n- Giá trần \/ Giá sàn\n- Giá hiện tại\n- Thay đổi so với phiên trước\n- Khối lượng giao dịch\n\nTuân thủ robots.txt và rate limit.\nXuất dữ liệu dạng bảng.\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch2\u003eXử lý các tình huống phức tạp\u003c\/h2\u003e\n\n\u003ch3\u003eWebsite yêu cầu đăng nhập\u003c\/h3\u003e\n\u003cp\u003eMột số dữ liệu chỉ hiển thị sau khi đăng nhập. Playwright MCP có thể tự động điền form login:\u003c\/p\u003e\n\u003cpre\u003e\u003ccode\u003eMở trang [URL đăng nhập].\nĐiền email: [email] và mật khẩu: [password].\nClick nút đăng nhập.\nChờ trang dashboard load xong.\nSau đó truy cập [URL dữ liệu] và thu thập bảng báo cáo.\u003c\/code\u003e\u003c\/pre\u003e\n\u003cp\u003eLư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.\u003c\/p\u003e\n\n\u003ch3\u003eWebsite render bằng JavaScript (SPA)\u003c\/h3\u003e\n\u003cp\u003eNhiề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.\u003c\/p\u003e\n\n\u003ch3\u003eXử lý CAPTCHA và anti-bot\u003c\/h3\u003e\n\u003cp\u003eNếu website có cơ chế chống bot, bạn nên:\u003c\/p\u003e\n\u003cul\u003e\n  \u003cli\u003eGiảm tốc độ request xuống mức thấp hơn\u003c\/li\u003e\n  \u003cli\u003eSử dụng User-Agent thực tế\u003c\/li\u003e\n  \u003cli\u003eCân nhắc liên hệ chủ website để xin phép hoặc sử dụng API chính thức nếu có\u003c\/li\u003e\n  \u003cli\u003eKhông cố gắng bypass CAPTCHA vì vi phạm điều khoản sử dụng\u003c\/li\u003e\n\u003c\/ul\u003e\n\n\u003ch2\u003eTích hợp scraping vào workflow\u003c\/h2\u003e\n\u003cp\u003eThu 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ế:\u003c\/p\u003e\n\n\u003ch3\u003eWorkflow 1: Nghiên cứu thị trường tự động\u003c\/h3\u003e\n\u003cpre\u003e\u003ccode\u003eThực hiện nghiên cứu thị trường cho ngành thương mại điện tử\ntại Việt Nam:\n\n1. Thu thập top 10 sản phẩm bán chạy từ 3 sàn TMDT\n2. So sánh giá giữa các sàn\n3. Phân tích xu hướng giá (nếu có dữ liệu lịch sử)\n4. Tổng hợp thành báo cáo với biểu đồ so sánh\n\nTuân thủ rate limiting và robots.txt cho mỗi website.\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch3\u003eWorkflow 2: Theo dõi đối thủ cạnh tranh\u003c\/h3\u003e\n\u003cpre\u003e\u003ccode\u003eTheo dõi hoạt động content marketing của đối thủ:\n\n1. Thu thập 5 bài blog mới nhất từ website đối thủ [URL]\n2. Phân tích chủ đề, từ khóa chính của mỗi bài\n3. So sánh với chiến lược content hiện tại của chúng tôi\n4. Đề xuất các chủ đề chúng tôi nên viết\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch2\u003eTối ưu hiệu suất scraping\u003c\/h2\u003e\n\u003cp\u003eKhi thu thập dữ liệu ở quy mô lớn, hiệu suất trở thành yếu tố quan trọng:\u003c\/p\u003e\n\u003cul\u003e\n  \u003cli\u003e\n\u003cstrong\u003eReuse browser context:\u003c\/strong\u003e 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\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eBlock tài nguyên không cần thiết:\u003c\/strong\u003e Chặn hình ảnh, CSS, font để trang load nhanh hơn khi chỉ cần dữ liệu text\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eSử dụng cache:\u003c\/strong\u003e 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\u003c\/li\u003e\n  \u003cli\u003e\n\u003cstrong\u003eParallel scraping:\u003c\/strong\u003e Thu thập nhiều trang đồng thời nhưng vẫn giữ rate limit cho mỗi domain\u003c\/li\u003e\n\u003c\/ul\u003e\n\u003cpre\u003e\u003ccode\u003e\/\/ Block tai nguyen khong can thiet de tang toc\nconst page = await browser.newPage();\nawait page.route(\"**\/*.{png,jpg,jpeg,gif,svg,css,woff,woff2}\", route =\u0026gt;\n  route.abort()\n);\nawait page.goto(url, { waitUntil: \"domcontentloaded\" });\u003c\/code\u003e\u003c\/pre\u003e\n\n\u003ch2\u003eBước tiếp theo\u003c\/h2\u003e\n\u003cp\u003eBạ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 \u003ca href=\"\/en\/collections\/ung-dung\"\u003eThư viện Ứng dụng Claude\u003c\/a\u003e.\u003c\/p\u003e\n","brand":"Minh Tuấn","offers":[{"title":"Default Title","offer_id":47730161287380,"sku":null,"price":0.0,"currency_code":"VND","in_stock":true}],"thumbnail_url":"\/\/cdn.shopify.com\/s\/files\/1\/0821\/0264\/9044\/files\/mcp-server-cho-web-scraping-claude-thu-th_p-d_-li_u-t_-website.jpg?v=1774718101","url":"https:\/\/claude.vn\/en\/products\/mcp-server-cho-web-scraping-claude-thu-th%e1%ba%adp-d%e1%bb%af-li%e1%bb%87u-t%e1%bb%ab-website","provider":"CLAUDE.VN","version":"1.0","type":"link"}