Playwright هو إطار أتمتة المتصفح من Microsoft: مكتبة مبنية على Apache-2.0 وتركّز أولًا على TypeScript، تشغّل متصفحًا حقيقيًا، وتتحكم فيه عبر واجهة واحدة، ثم تعيد لك الصفحة بعد انتهاء تنفيذ JavaScript. يُسوَّق على أنه إطار لاختبار التطبيقات من البداية إلى النهاية، لكن المحرك الذي يعمل تحته هو ما يلجأ إليه كثيرون بصمت عندما يعود طلب HTTP بغلاف فارغ بدل البيانات المطلوبة. ومن حيث الفكرة، ينافس Puppeteer وSelenium — متصفحات حقيقية تكتب لها الأوامر، لا عملاء HTTP تحلل استجاباتهم.
اختبرتُ microsoft/playwright بالإصدار 1.56.0 عبر مجموعة ثابتة من اختبارات استخراج البيانات: كتالوج ثابت مع صفحات متعددة، مقالة، كتالوج يُعرض عبر JavaScript، واجهة JSON API، خطأ 500، رسم بياني صغير للزحف، وموقعي تدريب عامّين — وذلك على Node v22.22.3 وmacOS arm64 وChromium فقط. جزء العرض جاء نظيفًا. أما جزء الزحف فلا وجود له أصلًا، وهذه هي النقطة الأهم لفهم الأداة قبل الاعتماد عليها.
ما الذي برز
هناك نتيجتان تتصدران الصورة، وكل واحدة منهما تشير إلى اتجاه مختلف قليلًا.
النتيجة الأولى هي سلوك المتصفح المتوقع، ضمن حدود الانتظار الذي استخدمته. بعد page.goto(..., { waitUntil: 'domcontentloaded' })، انتظر اختبار الصفحة الديناميكية ظهور #dynamic-products article.product-card، بينما انتظر اختبار Quotes to Scrape العام ظهور .quote. وما إن ظهرت هذه المحددات الخاصة بالتطبيق حتى أعادت الجولات 8/8 عناصر من العينة و10 اقتباسات من الموقع العام؛ وكانت نتيجة العينة استرجاعًا كاملًا 1.0 مقابل الحقيقة المرجعية ذات الثماني عناصر. لم أحتج إلى حلقة polling مخصصة، لكن Playwright لم يلغِ مشكلة الجاهزية — بل إن الاختبار هو من وفر شرط الاكتمال. كما تم حفظ لقطة شاشة للصفحة كاملة من أول استدعاء.
أما النتيجة الثانية فاستعملت browserContext.request: تحديدًا ctx.request.get(...) بعد أن كان Chromium قد شُغّل بالفعل وتم إنشاء browser context. عندها جرى استدعاء نقطة نهاية JSON الخاصة بالعينة مباشرة وأعاد 8/8 منتجات من دون إنشاء صفحة أو عرضها. هذا يتجاوز عمل DOM، لكنه لا يتجاوز كلفة عملية المتصفح داخل هذا الاختبار. عميل الطلب المرتبط بالسياق يمكنه مشاركة حالة الكوكيز مع صفحات المتصفح؛ أما playwright.request.newContext() المستقل فيتجنب الحاجة إلى browser context لكنه لا يشارك تلك الجلسة تلقائيًا. الاختبار غطّى المسار الأول فقط.
Playwright أيضًا لا يوفّر قائمة انتظار للزحف، ولا كاتبًا للبيانات، ولا خفضًا تلقائيًا لمعدل الطلبات. اختبار رسم الزحف البياني الذي أجريته — تتبع الروابط الداخلية، احتساب العمق، وتجنب الزيارات المتكررة — وصل إلى 12 صفحة عبر الأعماق {0:1, 1:4, 2:7}، لكن الترتيب بعرض المسار أولًا كان كودًا كتبته أنا. Playwright يفتح الصفحات ويفحصها؛ أما حفظ الجبهة، وسياسات الروابط، وإعادة المحاولة، والجدولة، فكلها تقع على طبقة أخرى.
ما هو Playwright فعليًا
الأداة — microsoft/playwright على GitHub — مكتوبة بـ TypeScript، ومرخّصة تحت Apache-2.0، وتديرها Microsoft. النسخة المختبرة هنا هي 1.56.0 بتاريخ 9 يوليو 2026. لذلك تُعرض النتائج على أساس هذه النسخة تحديدًا، لا كحكم على توافق الإصدارات الأحدث.
الموقع الرسمي واضح جدًا: إنها إطار لاختبار الويب والأتمتة، يقود Chromium وFirefox وWebKit عبر واجهة واحدة. المسار الأساسي في Playwright هو test runner مع fixtures وassertions وtrace viewer. أما استخدامه كأداة استخراج بيانات فيعني اتباع Library mode الموثق: chromium.launch() ثم context ثم page، خارج بيئة الاختبار. كل ما في هذه المراجعة استخدم هذه الواجهة العامة. لم أجرِ اختبار توافق بين الإصدارات، لذلك لا يمكن اعتبار ذلك ادعاءً بأن كل سلوك تم اختباره سيبقى ثابتًا عبر الإصدارات.
اتساع الدعم الموثق هو العنوان الأبرز في كل مكان آخر، لذا سأذكره بدقة. Playwright يقود ثلاثة محركات متصفح — Chromium وFirefox وWebKit — عبر واجهة واحدة، كما يوفّر عملاء أصليين في Python وJava و.NET إلى جانب JavaScript. هذا موثق، وهو فعلًا أبرز نقاط تميّزه من حيث الشكل. لكن هذه الجولة لم تختبر إلا نطاقًا أضيق:
| القدرة | الحالة في هذه المراجعة |
|---|---|
| محرك Chromium | تم اختباره — كل الاختبارات هنا جرت عليه |
| محرك Firefox | موثق، لكن لم يُتحقق منه هنا |
| محرك WebKit | موثق، لكن لم يُتحقق منه هنا |
| واجهة واحدة عبر المحركات الثلاثة | موثقة، لكن لم يُتحقق منها هنا |
| عملاء Python وJava و.NET | موثقة، لكن لم يُتحقق منها هنا |
| استخدام Proxy | غير مختبر |
| التوسع عبر سياقات متوازية | غير مختبر |
| اعتراض الشبكة لاستخراج API-first | غير مختبر |
إذا كان الهدف يعرض بشكل مختلف تحت WebKit في Safari، أو كانت فرقكم تكتب بـ Python، فهذه السعة الواسعة هي حجة Playwright — لكن لا تأخذ نتائجي دليلاً على تكافؤ Firefox أو WebKit، لأنني لم أختبرهما.
كيف يعمل من الداخل
النموذج الذهني هنا هو محرك متصفح تكتب له الأوامر. chromium.launch() يبدأ عملية المتصفح. وcontext هي جلسة معزولة بملفات تعريف الارتباط والتخزين والذاكرة المؤقتة الخاصة بها؛ أما page فهي لسان/تبويب داخل ذلك السياق. تستدعي page.goto(url)، ثم تنتظر الشرط الذي يمثل جاهزية التطبيق، وتقرأ DOM الناتج عبر أدوات مثل page.$$eval. هذا أقرب إلى متصفح واجهة المستخدم من تحليل استجابة HTTP، لكنه ليس تطابقًا كاملًا مع البيئة الحقيقية: مؤشرات headless، وحجم العرض، واللغة، والخطوط، وحالة الملف الشخصي، ومسار TLS/الشبكة، ودفاعات الموقع كلها قد تغيّر ما يتم تقديمه. هذه المراجعة لم تختبر سلوك مكافحة البوت ولا التطابق مع متصفح الإنتاج.
page.screenshot() تلتقط الصفحة المرسومة، كاملة أو ضمن جزء محدد، وقد نجحت من أول محاولة في تجربتي. وواجهة الطلبات التي ذكرتها — context.request.get — تشارك كوكيز السياق نفسه لكنها تتجاوز العرض المرئي، بحيث يمكنك في سكربت واحد الجمع بين "حمّل الصفحة واقرأ DOM" و"استدعِ نقطة نهاية JSON فقط" من دون تبديل الأدوات.
أما ما لا يوجد تحت الغطاء فهو آلية الزحف. لا توجد جدولة للطلبات، ولا مجموعة زيارة محفوظة، ولا سياسة للرفق بالموقع، ولا خط تصدير جاهز. من السهل رسم traversal محدود، لكن العمل الموثوق على مستوى الجبهة يحتاج أيضًا إلى تطبيع الروابط، ومعالجة التحويلات، وإعادة المحاولة، وقواعد النطاق، وتحديد المعدلات، والاستعادة بعد الفشل. إما أن تبني هذه الطبقة بنفسك، أو تستخدم إطارًا يغلّف محرك المتصفح.
واقع الإعداد والتثبيت
التثبيت يتم على خطوتين، والثانية هي التي تحمل العبء الأكبر في النشر. npm install playwright يثبت المكتبة؛ ثم npx playwright install منفصلًا يحمّل بناءات المتصفح (Chromium في حالتي). لذا احسب مساحة التخزين، ووقت التحميل، وتخزين المتصفح المؤقت في CI، وتنظيف العمليات، بدل أن تتعامل مع حزمة npm على أنها النظام القابل للتشغيل كله.
إذا ثبّتَّ Playwright وأنت تتوقع scraper ثم اتبعت دروس الاختبار، فستبدأ بملفات اختبار وعبارات expect(). أما كود الاستخراج فيستخدم واجهة المكتبة مباشرة. كلاهما موثق، لكن الفرق مهم عند البحث عن أمثلة واختيار أوامر النشر.
في هذه الجولة، كانت الجوانب العملية المفيدة واضحة: browser contexts عزلت حالة الجلسة، واستدعاءات async اندمجت بسلاسة، والتقاط screenshot احتاج سطرًا واحدًا، وأما HTTP 500 فبقي قابلًا للفحص عبر كائن الاستجابة. أما الجانب الأكثر خشونة فكان تشغيليًا لا نحويًا: كان لا بد من تثبيت بناء المتصفح وإدارة دورة حياته بشكل منفصل عن المكتبة.
النتائج العملية

