إنتقل إلى المحتوى الرئيسي

كشط الويب في Cursor: دليل شامل

كشط الويب في Cursor

كشط الويب هو عملية استخراج البيانات من المواقع برمجياً. يُشغّل مراقبة الأسعار، وتوليد العملاء المحتملين، وتجميع الأخبار، وأبحاث السوق، وجمع البيانات للتعلم الآلي. يقدم نظام Node.js البيئي ثلاث أدوات مهيمنة: Puppeteer لأتمتة Chrome بلا رأس، و Playwright لأتمتة المتصفحات المتقاطعة، و Cheerio لتحليل HTML السريع. يُعد Cursor، بمساعد الذكاء الاصطناعي المدمج وخادم لغة TypeScript المدمج، محرراً ممتازاً لمشاريع الكشط -- فهو يوفر IntelliSense لواجهات برمجة المتصفح، ويُكمل تلقائياً سلاسل المُحددات، ويمكنه إنشاء منطق الاستخراج من أوصاف صفحات الويب باللغة الطبيعية.

يغطي هذا الدليل سير عمل كشط الويب الكامل في Cursor: اختيار الأداة المناسبة، إعداد Puppeteer و Playwright، تحليل HTML مع Cheerio، تنفيذ أنماط الاستخراج، تخطي تدابير مكافحة الروبوتات، والاستفادة من الاستخراج بمساعدة الذكاء الاصطناعي.

اختيار الأداة المناسبة​

لكل أداة كشط نقاط قوة متميزة. فهم متى تستخدم كل واحدة هو أساس استراتيجية كشط فعالة.

الأداةالأفضل لـالمتصفحالسرعةالتعقيد
CheerioHTML ثابت، تحليل سريعلا شيءسريع جداًمنخفض
Puppeteerصفحات JS ديناميكية معروضةChrome/Chromiumمتوسطةمتوسطة
Playwrightمتصفحات متقاطعة، SPAs حديثةChrome، Firefox، WebKitمتوسطةمتوسطة-عالية
Puppeteer + Cheerioنهج هجينChromeسريعمتوسطة
تلميح

اطلب من Cursor: "I need to scrape a website. The data I need is rendered by JavaScript after the page loads. Which tool should I use and why?" سيوصي Cursor بـ Puppeteer أو Playwright ويشرح لماذا لا يستطيع Cheerio وحده التقاط المحتوى المُعرض ديناميكياً.

إعداد مشروع كشط في Cursor​

تهيئة المشروع​

mkdir web-scraper && cd web-scraper
npm init -y
npm install typescript tsx @types/node --save-dev
npx tsc --init
تلميح

