اليوم ، تزحف الويب تقنية معروفة ، ولكن لا تزال هناك العديد من التعقيدات. لا يزال من الصعب التنافس مع مواقع الويب الحديثة التي طورتها العديد من التقنيات المعقدة مثل Ajax Training و XMLHTTPrequest و WebSockets و Flash Sockets ، إلخ.
دعنا نأخذ احتياجاتنا الأساسية في مشروع Hubdoc كمثال ، حيث نقوم بزحف مبلغ الفاتورة ، وتاريخ انتهاء الصلاحية ، ورقم الحساب ، والأهم من ذلك: PDF من الفواتير الحديثة من مواقع البنوك والمرافق وشركات بطاقات الائتمان. بالنسبة لهذا المشروع ، بدأت بحل بسيط للغاية (لا أستخدم المنتج التجاري باهظ الثمن الذي نقوم بتقييمه في الوقت الحالي) - مشروع زاحف بسيط اعتدت عليه مع Perl في Messagelab/Symantec. لكن النتائج لم تسير على ما يرام ، وصنع مرسلي البريد العشوائي موقعًا أبسط بكثير من تلك الخاصة بالبنوك والمرافق.
فكيف تحل هذه المشكلة؟ نبدأ بشكل أساسي بمكتبة الطلب الممتازة التي تم تطويرها باستخدام Mikea. قدم طلبًا في المتصفح ، وتحقق من الرؤوس التي تم إرسالها في نافذة الشبكة ، ثم نسخ رؤوس الطلب هذه إلى الرمز. هذه العملية بسيطة للغاية. إنه مجرد تتبع جميع الطلبات من تسجيل الدخول إلى تنزيل ملف PDF ثم محاكاة جميع الطلبات من هذه العملية. من أجل تسهيل التعامل مع أشياء مماثلة وجعل مطوري الويب أكثر عقلانية في كتابة برامج الزاحف ، قمت بتصدير النتائج من HTML إلى jQuery (باستخدام مكتبة Cheatio خفيفة الوزن) ، مما جعل العمل مماثلًا بسيطًا وجعلت من السهل استخدام محدد CSS لتحديد العناصر في صفحة ما. يتم لف العملية بأكملها في إطار عمل ، والذي يمكنه أيضًا القيام بعمل إضافي ، مثل الحصول على شهادات من قاعدة البيانات ، وتحميل الروبوتات الفردية ، والتواصل مع واجهة المستخدم من خلال Socket.io.
هذا يعمل لبعض مواقع الويب ، لكنه مجرد برنامج نصي JS ، وليس رمز Node.js الذي يتم وضعه على موقعها من قبل هذه الشركات. يمكنهم وضع مشكلات بقايا الطعام لمعالجة التعقيد ، مما يجعل من الصعب عليك معرفة ما يجب القيام به للحصول على نقطة معلومات تسجيل الدخول. بالنسبة لبعض المواقع ، حاولت الحصول عليها من خلال دمجها مع مكتبة الطلب () لبضعة أيام ، لكنها كانت لا تزال سهلة.
بعد الانهيار تقريبًا ، اكتشفت عقدة phantomjs ، وهي مكتبة تسمح لي بالتحكم في متصفح WebKit Phantomjs من العقدة (ملاحظة المترجم: لم أكن أتوقع اسمًا مقابلًا. تعني مقطوعة الرأس أن صفحة العرض قد اكتملت في الخلفية دون عرض الجهاز). هذا يبدو وكأنه حل بسيط ، ولكن هناك بعض المشكلات التي لا يمكن أن يتجنبها phantomjs:
1. لا يمكن أن يخبرك phantomjs فقط ما إذا كانت الصفحة قد تم تحميلها ، لكن لا يمكنك تحديد ما إذا كان هناك إعادة توجيه (إعادة توجيه) تم تنفيذها من خلال علامات JavaScript أو Meta في هذه العملية. خاصة عندما يستخدم JavaScript SetTimeOut () لتأخير المكالمات.
2. يوفر لك phantomjs خطافًا باجيلاً لاكتشافًا يسمح لك بالتعامل مع المشكلات المذكورة أعلاه ، ولكن هذه الوظيفة يمكن أن تقلل فقط من هذا الرقم عندما تحدد عدد الصفحات التي يجب تحميلها ، وتقليل هذا الرقم عند تحميل كل صفحة ، وتوفير المعالجة لمهلات محتملة (لأن هذا لا يحدث دائمًا) ، لذلك عندما يتم تخفيض رقمك إلى 0 ، يمكن استدعاء وظيفة الاتصال. يمكن أن تعمل هذه الطريقة ، ولكنها تجعل الناس دائمًا يشعرون بأنه يشبه القراصنة.
3. يتطلب phantomjs عملية كاملة ومستقلة لكل صفحة للزحف ، لأنه إذا لم يكن هذا هو الحال ، فمن المستحيل فصل ملفات تعريف الارتباط بين كل صفحة. إذا كنت تستخدم نفس عملية phantomjs ، فسيتم إرسال الجلسة في الصفحة التي تم تسجيلها إلى صفحة أخرى.
4. غير قادر على استخدام Phantomjs لتنزيل الموارد - يمكنك فقط حفظ الصفحة كـ PNG أو PDF. هذا مفيد ، ولكن هذا يعني أننا بحاجة إلى اللجوء إلى الطلب () لتنزيل PDF.
5. بسبب الأسباب المذكورة أعلاه ، يجب أن أجد طريقة لتوزيع ملفات تعريف الارتباط من جلسة PhantomJS إلى مكتبة الجلسة للطلب (). ما عليك سوى توزيع سلسلة المستند.
6. حقن المتغيرات في جلسة المتصفح ليس بالأمر السهل. للقيام بذلك ، أحتاج إلى إنشاء سلسلة لإنشاء وظيفة JavaScript.
نسخة الكود كما يلي:
robot.prototype.add_page_data = دالة (الصفحة ، الاسم ، البيانات) {
page.evaluate (
"function () {var" + name + "= window." + name + "=" + json.stringify (data) + "}"
) ؛
}
7. تمتلئ بعض مواقع الويب دائمًا برمز مثل Console.log () ، ويجب إعادة تعريفها وإخراجها إلى الموقع الذي نريده. لإنجاز هذا ، فعلت هذا:
نسخة الكود كما يلي:
if (! console.log) {
var iframe = document.createElement ("iframe") ؛
document.body.appendChild (iframe) ؛
وحدة التحكم = window.frames [0] .Console ؛
}
8. تمتلئ بعض مواقع الويب دائمًا برمز مثل Console.log () ، ويجب إعادة تعريفها وإخراجها إلى الموقع الذي نريده. لإنجاز هذا ، فعلت هذا:
نسخة الكود كما يلي:
if (! console.log) {
var iframe = document.createElement ("iframe") ؛
document.body.appendChild (iframe) ؛
وحدة التحكم = window.frames [0] .Console ؛
}
9. ليس من السهل إخبار المتصفح بأنني نقرت على العلامة. من أجل إنجاز هذه الأشياء ، أضفت الكود التالي:
نسخة الكود كما يلي:
var clickelement = window.clickelement = function (id) {
var a = document.getElementById (id) ؛
var e = document.createEvent ("mouseevents") ؛
e.Initmousevent ("انقر" ، صواب ، صحيح ، نافذة ، 0 ، 0 ، 0 ، 0 ، خطأ ، خطأ ، خطأ ، خطأ ، 0 ، فارغة) ؛
A.Dispatchevent (E) ؛
} ؛
10. أحتاج أيضًا إلى الحد من الحد الأقصى لتزامن جلسة المتصفح للتأكد من أننا لن ننفجر الخادم. ومع ذلك ، فإن هذا القيد أعلى بكثير مما يمكن أن تقدمه الحلول التجارية باهظة الثمن. (ملاحظة المترجم: أي أن توافق الحل التجاري أكبر من هذا الحل)
بعد كل هذا العمل ، لدي حل زاحف لائق نسبيًا لطلب phantomjs +. يجب عليك تسجيل الدخول باستخدام PhantomJs قبل أن تتمكن من العودة إلى طلب الطلب (). سوف تستخدم ملفات تعريف الارتباط المحددة في PhantomJs للتحقق من جلسة تسجيل الدخول. هذا فوز كبير لأنه يمكننا استخدام دفق الطلب () لتنزيل ملف PDF.
تتمثل الخطة بأكملها في جعل من السهل نسبيًا على مطوري الويب فهم كيفية استخدام محددات JQuery و CSS لإنشاء زحف لمواقع الويب المختلفة. لم أثبت بنجاح أن هذه الفكرة ممكنة ، لكنني أعتقد أن ذلك سيحدث قريبًا.