كل الأرقام المحلية كانت ضد خادم fixture على 127.0.0.1 مع تسجيل الحقيقة المرجعية قبل بدء الزحف. توجد بنية الاختبار الدقيقة في run_playwright_material_tests.mjs، كما تتضمن الملفات الخام المحفوظة الحقيقة المرجعية ومخرجات كل اختبار. هذه ما تزال ملاحظات من تشغيل المؤلف على جهاز واحد وفي مرة واحدة؛ والروابط هنا تكشف قابلية إعادة الإنتاج بدلًا من تحويلها إلى benchmark واسع.
| الاختبار | الهدف | النتيجة |
|---|---|---|
| كتالوج ثابت + صفحات متعددة | fixture محلي | 12/12 منتجًا، استرجاع 1.0 |
| استخراج مقالة | fixture محلي | العنوان + 3/3 فقرات، مع إبقاء النص التمهيدي منفصلًا |
| صفحة ديناميكية JavaScript (عرض أصلي) | fixture محلي | 8/8، استرجاع 1.0، تم حفظ لقطة شاشة كاملة |
JSON API ديناميكي (page.request) | fixture محلي | 8/8، استرجاع 1.0، من دون عرض DOM |
| التعامل مع HTTP 500 | fixture محلي | حالة 500 قابلة للفحص، ولم يفشل الانتقال |
| رسم الزحف البياني (BFS مكتوب يدويًا) | fixture محلي | 12 صفحة، الأعماق {0:1, 1:4, 2:7} |
| Books to Scrape | نموذج عام | 20 منتجًا |
| Quotes JS (مُعروض بـ JS) | نموذج عام | 10 اقتباسات، مع العرض الأصلي |
حلقة الصفحات المتعددة اتبعت رابط الصفحة التالية صراحةً؛ Playwright لم يكتشف الصفحات من تلقاء نفسه. محدد المقالة أبقى عناصر التنقل والتذييل خارج نتيجة المحتوى الأساسي. في مسار الفشل، أعادت عملية الانتقال كائن استجابة بحالة 500 بدل أن ترمي استثناءً، ما ترك القرار للمستدعي: هل يسجل الخطأ، أم يعيد المحاولة، أم يتابع. أما هدفا التدريب العامّان فأعيدا بعدد العناصر الظاهر في الجدول.
وهناك حد يستحق أن يُقال بوضوح: كل ما سبق جرى على Chromium، وعلى جهاز واحد، ولمرة واحدة. جدول القدرات يفصل بين الاتساع الموثق والسلوك الذي تم اختباره فعلًا. ولم أعد تشغيل المجموعة على build آخر من Playwright، لذا لا يمكن استخلاص نتيجة عبر إصدارات مختلفة. كما أن أزمنة كل اختبار لم تُذكر كمعايير أداء؛ لأن تمريرة ساعة توقيت واحدة على حاسوب محمول واحد لا تكفي للمقارنة في السرعة.
الجاهزية جزء من عقد الاستخراج
النتائج الديناميكية اعتمدت على شروط انتظار تمثل البيانات المطلوبة، لا مجرد التنقل داخل المتصفح. بالنسبة للكتالوج المحلي، انتقل الاختبار مع waitUntil: 'domcontentloaded' ثم استدعى waitForSelector('#dynamic-products article.product-card') بمهلة 15 ثانية. أما اختبار Quotes JS العام فاستعمل حالة التنقل نفسها وانتظر .quote مع مهلة 20 ثانية. ولم يبدأ الاستخراج إلا بعد ظهور هذه المحددات.
هذا الفرق مهم عند تعديل السكربت. domcontentloaded يعني أن المستند الأوّلي تم تحليله؛ لكنه لا يعني أن استجابة API المتأخرة وصلت، أو أن hydration اكتملت، أو أن قائمة لا نهائية توقفت عن النمو، أو أن صفًا افتراضيًا دخل نطاق العرض. يكون المحدد مفيدًا عندما يكفي وجود عنصر واحد يطابقه. أما إذا كانت الاكتمالية تعتمد على استجابة معروفة، أو عدد عناصر، أو حالة تطبيق، أو نافذة شبكة هادئة، فانتظر ذلك الشرط بدلًا منه. يجب ربط الشرط بعقد المخرجات: "يوجد على الأقل بطاقة واحدة" و"تم تحميل كل الصفحات المتوقعة" ليسا نفس الادعاء.