استخدم tsx لتشغيل سكربتات كشط TypeScript مباشرة دون خطوة بناء منفصلة. شغّل npx tsx scraper.ts من الطرفية المدمجة في Cursor (Ctrl+`) لاختبار السكربتات فوراً.

تثبيت Puppeteer​

npm install puppeteer

يُنزّل Puppeteer نسخة Chromium مُجمعة افتراضياً. تحقق من التثبيت:

// test-puppeteer.ts
import puppeteer from 'puppeteer';

const browser = await puppeteer.launch({ headless: true });
const page = await browser.newPage();
await page.goto('https://example.com');
console.log(await page.title());
await browser.close();

تثبيت Playwright​

npm install playwright
npx playwright install # Downloads browser binaries

تحقق:

// test-playwright.ts
import { chromium } from 'playwright';

const browser = await chromium.launch({ headless: true });
const page = await browser.newPage();
await page.goto('https://example.com');
console.log(await page.title());
await browser.close();

تثبيت Cheerio​

npm install cheerio

يُحلل Cheerio سلاسل HTML دون متصفح، مما يجعله الخيار الأسرع للصفحات الثابتة:

// test-cheerio.ts
import * as cheerio from 'cheerio';

const html = '<div class="item"><h2>Title</h2><span class="price">$9.99</span></div>';
const $ = cheerio.load(html);
console.log($('.item h2').text()); // "Title"
console.log($('.item .price').text()); // "$9.99"
warning

لا يستطيع Cheerio تنفيذ JavaScript. إذا كانت الصفحة المستهدفة تعرض المحتوى ديناميكياً عبر JS من جانب العميل (React، Vue، إلخ)، سيرى Cheerio الهيكل العظمي HTML الأولي فقط. استخدم Puppeteer أو Playwright لهذه المواقع.

الكشط مع Puppeteer​

يوفر Puppeteer واجهة برمجة عالية المستوى للتحكم في Chrome أو Chromium. إنه مثالي لكشط الصفحات المُعرضة بـ JavaScript، ومعالجة تسجيلات الدخول، والتفاعل مع عناصر الصفحة.

كشط الصفحات الأساسي​

// scrape-products-puppeteer.ts
import puppeteer from 'puppeteer';
import * as cheerio from 'cheerio';

interface Product {
name: string;
price: string;
rating: string;
url: string;
}

async function scrapeProducts(): Promise<Product[]> {
const browser = await puppeteer.launch({
headless: true,
args: ['--no-sandbox', '--disable-setuid-sandbox'],
});

try {
const page = await browser.newPage();

// Set a realistic viewport
await page.setViewport({ width: 1920, height: 1080 });

// Set a realistic user agent
await page.setUserAgent(
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36'
);

// Navigate and wait for the product grid to render
await page.goto('https://example-store.com/products', {
waitUntil: 'networkidle2',
timeout: 30000,
});

// Wait for the product cards to appear
await page.waitForSelector('.product-card', { timeout: 10000 });

// Scroll to trigger lazy-loaded content
await autoScroll(page);

// Extract data from the page
const products = await page.evaluate(() =>
Array.from(document.querySelectorAll('.product-card')).map((card) => ({
name: card.querySelector('.product-name')?.textContent?.trim() ?? '',
price: card.querySelector('.product-price')?.textContent?.trim() ?? '',
rating: card.querySelector('.product-rating')?.textContent?.trim() ?? '',
url: card.querySelector('a')?.href ?? '',
}))
);

return products;
} finally {
await browser.close();
}
}

async function autoScroll(page: puppeteer.Page) {
await page.evaluate(async () => {
await new Promise<void>((resolve) => {
let totalHeight = 0;
const distance = 100;
const timer = setInterval(() => {
window.scrollBy(0, distance);
totalHeight += distance;
if (totalHeight >= document.body.scrollHeight) {
clearInterval(timer);
resolve();
}
}, 100);
});
});
}

const products = await scrapeProducts();
console.log(`Scraped ${products.length} products`);
console.log(products[0]);
تلميح

دالة autoScroll ضرورية لصفحات التمرير اللانهائي. العديد من المواقع تُحمّل المنتجات كسولاً أثناء التمرير. بدون التمرير، يلتقط Puppeteer العناصر المُحمّلة أولياً فقط.

معالجة ترقيم الصفحات​

async function scrapeAllPages(baseUrl: string): Promise<Product[]> {
const browser = await puppeteer.launch({ headless: true });
const page = await browser.newPage();
const allProducts: Product[] = [];
let currentPage = 1;
let hasNextPage = true;

try {
while (hasNextPage) {
await page.goto(`${baseUrl}?page=${currentPage}`, { waitUntil: 'networkidle2' });
await page.waitForSelector('.product-card', { timeout: 10000 });

const products = await page.evaluate(() =>
Array.from(document.querySelectorAll('.product-card')).map((card) => ({
name: card.querySelector('.product-name')?.textContent?.trim() ?? '',
price: card.querySelector('.product-price')?.textContent?.trim() ?? '',
rating: card.querySelector('.product-rating')?.textContent?.trim() ?? '',
url: card.querySelector('a')?.href ?? '',
}))
);
allProducts.push(...products);

hasNextPage = await page.evaluate(
() => document.querySelector('.pagination .next:not(.disabled)') !== null
);
currentPage++;
await new Promise((r) => setTimeout(r, 2000));
}
} finally {
await browser.close();
}
return allProducts;
}
warning

أضف دائماً تأخيرات بين طلبات الصفحات. الكشط السريع جداً قد يُطلق تحديد المعدل، أو حظر IP، أو تحديات CAPTCHA. تأخير 1-3 ثوانٍ بين الطلبات نقطة بداية جيدة. للزحف الأكبر، استخدم خدمة تدوير بروكسي.

معالجة الصفحات المحمية بتسجيل الدخول​

async function scrapeLoggedInPage(email: string, password: string) {
const browser = await puppeteer.launch({ headless: false }); // Show browser for debugging
const page = await browser.newPage();

try {
await page.goto('https://example.com/login', { waitUntil: 'networkidle2' });
await page.type('#email', email, { delay: 50 });
await page.type('#password', password, { delay: 50 });

await Promise.all([
page.waitForNavigation({ waitUntil: 'networkidle2' }),
page.click('#submit'),
]);

// Verify login success
const isLoggedIn = await page.evaluate(() => !document.querySelector('.login-error'));
if (!isLoggedIn) throw new Error('Login failed');

// Scrape the protected page
await page.goto('https://example.com/dashboard', { waitUntil: 'networkidle2' });
return await page.evaluate(() => document.querySelector('.dashboard-data')?.textContent);
} finally {
await browser.close();
}
}

الكشط مع Playwright​

Playwright هي أداة أتمتة متصفحات متقاطعة من Microsoft. تدعم Chromium و Firefox و WebKit، ولديها واجهة برمجة أكثر حداثة من Puppeteer.

كشط Playwright الأساسي​

// scrape-playwright.ts
import { chromium } from 'playwright';

interface Article {
title: string;
author: string;
date: string;
summary: string;
url: string;
}

async function scrapeArticles(): Promise<Article[]> {
const browser = await chromium.launch({ headless: true });
const context = await browser.newContext({
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
viewport: { width: 1920, height: 1080 },
});

const page = await context.newPage();

try {
await page.goto('https://example-blog.com', {
waitUntil: 'domcontentloaded',
timeout: 30000,
});

// Wait for articles to load
await page.waitForSelector('.article-card', { timeout: 10000 });

const articles = await page.$$eval('.article-card', (cards) =>
cards.map((card) => ({
title: card.querySelector('.article-title')?.textContent?.trim() ?? '',
author: card.querySelector('.article-author')?.textContent?.trim() ?? '',
date: card.querySelector('.article-date')?.textContent?.trim() ?? '',
summary: card.querySelector('.article-summary')?.textContent?.trim() ?? '',
url: card.querySelector('a')?.href ?? '',
}))
);

return articles;
} finally {
await browser.close();
}
}

كشط SPAs مع اعتراض الشبكة​

يستطيع Playwright اعتراض طلبات الشبكة لالتقاط استجابات API مباشرة، مما يجنب الحاجة لتحليل HTML المُعرض:

async function scrapeViaAPI() {
const browser = await chromium.launch({ headless: true });
const context = await browser.newContext();
const page = await context.newPage();

const apiResponses: any[] = [];

// Intercept API responses
page.on('response', async (response) => {
if (response.url().includes('/api/products') && response.status() === 200) {
const json = await response.json();
apiResponses.push(json);
}
});

await page.goto('https://example-store.com', { waitUntil: 'networkidle' });

await browser.close();

// Now you have the raw JSON data, no HTML parsing needed
return apiResponses;
}
تلميح

اعتراض الشبكة هو أكثر طريقة موثوقة لكشط SPAs الحديثة. بدلاً من تحليل HTML المُعرض، تلتقط استجابات JSON API التي تجلبها الصفحة. اطلب من Cursor: "Intercept the XHR requests on this page and extract the product data from the API response." سيقوم Cursor بإنشاء مستمع استجابة Playwright.

تحليل HTML مع Cheerio​

يوفر Cheerio واجهة شبيهة بـ jQuery لتحليل سلاسل HTML. إنه أسرع 10-100 مرة من الكشط القائم على المتصفح لأنه لا يعرض الصفحات أو ينفذ JavaScript.

الجلب والتحليل​

// scrape-cheerio.ts
import * as cheerio from 'cheerio';

interface Book {
title: string;
price: number;
availability: string;
rating: number;
}

async function scrapeBooks(): Promise<Book[]> {
const response = await fetch('https://books.toscrape.com/', {
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
},
});

const html = await response.text();
const $ = cheerio.load(html);

const books: Book[] = [];

$('.product_pod').each((_, element) => {
const $el = $(element);
const title = $el.find('h3 a').attr('title') ?? '';
const priceText = $el.find('.price_color').text();
const price = parseFloat(priceText.replace(/[^0-9.]/g, ''));
const availability = $el.find('.instock').text().trim();

// Parse rating from class name (e.g., "star-rating Three" -> 3)
const ratingClass = $el.find('.star-rating').attr('class') ?? '';
const ratingMap: Record<string, number> = {
One: 1, Two: 2, Three: 3, Four: 4, Five: 5,
};
const ratingWord = ratingClass.split(' ')[1];
const rating = ratingMap[ratingWord] ?? 0;

books.push({ title, price, availability, rating });
});

return books;
}

أنماط مُحددات Cheerio​

يستخدم Cheerio مُحددات شبيهة بـ jQuery: $('.class') للفئات، و $('#id') للمعرفات، و $('a[href*="/product/"]') لمطابقة السمات، ودوال مثل .parent() و .siblings() و .children() و .text() و .html() و .attr() لاجتياز DOM والاستخراج.

تلميح

إذا كنت تعرف مُحددات jQuery، فأنت تعرف Cheerio. اطلب من Cursor: "Write a Cheerio selector chain to extract all product names, prices, and image URLs from this HTML structure" والصق HTML. سيقوم Cursor بإنشاء المُحددات الصحيحة.

أنماط استخراج البيانات​

استخراج بيانات منظمة من الجداول​

async function scrapeTable(): Promise<Record<string, string>[]> {
const response = await fetch('https://example.com/data-table');
const html = await response.text();
const $ = cheerio.load(html);

// Get headers
const headers: string[] = [];
$('table thead th').each((_, el) => {
headers.push($(el).text().trim().toLowerCase().replace(/\s+/g, '_'));
});

// Extract rows
const rows: Record<string, string>[] = [];
$('table tbody tr').each((_, rowEl) => {
const cells: string[] = [];
$(rowEl).find('td').each((_, cellEl) => {
cells.push($(cellEl).text().trim());
});

const row: Record<string, string> = {};
headers.forEach((header, index) => {
row[header] = cells[index] ?? '';
});
rows.push(row);
});

return rows;
}

استخراج بيانات JSON-LD​

تُدمج العديد من المواقع بيانات منظمة بتنسيق JSON-LD. هذه هي طريقة الاستخراج الأكثر موثوقية عند توفرها:

import * as cheerio from 'cheerio';

async function scrapeJsonLd(url: string) {
const response = await fetch(url);
const html = await response.text();
const $ = cheerio.load(html);

const jsonLdData: any[] = [];

$('script[type="application/ld+json"]').each((_, el) => {
try {
const data = JSON.parse($(el).contents().text());
if (Array.isArray(data)) {
jsonLdData.push(...data);
} else {
jsonLdData.push(data);
}
} catch (e) {
console.warn('Failed to parse JSON-LD:', e);
}
});

return jsonLdData;
}

// Usage
const structuredData = await scrapeJsonLd('https://example.com/product/123');
// structuredData[0] might contain: { "@type": "Product", "name": "...", "offers": { "price": "..." } }
تلميح

JSON-LD هو أسهل وأكثر طريقة موثوقية لاستخراج البيانات المنظمة. اطلب من Cursor: "Check if this page has JSON-LD structured data and extract the product information from it." إذا كان الموقع يستخدم ترميز schema.org، سيقوم Cursor بتحليله دون مُحددات CSS هشة.

حفظ البيانات المستخرجة​

import { writeFileSync } from 'fs';

// Save to JSON
function saveToJson(data: any[], filename: string) {
writeFileSync(filename, JSON.stringify(data, null, 2));
console.log(`Saved ${data.length} records to ${filename}`);
}

// Save to CSV
function saveToCsv(data: Record<string, any>[], filename: string) {
if (data.length === 0) return;
const headers = Object.keys(data[0]);
const csvLines = [
headers.join(','),
...data.map((row) =>
headers.map((h) => `"${String(row[h] ?? '').replace(/"/g, '""')}"`).join(',')
),
];
writeFileSync(filename, csvLines.join('\n'));
}

