Puppeteer و Playwright هما أدوات شائعة لأتمتة المتصفح واستخراج البيانات من الويب. عند العمل مع كميات كبيرة من الطلبات أو استخراج البيانات من المواقع المحمية، يصبح استخدام البروكسي أمرًا بالغ الأهمية لتجنب حظر IP. في هذا الدليل، سنستعرض جميع طرق دمج البروكسي في كلا الأداتين، من الإعداد الأساسي إلى السيناريوهات المتقدمة مع تدوير ومعالجة الأخطاء.
أساسيات عمل البروكسي في المتصفحات بدون واجهة مستخدم
Puppeteer و Playwright يديران متصفحات حقيقية (Chromium، Firefox، WebKit) عبر بروتوكول DevTools. هذا يعني أن البروكسي يتم إعداده على مستوى بدء تشغيل المتصفح، وليس على مستوى الطلبات الفردية. كلا الأداتين تدعمان بروكسي HTTP و HTTPS و SOCKS5، لكن لديهما واجهات برمجة تطبيقات مختلفة لإعدادها.
الاختلافات الرئيسية عن مكتبات HTTP العادية (axios، fetch):
- يتم تعيين البروكسي عند بدء تشغيل المتصفح - لا يمكن تغيير البروكسي أثناء جلسة المتصفح الواحدة
- دعم JavaScript والتصيير - يتم تطبيق البروكسي على جميع موارد الصفحة (الصور، السكربتات، XHR)
- معالجة تلقائية لإعادة التوجيه وملفات تعريف الارتباط - يتصرف المتصفح كما لو كان مستخدمًا حقيقيًا
- التعرف على بصمة المتصفح - حتى مع البروكسي، يمكن للمواقع تحديد الأتمتة من خلال خصائص المتصفح
مهم: بالنسبة للمهام التي تتطلب تغيير IP بشكل متكرر (استخراج آلاف الصفحات، التسجيل الجماعي)، من الأكثر فعالية استخدام بروكسي سكنية مع تدوير - فهي تسمح بتغيير IP مع كل طلب دون إعادة تشغيل المتصفح.
إعداد البروكسي في Puppeteer
Puppeteer هي مكتبة من Google لإدارة Chrome/Chromium. يتم إعداد البروكسي عبر معلمات بدء تشغيل المتصفح باستخدام العلم --proxy-server.
الإعداد الأساسي لبروكسي HTTP/HTTPS
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({
headless: true,
args: [
'--proxy-server=http://proxy.example.com:8080'
]
});
const page = await browser.newPage();
// التحقق من عنوان IP
await page.goto('https://api.ipify.org?format=json');
const content = await page.content();
console.log('عنوان IP الحالي:', content);
await browser.close();
})();
هذا الكود يقوم بتشغيل المتصفح عبر خادم البروكسي. ستتم معالجة جميع طلبات HTTP و HTTPS عبر البروكسي المحدد. يتم استخدام خدمة ipify للتحقق من العمل، والتي تعيد عنوان IP الخارجي.
إعداد بروكسي SOCKS5
const browser = await puppeteer.launch({
headless: true,
args: [
'--proxy-server=socks5://proxy.example.com:1080'
]
});
// باقي الكود مماثل
تعمل بروكسي SOCKS5 على مستوى أدنى وتدعم حركة مرور UDP، مما قد يكون مفيدًا لبعض تطبيقات الويب. التركيب مماثل لبروكسي HTTP، فقط يتغير البروتوكول في عنوان URL.
استخدام البروكسي لنطاقات معينة
const browser = await puppeteer.launch({
args: [
'--proxy-server=http://proxy1.example.com:8080',
'--proxy-bypass-list=localhost;127.0.0.1;*.internal.com'
]
});
// الطلبات المحلية والطلبات إلى *.internal.com ستذهب مباشرة
// جميع الطلبات الأخرى - عبر البروكسي
العلم --proxy-bypass-list يسمح باستبعاد نطاقات معينة من البروكسي. هذا مفيد عندما تحتاج إلى دمج الطلبات المباشرة والموجهة عبر البروكسي.
إعداد البروكسي في Playwright
Playwright هي مكتبة أكثر حداثة من Microsoft، تدعم Chromium و Firefox و WebKit. يتم إعداد البروكسي عبر كائن التكوين، مما يجعل واجهة برمجة التطبيقات أكثر وضوحًا ونوعًا.
الإعداد الأساسي للبروكسي
const { chromium } = require('playwright');
(async () => {
const browser = await chromium.launch({
proxy: {
server: 'http://proxy.example.com:8080'
}
});
const context = await browser.newContext();
const page = await context.newPage();
await page.goto('https://api.ipify.org?format=json');
const ip = await page.textContent('body');
console.log('IP عبر البروكسي:', ip);
await browser.close();
})();
يستخدم Playwright كائن proxy بدلاً من معلمات سطر الأوامر. هذا يوفر نوعًا أفضل في TypeScript وكودًا أكثر نظافة.
إعداد البروكسي على مستوى السياق
const browser = await chromium.launch();
// السياق 1 - مع البروكسي
const context1 = await browser.newContext({
proxy: {
server: 'http://proxy1.example.com:8080'
}
});
// السياق 2 - مع بروكسي آخر
const context2 = await browser.newContext({
proxy: {
server: 'http://proxy2.example.com:8080'
}
});
const page1 = await context1.newPage();
const page2 = await context2.newPage();
// كل صفحة تستخدم بروكسيها الخاص!
واحدة من المزايا الرئيسية لـ Playwright هي القدرة على إنشاء سياقات متصفح متعددة مع بروكسيات مختلفة ضمن عملية واحدة. هذا يوفر الموارد عند العمل مع العديد من عناوين IP.
استبعاد النطاقات من البروكسي
const browser = await chromium.launch({
proxy: {
server: 'http://proxy.example.com:8080',
bypass: 'localhost,127.0.0.1,*.internal.com'
}
});
// الطلبات إلى localhost و *.internal.com ستذهب مباشرة
المصادقة باستخدام اسم المستخدم وكلمة المرور
تتطلب معظم البروكسي التجارية المصادقة. يدعم كلا الأداتين التفويض، لكن يتم تنفيذهما بشكل مختلف.
المصادقة في Puppeteer
const browser = await puppeteer.launch({
args: ['--proxy-server=http://proxy.example.com:8080']
});
const page = await browser.newPage();
// تعيين بيانات الاعتماد للبروكسي
await page.authenticate({
username: 'your_username',
password: 'your_password'
});
await page.goto('https://httpbin.org/ip');
const content = await page.content();
console.log(content);
تقوم الطريقة page.authenticate() بتعيين بيانات الاعتماد لجميع الطلبات اللاحقة على هذه الصفحة. من المهم استدعاؤها قبل أول page.goto().
المصادقة في Playwright
const browser = await chromium.launch({
proxy: {
server: 'http://proxy.example.com:8080',
username: 'your_username',
password: 'your_password'
}
});
const page = await browser.newPage();
await page.goto('https://httpbin.org/ip');
يسمح Playwright بتحديد بيانات الاعتماد مباشرة في كائن تكوين البروكسي - وهذا أكثر ملاءمة وأمانًا، حيث لا يتطلب استدعاءات إضافية للطرق.
طريقة بديلة: بيانات الاعتماد في URL
// يعمل في كلا الإطارين
const proxyUrl = 'http://username:password@proxy.example.com:8080';
// Puppeteer
const browser = await puppeteer.launch({
args: [`--proxy-server=${proxyUrl}`]
});
// Playwright
const browser = await chromium.launch({
proxy: { server: proxyUrl }
});
تعمل هذه الطريقة، لكنها غير موصى بها للإنتاج - قد تظهر بيانات الاعتماد في السجلات. استخدم متغيرات البيئة لتخزين البيانات الحساسة.
نصيحة: عند العمل مع استخراج البيانات من المواقع التجارية، نوصي باستخدام بروكسي سكنية - فهي تحتوي على عناوين IP حقيقية لمستخدمي المنازل وتتعرض لحظر أقل من أنظمة مكافحة الروبوتات.
تدوير البروكسي وإدارة مجموعة IP
للاستخراج على نطاق واسع، من الضروري تغيير عناوين IP بانتظام. نظرًا لأن البروكسي يتم تعيينه عند بدء تشغيل المتصفح، فإن التدوير يتطلب إعادة تشغيل جلسة المتصفح.
تدوير بسيط باستخدام مصفوفة من البروكسي (Puppeteer)
const puppeteer = require('puppeteer');
const proxyList = [
'http://user1:pass1@proxy1.example.com:8080',
'http://user2:pass2@proxy2.example.com:8080',
'http://user3:pass3@proxy3.example.com:8080'
];
async function scrapeWithRotation(urls) {
for (let i = 0; i < urls.length; i++) {
const proxyUrl = proxyList[i % proxyList.length];
const browser = await puppeteer.launch({
args: [`--proxy-server=${proxyUrl}`]
});
try {
const page = await browser.newPage();
await page.goto(urls[i], { waitUntil: 'networkidle0' });
const data = await page.evaluate(() => {
return {
title: document.title,
url: window.location.href
};
});
console.log(`URL ${i + 1}:`, data);
} catch (error) {
console.error(`خطأ في ${urls[i]}:`, error.message);
} finally {
await browser.close();
}
}
}
const urlsToScrape = [
'https://example.com/page1',
'https://example.com/page2',
'https://example.com/page3',
'https://example.com/page4'
];
scrapeWithRotation(urlsToScrape);
هذا الكود يتكرر دوريًا عبر البروكسي من القائمة ويقوم بتشغيل متصفح جديد لكل URL. تضمن الطريقة i % proxyList.length تدويرًا دوريًا.
تدوير مع مجموعة من السياقات (Playwright)
const { chromium } = require('playwright');
const proxyList = [
{ server: 'http://proxy1.example.com:8080', username: 'user1', password: 'pass1' },
{ server: 'http://proxy2.example.com:8080', username: 'user2', password: 'pass2' },
{ server: 'http://proxy3.example.com:8080', username: 'user3', password: 'pass3' }
];
async function scrapeWithContextPool(urls) {
const browser = await chromium.launch();
// إنشاء مجموعة من السياقات مع بروكسيات مختلفة
const contexts = await Promise.all(
proxyList.map(proxy => browser.newContext({ proxy }))
);
for (let i = 0; i < urls.length; i++) {
const context = contexts[i % contexts.length];
const page = await context.newPage();
try {
await page.goto(urls[i], { waitUntil: 'networkidle' });
const title = await page.title();
console.log(`URL ${i + 1} (بروكسي ${i % contexts.length}):`, title);
} catch (error) {
console.error(`خطأ في ${urls[i]}:`, error.message);
} finally {
await page.close();
}
}
await browser.close();
}
const urls = [
'https://example.com/page1',
'https://example.com/page2',
'https://example.com/page3'
];
scrapeWithContextPool(urls);
يتيح Playwright إنشاء عدة سياقات في متصفح واحد، كل منها مع بروكسي خاص به. هذا يوفر الذاكرة ووقت التشغيل مقارنةً بإعادة تشغيل المتصفح بالكامل.
تدوير ذكي مع تتبع الأخطاء
class ProxyRotator {
constructor(proxyList) {
this.proxyList = proxyList;
this.currentIndex = 0;
this.failedProxies = new Set();
}
getNext() {
const availableProxies = this.proxyList.filter(
(_, index) => !this.failedProxies.has(index)
);
if (availableProxies.length === 0) {
throw new Error('جميع البروكسيات غير متاحة');
}
const proxy = this.proxyList[this.currentIndex];
this.currentIndex = (this.currentIndex + 1) % this.proxyList.length;
return { proxy, index: this.currentIndex - 1 };
}
markFailed(index) {
this.failedProxies.add(index);
console.log(`تم وضع البروكسي ${index} كغير متاح`);
}
resetFailed() {
this.failedProxies.clear();
}
}
// الاستخدام
const rotator = new ProxyRotator(proxyList);
async function scrapeWithSmartRotation(url, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
const { proxy, index } = rotator.getNext();
const browser = await chromium.launch({ proxy });
const page = await browser.newPage();
try {
await page.goto(url, { timeout: 30000 });
const data = await page.content();
await browser.close();
return data;
} catch (error) {
console.error(`خطأ مع البروكسي ${index}:`, error.message);
rotator.markFailed(index);
await browser.close();
if (attempt === maxRetries - 1) {
throw new Error(`فشل تحميل ${url} بعد ${maxRetries} محاولات`);
}
}
}
}
تتبع هذه الفئة البروكسيات غير العاملة وتستبعدها من التدوير. عند حدوث خطأ، يتم التبديل تلقائيًا إلى البروكسي التالي في القائمة.
معالجة الأخطاء والتحقق من العمل
عند العمل مع البروكسي، تظهر أخطاء محددة: مهلات الاتصال، رفض المصادقة، حظر IP من قبل الموقع المستهدف. تعتبر معالجة الأخطاء بشكل صحيح أمرًا حاسمًا لعمل مستقر لجهاز الاستخراج.
الأخطاء الشائعة ومعالجتها
async function safePageLoad(page, url, options = {}) {
const defaultOptions = {
timeout: 30000,
waitUntil: 'networkidle0',
maxRetries: 3,
retryDelay: 2000
};
const config = { ...defaultOptions, ...options };
for (let attempt = 1; attempt <= config.maxRetries; attempt++) {
try {
await page.goto(url, {
timeout: config.timeout,
waitUntil: config.waitUntil
});
return { success: true, attempt };
} catch (error) {
console.error(`المحاولة ${attempt} فشلت:`, error.message);
// تحليل نوع الخطأ
if (error.message.includes('ERR_PROXY_CONNECTION_FAILED')) {
throw new Error('البروكسي غير متاح');
}
if (error.message.includes('ERR_TUNNEL_CONNECTION_FAILED')) {
throw new Error('خطأ في نفق البروكسي');
}
if (error.message.includes('407')) {
throw new Error('خطأ في مصادقة البروكسي (407)');
}
if (error.message.includes('Navigation timeout')) {
console.log(`مهلة تحميل، إعادة المحاولة بعد ${config.retryDelay}ms`);
await new Promise(resolve => setTimeout(resolve, config.retryDelay));
continue;
}
// إذا كانت هذه هي المحاولة الأخيرة - نعيد الخطأ
if (attempt === config.maxRetries) {
throw error;
}
}
}
}
التحقق من عمل البروكسي
async function testProxy(proxyConfig) {
const browser = await chromium.launch({ proxy: proxyConfig });
const page = await browser.newPage();
const result = {
working: false,
ip: null,
responseTime: null,
error: null
};
const startTime = Date.now();
try {
await page.goto('https://api.ipify.org?format=json', { timeout: 10000 });
const content = await page.textContent('body');
const data = JSON.parse(content);
result.working = true;
result.ip = data.ip;
result.responseTime = Date.now() - startTime;
} catch (error) {
result.error = error.message;
} finally {
await browser.close();
}
return result;
}
// اختبار قائمة البروكسي
async function validateProxyList(proxyList) {
console.log('التحقق من البروكسي...');
const results = await Promise.all(
proxyList.map(async (proxy, index) => {
const result = await testProxy(proxy);
console.log(`البروكسي ${index + 1}:`, result.working ? `✓ ${result.ip} (${result.responseTime}ms)` : `✗ ${result.error}`);
return { proxy, ...result };
})
);
const workingProxies = results.filter(r => r.working);
console.log(`\nعدد البروكسيات العاملة: ${workingProxies.length}/${proxyList.length}`);
return workingProxies.map(r => r.proxy);
}
تتحقق هذه الوظيفة من كل بروكسي قبل الاستخدام، وتقيس زمن الاستجابة وتعيد فقط البروكسيات العاملة. يُنصح بتشغيل التحقق عند بدء التطبيق.
المراقبة والتسجيل
class ProxyMonitor {
constructor() {
this.stats = {
totalRequests: 0,
successfulRequests: 0,
failedRequests: 0,
proxyErrors: 0,
averageResponseTime: 0,
requestsByProxy: new Map()
};
}
recordRequest(proxyIndex, success, responseTime, error = null) {
this.stats.totalRequests++;
if (success) {
this.stats.successfulRequests++;
this.stats.averageResponseTime =
(this.stats.averageResponseTime * (this.stats.successfulRequests - 1) + responseTime) /
this.stats.successfulRequests;
} else {
this.stats.failedRequests++;
if (error && error.includes('proxy')) {
this.stats.proxyErrors++;
}
}
// إحصائيات لكل بروكسي
if (!this.stats.requestsByProxy.has(proxyIndex)) {
this.stats.requestsByProxy.set(proxyIndex, { success: 0, failed: 0 });
}
const proxyStats = this.stats.requestsByProxy.get(proxyIndex);
success ? proxyStats.success++ : proxyStats.failed++;
}
getReport() {
const successRate = (this.stats.successfulRequests / this.stats.totalRequests * 100).toFixed(2);
return {
...this.stats,
successRate: `${successRate}%`,
averageResponseTime: `${this.stats.averageResponseTime.toFixed(0)}ms`
};
}
}
// الاستخدام
const monitor = new ProxyMonitor();
async function monitoredScrape(url, proxyIndex) {
const startTime = Date.now();
try {
// ... كود الاستخراج ...
const responseTime = Date.now() - startTime;
monitor.recordRequest(proxyIndex, true, responseTime);
} catch (error) {
monitor.recordRequest(proxyIndex, false, 0, error.message);
throw error;
}
}
سيناريوهات متقدمة: تحديد الموقع الجغرافي والتعرف على بصمة المتصفح
تتحقق أنظمة مكافحة الروبوتات الحديثة من عنوان IP فقط، ولكن أيضًا من تطابق الموقع الجغرافي، المنطقة الزمنية، لغة المتصفح وغيرها من المعلمات. عند استخدام بروكسي من دولة أخرى، من المهم إعداد جميع هذه المعلمات بشكل صحيح.
إعداد الموقع الجغرافي واللغة للبروكسي
const { chromium } = require('playwright');
async function createContextWithGeo(proxy, geoData) {
const browser = await chromium.launch({ proxy });
const context = await browser.newContext({
locale: geoData.locale, // 'en-US', 'de-DE', 'fr-FR'
timezoneId: geoData.timezone, // 'America/New_York', 'Europe/Berlin'
geolocation: {
latitude: geoData.latitude,
longitude: geoData.longitude
},
permissions: ['geolocation']
});
return { browser, context };
}
// مثال: بروكسي من ألمانيا
const germanyProxy = {
server: 'http://de-proxy.example.com:8080',
username: 'user',
password: 'pass'
};
const germanyGeo = {
locale: 'de-DE',
timezone: 'Europe/Berlin',
latitude: 52.520008,
longitude: 13.404954
};
const { browser, context } = await createContextWithGeo(germanyProxy, germanyGeo);
const page = await context.newPage();
await page.goto('https://www.google.com');
// ستظهر Google النسخة الألمانية مع نتائج برلين
يقوم هذا الكود بإعداد المتصفح ليبدو كأنه مستخدم حقيقي من ألمانيا: لغة واجهة المستخدم بالألمانية، المنطقة الزمنية لبرلين، وإحداثيات وسط برلين.
الإعداد الكامل لبصمة المتصفح
async function createStealthContext(proxy, profile) {
const context = await chromium.launch({ proxy }).then(b =>
b.newContext({
locale: profile.locale,
timezoneId: profile.timezone,
userAgent: profile.userAgent,
viewport: profile.viewport,
deviceScaleFactor: profile.deviceScaleFactor,
isMobile: profile.isMobile,
hasTouch: profile.hasTouch,
colorScheme: profile.colorScheme,
geolocation: profile.geolocation,
permissions: ['geolocation']
})
);
return context;
}
// ملف تعريف لنظام Windows 10 + Chrome من الولايات المتحدة
const desktopUSProfile = {
locale: 'en-US',
timezone: 'America/New_York',
userAgent: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
viewport: { width: 1920, height: 1080 },
deviceScaleFactor: 1,
isMobile: false,
hasTouch: false,
colorScheme: 'light',
geolocation: { latitude: 40.7128, longitude: -74.0060 }
};
// ملف تعريف لجهاز iPhone من المملكة المتحدة
const mobileUKProfile = {
locale: 'en-GB',
timezone: 'Europe/London',
userAgent: 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1',
viewport: { width: 390, height: 844 },
deviceScaleFactor: 3,
isMobile: true,
hasTouch: true,
colorScheme: 'light',
geolocation: { latitude: 51.5074, longitude: -0.1278 }
};
يقلل الإعداد الشامل لبصمة المتصفح من احتمال اكتشاف الأتمتة. من المهم أن تتطابق جميع المعلمات مع بعضها البعض: على سبيل المثال، يجب أن يتوافق User-Agent المحمول مع دقة الشاشة المحمولة.
مهم: عند العمل مع منصات الإعلان (Google Ads، Facebook Ads) أو الخدمات المالية، نوصي باستخدام بروكسيات موبايل - فهي تحتوي على درجة ثقة من مشغلي الهواتف المحمولة الحقيقيين ونادرًا ما يتم حظرها.
تجاوز تسرب WebRTC
// Puppeteer: حظر WebRTC
const browser = await puppeteer.launch({
args: [
'--proxy-server=http://proxy.example.com:8080',
'--disable-webrtc',
'--disable-webrtc-hw-encoding',
'--disable-webrtc-hw-decoding'
]
});
// Playwright: إعادة تعريف واجهة برمجة تطبيقات WebRTC
const context = await browser.newContext({ proxy: proxyConfig });
await context.addInitScript(() => {
// حظر RTCPeerConnection
window.RTCPeerConnection = undefined;
window.RTCDataChannel = undefined;
window.RTCSessionDescription = undefined;
// إعادة تعريف getUserMedia
navigator.mediaDevices.getUserMedia = undefined;
navigator.getUserMedia = undefined;
});
يمكن أن يكشف WebRTC عن عنوان IP الحقيقي الخاص بك حتى عند استخدام البروكسي. يقوم هذا الكود بإيقاف تشغيل واجهة برمجة تطبيقات WebRTC بالكامل في المتصفح.
مقارنة Puppeteer و Playwright للعمل مع البروكسي
| المعيار | Puppeteer | Playwright |
|---|---|---|
| إعداد البروكسي | عبر args سطر الأوامر | عبر كائن التكوين |
| المصادقة | page.authenticate() بعد التشغيل | في كائن proxy عند الإنشاء |
| عدة بروكسيات في متصفح واحد | لا، يحتاج إلى متصفح منفصل | نعم، عبر سياقات مختلفة |
| دعم المتصفحات | فقط Chromium/Chrome | Chromium، Firefox، WebKit |
| الأداء | تشغيل سريع لمتصفح واحد | أكثر كفاءة مع العديد من السياقات |
| TypeScript | أنواع عبر @types/puppeteer | دعم مدمج لـ TypeScript |
| التوثيق | جيد، مع الكثير من الأمثلة | رائع، أكثر تنظيمًا |
| النظام البيئي | الكثير من المكونات الإضافية والامتدادات | تتطور بسرعة، ميزات جديدة |
توصيات للاختيار
اختر Puppeteer إذا:
- كنت تعمل فقط مع Chrome/Chromium
- تستخدم بروكسي واحد في كل مرة
- تحتاج إلى أقصى توافق مع الأدوات الحالية
- لديك قاعدة شفرة كبيرة بالفعل على Puppeteer
اختر Playwright إذا:
- تحتاج إلى العمل مع Firefox أو Safari (WebKit)
- تتطلب استخدام عدة بروكسيات في وقت واحد
- الأداء مهم عند التوسع
- تكتب بلغة TypeScript
- تبدأ مشروعًا جديدًا من الصفر
الأداء عند تدوير البروكسي
اختبار: استخراج 100 صفحة مع تدوير 10 بروكسيات على MacBook Pro M1:
| الطريقة | زمن التنفيذ | استهلاك RAM |
|---|---|---|
| Puppeteer (إعادة تشغيل المتصفح) | 8 دقائق و 23 ثانية | ~1.2 GB كحد أقصى |
| Playwright (إعادة تشغيل المتصفح) | 7 دقائق و 54 ثانية | ~1.1 GB كحد أقصى |
| Playwright (مجموعة السياقات) | 4 دقائق و 12 ثانية | ~800 MB بشكل مستقر |
Playwright مع مجموعة السياقات أسرع تقريبًا بمقدار الضعف بسبب عدم وجود تكاليف تشغيل المتصفح. هذا أمر حاسم عند استخراج آلاف الصفحات.
الخاتمة
يعد دمج البروكسي مع Puppeteer و Playwright ممارسة قياسية للاستخراج من الويب، والاختبار، والأتمتة. يقدم Puppeteer البساطة ونظامًا بيئيًا واسعًا، بينما يوفر Playwright واجهة برمجة تطبيقات حديثة وأداءً أفضل عند العمل مع العديد من البروكسيات عبر سياقات المتصفح.
النقاط الرئيسية التي ناقشناها:
- الإعداد الأساسي لبروكسي HTTP و HTTPS و SOCKS5 في كلا الإطارين
- المصادقة باستخدام اسم المستخدم وكلمة المرور
- تدوير البروكسي للاستخراج على نطاق واسع
- معالجة الأخطاء والتحقق من البروكسي قبل الاستخدام
- إعداد الموقع الجغرافي وبصمة المتصفح لتجاوز أنظمة مكافحة الروبوتات
- مقارنة أداء الأساليب المختلفة
للحلول الإنتاجية، نوصي بدمج بروكسيات عالية الجودة مع إعدادات بصمة المتصفح الصحيحة، ومعالجة الأخطاء، والمراقبة. سيوفر ذلك عملًا مستقرًا لجهاز الاستخراج حتى على المواقع المحمية.
إذا كنت تخطط لاستخراج البيانات من المواقع التجارية، أو الأسواق، أو العمل مع منصات الإعلان، نوصي باستخدام بروكسيات سكنية - فهي توفر أقصى درجات الخصوصية وأقل خطر للحظر بفضل عناوين IP الحقيقية لمستخدمي المنازل.