التعامل مع المهلة أيضًا يقع على عاتق المستدعي. الاختبار استخدم مهلات finite للمحددات، لكنه لم يدرس سياسة إعادة المحاولة أو يميز بين صفحة بطيئة ومحدد تغيّر نهائيًا. ينبغي للغلاف الإنتاجي أن يسجل أي شرط جاهزية فشل، ويلتقط قدرًا كافيًا من حالة الصفحة لتشخيص المشكلة، ثم يقرر ما إذا كانت إعادة المحاولة آمنة. Playwright يمنحك الأحداث وDOM؛ لكنه لا يستطيع استنتاج ما تعنيه "البيانات الكاملة" في عملك.
هذا الحد يجب توثيقه بجوار كل extractor، لا أن يُترك ضمنيًا داخل timeout.
مسار الـ API له عقد موازٍ. كان ctx.request.get مناسبًا لأن browser context كان موجودًا بالفعل، ومشاركة الجلسة قد تكون مفيدة. وإذا اكتشف العمل أن نقطة البيانات تعمل من دون أي جلسة متصفح، فإن request context مستقل يمثل معمارية مختلفة بسلوك مختلف للجلسة والكوكيز. هذه الجولة لم تقارن بينهما. اعتبر "من دون عرض DOM" حقيقة مقاسة، ثم قرر منفصلًا ما إذا كانت عملية المتصفح مطلوبة لباقي سير العمل.
سؤال الزحف
نتيجة رسم الزحف البياني هي ما يحدد كيف يجب أن تفكر في Playwright. اثنتا عشرة صفحة، وثلاثة أعماق، وصحيحة — لكن كل منطق السير كتبته أنا. Playwright وفّر جزء "افتح هذا الرابط واقرأه"؛ وأنا وفّرت قائمة الانتظار، ومجموعة الزيارات السابقة، وتتبع العمق.
بالنسبة للمهام الصغيرة والمحدودة، هذا ليس مشكلة. أما في أعمال الزحف الكبيرة، فمعناه أنك إما تكتب crawler فوق مكتبة متصفح، أو تقرن Playwright بأداة أخرى قامت بهذا مسبقًا. النمط الموثق هو Crawlee، الذي يغلّف Playwright (وPuppeteer) بقائمة طلبات حقيقية، وتخزين بيانات، وتهدئة تلقائية — أي أنك تحتفظ بعرض Playwright وتستعير طبقة التنسيق. وإذا كنت تريد قائمة الانتظار مدمجة في الإطار نفسه بدلًا من إضافتها بعد ذلك، فهذه هي الفكرة الأساسية كاملة في Scrapy's، رغم أن Scrapy يعتمد HTTP أولًا ولا يعرض JavaScript من تلقاء نفسه. الفكرة ليست أن Playwright ناقص، بل أن "أتمتة المتصفح" و"الزحف" مهمتان مختلفتان، وPlaywright يدّعي واحدة منهما فقط.