تقنيات تخطي مكافحة الروبوتات​

تنشر المواقع الحديثة حماية مكافحة الروبوتات (Cloudflare، reCAPTCHA، Datadome، PerimeterX) لاكتشاف وحظر الكشط الآلي. إليك استراتيجيات لتخطي الحمايات الشائعة.

تعيين ترويسات واقعية​

const headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'en-US,en;q=0.9',
'Accept-Encoding': 'gzip, deflate, br',
'Connection': 'keep-alive',
'Upgrade-Insecure-Requests': '1',
};

const response = await fetch(url, { headers });

استخدام Puppeteer-Stealth​

npm install puppeteer-extra puppeteer-extra-plugin-stealth
import puppeteer from 'puppeteer-extra';
import StealthPlugin from 'puppeteer-extra-plugin-stealth';

puppeteer.use(StealthPlugin());

const browser = await puppeteer.launch({ headless: true });
const page = await browser.newPage();

// The stealth plugin patches common detection vectors:
// - navigator.webdriver = false
// - chrome.runtime object
// - permissions API
// - plugins array
// - languages array
// - WebGL vendor/renderer

await page.goto('https://bot-protected-site.com');
warning

إضافات التخفي تساعد لكنها ليست حلاً سحرياً. خدمات مكافحة الروبوتات المتطورة مثل Cloudflare Turnstile تستخدم بصمات TLS، وتحليل سلوكي، وآليات تحدي-استجابة تتجاوز فحوصات خصائص المتصفح البسيطة. لكشط الإنتاج للمواقع المحمية بشدة، فكر في خدمات البروكسي التجارية مع حل CAPTCHA مدمج.