اختبار BFS ذو الصفحات الاثنتي عشرة يوضح حدود الملكية بوضوح. لقد وفّر قائمة انتظار، ومجموعة زيارات سابقة، وتتبع عمق لرسم بياني مضبوط. لكن الجبهة الإنتاجية ما تزال بحاجة إلى تعريف canonicalization للروابط، ومعالجة التحويلات، والمضيفين المسموح بهم، ومفاتيح التكرار، وإعادة المحاولة، والتوازي، والتأخير لكل مضيف، والحفظ المستمر، ودلالات إعادة التشغيل. أما التصدير فهو قرار آخر: العينة كتبت JSON وCSV لأن الاختبار فعل ذلك، لا لأن Playwright يوفر تجريدًا للبيانات.
كما أن تصميم الجلسة يؤثر على الغلاف. يمكن لمتصفح واحد أن يحتوي عدة contexts معزولة الكوكيز والتخزين، لكن هذه المراجعة لم تقسّم مقياس الأداء مع السياقات المتوازية ولا عزلة الفشل بينها. إعادة استخدام context قد تحفظ تسجيل الدخول وتقلل وقت الإعداد؛ وإنشاء contexts منفصلة قد يمنع تسرب الحالة بين المهام. هذه كلها سياسات على مستوى crawler، حتى لو أن Playwright يوفّر primitive الخاص بالسياق. لذلك يجب قياس دورة الحياة التي اخترتها في بيئة النشر وبناء المتصفح اللذين ستشغل عليهما فعليًا.
المزايا والعيوب
المزايا:
- تنفيذ JavaScript عبر محرك Chromium حقيقي؛ والهدفان الديناميان وصلا إلى المحددات المستخدمة كشرط جاهزية.
- تم التقاط لقطة شاشة كاملة من أول محاولة.
- استخدمت المحددات لاستخراج حقول الكتالوج الثابت والمقالة كما هو متوقع من العينات المضبوطة.
browserContext.requestوصل إلى نقطة نهاية JSON من دون عرض الصفحة، بينما بقيت عملية المتصفح التي كانت قد شُغلت مسبقًا جزءًا من الاختبار.- متين عند الاستجابة السيئة: كان HTTP 500 قابلًا للفحص ولم ينهَر الانتقال.
- دعم موثق لثلاثة محركات (Chromium وFirefox وWebKit) عبر واجهة واحدة، مع عملاء Python وJava و.NET (موثقون؛ لكن المستَخدم هنا Chromium فقط).
- Apache-2.0 وتديره Microsoft.
- تجربة تطوير نظيفة بمجرد الدخول إلى library mode: واجهة واحدة عبر المحركات، async ممتاز، ولقطات شاشة بسيطة جدًا.
العيوب:
- لا توجد قائمة زحف أو dataset أو auto-throttle مدمجة — أعمال الزحف الكبيرة تحتاج كودك أنت أو غلافًا مثل Crawlee.
- ثقل المتصفح: تنزيل binary وكلفة كل صفحة هما الضريبة الحقيقية مقارنة بأداة تعتمد HTTP فقط.
- الإطار الافتراضي هو test runner؛ أما الاستخراج فيعني أن تعرف أن library mode موجود ثم تخرج من المسار التسويقي المعتاد.
- لم تُختبر إلا Playwright 1.56.0 وChromium؛ ولم تُفحص المساواة عبر الإصدارات أو المحركات.
- لا يوجد إخراج JSON منظم بحسب schema من تلقاء نفسه؛ أنت من يكتب المحددات ويشكّل البيانات.
لمن يناسب، ومن الأفضل أن يتجاوزه
إذا كانت مشكلتك هي عرض صفحات لا تظهر بياناتها إلا بعد تنفيذ JavaScript، أو جمع لقطات شاشة إلى جانب بيانات DOM، فإن Playwright مرشح معقول لإعادة التجربة على أهدافك. ويمكن للفرق التي تستخدم اختبارات Playwright أصلًا أن تعيد توظيف المفاهيم نفسها ومهارات المحددات في library mode. عملاء Python وJava و.NET خيارات موثقة، لكن هذه المراجعة اختبرت Node وChromium فقط.
فكّر في طبقة أخرى في ثلاث حالات. إذا كانت البيانات المطلوبة موجودة أصلًا داخل استجابة HTTP، فالأداة المعتمدة على HTTP تتجنب كلفة تشغيل المتصفح والعرض؛ وColly مكتبة crawler من هذا النوع، بينما Trafilatura تستهدف استخراج المقالات. وإذا كنت تحتاج إلى queueing وpersistence وthrottling، فاستخدم إطار زحف أو غلافًا حول Playwright. وإذا كنت تريد إخراجًا على هيئة schema من دون صيانة المحددات، فقارن خدمات الاستخراج المُدارة. لم يُجرَ benchmark لأي من هذه البدائل في هذه المراجعة.
وإذا كنت تقارن تحديدًا بين Playwright وPuppeteer، فذلك نقاش مستقل؛ فقارنتنا جنبًا إلى جنب تشغّل الاثنين على العينات نفسها وتوضح أين ينتهي الاختيار فعليًا.
البدائل، وأين يندرج الاستخراج المُدار
Playwright مجاني، وApache-2.0، وتديره أنت على بنيتك. أنت المسؤول عن نشر المتصفح، والمحددات، وشروط الجاهزية، وكود الزحف، والتحديثات، ومعالجة الأعطال. هذه المراجعة لم تقِس أداء مكافحة البوت ولم تقارن التكلفة التشغيلية الكاملة بخدمة مُدارة.
ضمن عالم المصادر المفتوحة، المقارنات المفيدة تكون حسب المهمة. لأعمال الزحف على نطاق واسع فوق متصفح، يضيف Crawlee قائمة الانتظار والبيانات اللتين يتركهما Playwright خارجًا. وإذا كان هدفك إخراج Markdown جاهزًا لـ LLM من متصفح حقيقي بدل صفوف مصاغة يدويًا، فإن Crawl4AI يشغّل متصفحًا ويُنتج Markdown لهذا المسار. وإذا كنت تقارن بين عدة أدوات من هذه معًا، فإن open-source scraper roundup يضع الفئات جنبًا إلى جنب.
إفصاح: Thunderbit هو منتج الجهة الناشرة، ولم يُشغَّل عبر هذا الاختبار الخاص بـ Playwright. وهو يمثل فئة الاستخراج المُدار: الخدمة تدير العرض وتعيد نص الصفحة أو سجلات على هيئة schema، بينما يترك Playwright تشغيل المتصفح ومنطق المحددات للمطور. لذلك فالمقارنة هنا تتعلق بنموذج الاستضافة، وشكل المخرجات، ونموذج التكلفة — وليست نتيجة أداء ناتجة عن هذه المراجعة.
جرّب Thunderbit لاستخراج بيانات الويب
الحكم النهائي
استخدم Playwright عندما يحتاج هدفك إلى محرك متصفح، وعندما تكون مستعدًا لتحمّل مسؤولية شروط الجاهزية، والمحددات، وتنسيق الزحف. يوضح جدول النتائج أن library mode الخاص بـ Chromium تعامل مع العينات الثابتة والديناميكية وواجهات API ولقطات الشاشة والفشل كما هو متوقع في هذه الجولة التي أجراها المؤلف.
واحفظ حدود الدليل كما هي: لم يُختبر إلا Chromium وNode، واعتمدت عملية المشي ذات 12 صفحة على BFS مكتوب يدويًا، وbrowserContext.request تجاوز عرض الصفحة لكنه لم يتجاوز عملية المتصفح التي كانت تعمل أصلًا، وكل استخراج ديناميكي استند إلى محدد جاهزية معلن. هذه القيود تجعل Playwright هنا primitive للمتصفح في هذه المراجعة، لا نظام زحف متكاملًا من البداية إلى النهاية تم قياسه.
جرّب Thunderbit لاستخراج بيانات الويب Get Started Free
الأسئلة الشائعة
هل ما زلت أحتاج إلى waits عند استخراج البيانات باستخدام Playwright؟
نعم. تشغيل المتصفح لا يخبر السكربت متى تصبح بيانات التطبيق جاهزة. في هذه الاختبارات انتقلنا إلى domcontentloaded ثم انتظرنا محددًا خاصًا بالهدف قبل الاستخراج. قد تحتاج صفحات الإنتاج إلى إشارة مختلفة، مثل استجابة، أو حالة locator، أو حدث من التطبيق.
هل يستطيع Playwright الزحف إلى موقع كامل من تلقاء نفسه؟ ليس بشكل مدمج. لا توجد قائمة طلبات، ولا writer للبيانات، ولا auto-throttle — وقد وصل اختبار رسم الزحف البياني إلى 12 صفحة عبر الأعماق {0:1, 1:4, 2:7} فقط لأنني كتبت البحث بعرض المسار يدويًا. لأعمال الزحف الكبيرة، اقرن Playwright مع Crawlee الذي يضيف طبقة زحف حقيقية، أو استخدم إطار crawler بدلًا منه.
متى أستخدم browserContext.request بدل request context مستقل؟
استخدم browserContext.request عندما يجب أن تشارك طلبات HTTP الكوكيز مع الصفحات داخل browser context موجود. واستخدم playwright.request.newContext() عندما تريد سياقًا خاصًا بالـ API فقط من دون تشغيل متصفح، ولا تحتاج إلى مشاركة تلقائية للكوكيز مع صفحات المتصفح. المسار الأول فقط هو الذي اختُبر هنا.
هل تم اختبار Firefox وWebKit هنا؟ لا. كل اختبار جرى على Chromium، وعلى جهاز واحد، ولمرة واحدة. دعم Playwright لثلاثة محركات (Chromium وFirefox وWebKit) ولعملاء Python وJava و.NET هو قدرة موثقة أذكرها كما هي، لا كما تم التحقق منها — إذ إن تكافؤ Firefox وWebKit، واستخدام Proxy، والتوسع المتوازي، واعتراض الشبكة كلها خارج نطاق هذه الأرقام.
ما البيئة التي غطّتها هذه المراجعة؟ Playwright 1.56.0، وNode v22.22.3، وmacOS arm64، وChromium فقط. أما Firefox وWebKit وProxying والتوسع المتوازي وسلوك مكافحة البوت والإصدارات الأحدث من Playwright فلم تكن ضمن التشغيل. وكان التثبيت يتطلب المكتبة بالإضافة إلى تنزيل منفصل لبناء المتصفح.