استخدام البروكسيات​

// Puppeteer with proxy
const browser = await puppeteer.launch({
headless: true,
args: [
`--proxy-server=http://${proxyHost}:${proxyPort}`,
'--no-sandbox',
],
});

await page.authenticate({
username: proxyUsername,
password: proxyPassword,
});

// Playwright with proxy
const browser = await chromium.launch({
headless: true,
proxy: {
server: `http://${proxyHost}:${proxyPort}`,
username: proxyUsername,
password: proxyPassword,
},
});

تدوير User Agents​

const userAgents = [
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36',
'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:126.0) Gecko/20100101 Firefox/126.0',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.5 Safari/605.1.15',
];

const randomUA = userAgents[Math.floor(Math.random() * userAgents.length)];
await page.setUserAgent(randomUA);

معالجة التأخيرات والسلوك الشبيه بالبشر​

async function humanLikeScroll(page: puppeteer.Page) {
const totalHeight = await page.evaluate(() => document.body.scrollHeight);
let scrolled = 0;
while (scrolled < totalHeight) {
const scrollAmount = Math.floor(Math.random() * 200) + 100;
await page.evaluate((y) => window.scrollBy(0, y), scrollAmount);
scrolled += scrollAmount;
await new Promise((r) => setTimeout(r, Math.random() * 1500 + 500));
}
}

async function randomMouseMovement(page: puppeteer.Page) {
await page.mouse.move(Math.random() * 800, Math.random() * 600);
await new Promise((r) => setTimeout(r, Math.random() * 500 + 200));
await page.mouse.move(Math.random() * 800, Math.random() * 600);
}
تلميح

اطلب من Cursor: "Make my Puppeteer scraper behave more like a human. Add random mouse movements, variable scroll speeds, and random delays between actions." سيقوم Cursor بإنشاء دوال محاكاة السلوك ودمجها في تدفق الكشط الخاص بك.

الاستخراج بمساعدة الذكاء الاصطناعي في Cursor​

يمكن لمساعد الذكاء الاصطناعي في Cursor إنشاء منطق الكشط من أوصاف الصفحات، وتحديد المُحددات من مقتطفات HTML، وتصحيح الاستخراج الفاشل.

إنشاء المُحددات من HTML​

افتح Cursor Chat (Ctrl+L) والصق مقتطف HTML:

Here is a product card's HTML structure:

<div class="product-item" data-id="123">
<img src="/img/product.jpg" alt="Product Name" />
<h3 class="product-title">Product Name</h3>
<span class="price-current">$29.99</span>
<span class="price-original">$49.99</span>
<span class="rating" data-rating="4.5">4.5 stars</span>
<span class="stock">In Stock</span>
</div>

Generate a Cheerio extraction function with a typed interface.
Include: productId, name, currentPrice, originalPrice, rating, stockStatus, imageUrl.

سيقوم Cursor بإنشاء:

interface ScrapedProduct {
productId: string;
name: string;
currentPrice: number;
originalPrice: number;
rating: number;
stockStatus: string;
imageUrl: string;
}

function extractProduct($: cheerio.CheerioAPI, element: any): ScrapedProduct {
const $el = $(element);
const parsePrice = (sel: string) =>
parseFloat($el.find(sel).text().replace(/[^0-9.]/g, '')) || 0;

return {
productId: $el.attr('data-id') ?? '',
name: $el.find('.product-title').text().trim(),
currentPrice: parsePrice('.price-current'),
originalPrice: parsePrice('.price-original'),
rating: parseFloat($el.find('.rating').attr('data-rating') ?? '0') || 0,
stockStatus: $el.find('.stock').text().trim(),
imageUrl: $el.find('img').attr('src') ?? '',
};
}
تلميح

عند طلب إنشاء مُحددات من Cursor، الصق دائماً عينة HTML تمثيلية. هذا يضمن أن المُحددات تطابق بنية DOM الفعلية بدلاً من تخمين. سيحدد Cursor أيضاً الحالات الحدية مثل الحقول الاختيارية المفقودة ويضيف بدائل.

التصحيح بمساعدة الذكاء الاصطناعي​

عند يُرجع كاشطك نتائج فارغة، اطلب من Cursor المساعدة:

My Puppeteer scraper is returning an empty array. The selector
".product-card" should match elements but page.evaluate returns [].
Here is my code. The page loads successfully and I can see the elements
in the browser. What could be wrong?

سيحدد Cursor المشاكل الشائعة:

  1. المُحدد قد يكون داخل shadow DOM.
  2. المحتوى قد يكون في iframe.
  3. الصفحة قد تستخدم مُحدداً مختلفاً بعد إعادة تصميم حديثة.
  4. خيار waitUntil قد لا يكون كافياً.
warning

المواقع تغير بنية HTML بشكل متكرر. الكاشط الذي يعمل اليوم قد يتعطل غداً. ابنِ كاشطاتك بشكل دفاعي: استخدم مُحددات بديلة متعددة، سجل إخفاقات الاستخراج، وأعد مراقبة لاكتشاف توقف المُحددات عن المطابقة.

أفضل الممارسات والأخلاقيات​

احترام robots.txt​

async function checkRobotsTxt(url: string): Promise<boolean> {
const robotsUrl = `${new URL(url).origin}/robots.txt`;
try {
const robotsTxt = await (await fetch(robotsUrl)).text();
const path = new URL(url).pathname;
for (const line of robotsTxt.split('\n')) {
if (line.trim().toLowerCase().startsWith('disallow:')) {
const disallowed = line.split(':')[1].trim();
if (disallowed && path.startsWith(disallowed)) return false;
}
}
return true;
} catch {
return true; // If robots.txt doesn't exist, assume allowed
}
}
warning

تحقق دائماً من robots.txt قبل الكشط. إنه البروتوكول القياسي للمواقع لتعريف الصفحات التي يمكن كشطها. انتهاك robots.txt قد يؤدي إلى حظر IP ومشاكل قانونية. استخدم دالة checkRobotsTxt أعلاه قبل أي عملية كشط.

تحديد المعدل​

async function rateLimitedDelay() {
const delay = Math.random() * 2000 + 1000; // 1-3 second delay
await new Promise((r) => setTimeout(r, delay));
}

// Usage: call between each page request
await rateLimitedDelay();

الخلاصة​

يجمع كشط الويب في Cursor بين قوة Puppeteer و Playwright و Cheerio مع إنشاء الكود بمساعدة الذكاء الاصطناعي. Cheerio هو خيارك لتحليل HTML الثابت السريع، ويتعامل Puppeteer مع الصفحات المُعرضة بـ JavaScript مع أتمتة Chrome، بينما يقدم Playwright دعم المتصفحات المتقاطعة واعتراض الشبكة لـ SPAs الحديثة. تقنيات مكافحة الروبوتات -- إضافات التخفي، وتدوير البروكسي، والسلوك الشبيه بالبشر -- تساعدك على الوصول للمواقع المحمية، بينما يُنشئ مساعد الذكاء الاصطناعي في Cursor المُحددات من مقتطفات HTML، ويُصحح الاستخراج الفاشل، ويكتب خطوط أنابيب كشط كاملة من أوصاف اللغة الطبيعية. ابدأ باختيار الأداة المناسبة لهدفك، ابنِ بشكل دفاعي مع مُحددات بديلة وتحديد المعدل، احترم دائماً robots.txt، ودع Cursor يُنشأ منطق الاستخراج لتركز على جودة البيانات وموثوقية خط الأنابيب.