انقر على الشهرة ، أو كيفية إثارة الروبوت و ... الآخرين



ذات مرة ، جرت محادثة متنصت أمام متجر بعيد بعيد :
NB: -         ? 

GURU : - «» . . . , ...

 NB: -      ,     ? 

GURU : - google yandex , . . , .

 NB: -       ? 

GURU : - ?… ...
توقف NB عن السؤال ، خوفًا على ما يبدو من إزعاج محاور أكثر خبرة بوضوح.
توالت جورو عينيه ، كما لو كان التأكيد على استنفاد موضوع الوكيل وكان صامتا ...

بالطبع ، عرفت GURU أن استعلام البحث (على سبيل المثال ، بالكلمة: proxy) سيؤدي قريبًا جدًا إلى ملاحظة NB للحصول على العنوان المطلوب: قائمة المنفذ. ولكن بعد التجارب الأولى ، سوف يفهم NB بنفس السرعة:

  • ليست كل العناوين في قائمته تعمل ؛
  • ليست جميع الوكلاء جيدة على قدم المساواة.
  • "التمسك" بموقع عبر وكيل يدويًا هي مهمة تتطلب إرادة كبيرة ؛
  • وكيل "خاطئ" سيضر الوضع ، لأنه قد يتم الاشتباه في الموقع من خلال مخطوطات العمالقة في الغلاف.


سوف أتحدث في هذا المقال عن مدى الارتجال (والأهم من ذلك عالمي)
(دون استخدام برامج خاصة معينة ، مثل ZennoPoster ، إلخ ...)
قم ببناء أداة تلقائية للحصول على قائمة بالوكلاء "المناسبين حقًا" واستخدامهم لتنظيم زيارات (تلقائية) للذين تمت ترقيتهم
الموقع باستخدام متصفح كروم .

باتباع التعليمات ، سوف تحصل على أداة جاهزة تتيح لك:

  • "انقر" - في (زيارة) الموقع المستهدف تلقائيًا بالكامل ، دون خوف من التسوية ؛
  • محاكاة سلوك المستخدم بالكامل ؛
  • تنظيم جميع الزيارات وفقًا لجدول (سيناريو) ؛
  • تفعل كل ما سبق في عدد المرات اللازمة للتقدم.

وعلى الرغم من أن كل عملي (إلى جانب البحث) استغرق أسبوعًا ، فلن تحتاج إلى يومين لإنشاء مثل هذه الأداة ، ولديك معرفة أساسية بسطر الأوامر و PHP و JavaScript .


ومع ذلك ، قبل التمرير أسفل المخطط التالي ، سأقول بضع كلمات حول سبب إعداد هذه المادة ولمن.

ستكون المادة مفيدة إذا كنت تريد أن تفهم كيف يتم ترتيب الإنشاءات (؟ أو المنشئات؟) التي يمكنك من خلالها بناء تطبيق بسرعة نسبية ، بسهولة ودون تكلفة ، قابلة للتكيف مع تغييرات التغييرات. إذا كنت مهتمًا بإمكانية إنشاء تطبيق يستند إلى حافلة خدمة ( ESB ).

سيكون النص مفيدًا إذا كنت ترغب في التعرف على استخدام Docker لأنظمة البناء الفوري . أو إذا كنت مهتمًا فقط بـ Selenium Server والفروق الدقيقة في تلقي محتوى / مظهر من مظاهر نشاط HTTPx.
بالنسبة إلى "الاستخدام الفوري" ، فإن قراءة كل هذا بعناية لا يستحق كل هذا العناء. الكود هو بالتأكيد.
انتقل مباشرة لإعداد الأداة النهائية. يستغرق الإعداد أقل من 20 دقيقة.
يفترض الدليل أن لديك جهازين تحت تصرفك مع تثبيت Ubuntu 18.04.
واحد للبنية التحتية ( عامل ميناء ) ، والآخر لمراقبة العملية ( عملية ).

من المفترض أن الحزم التالية مثبتة بالفعل على عامل الميناء :
بوابة ، عامل ميناء ، عامل ميناء يؤلف

من المفترض أن الحزم التالية مثبتة بالفعل على العملية :
git ، php-common ، php-cli ، php-curl ، php-zip ، php-memcached ، الملحن
إذا كان لديك أي أسئلة في هذه المرحلة ، أقترح قضاء 15 دقيقة في قراءة المادة بأكملها.

عامل ميناء

 #    root-. # ,     TCP-: # 11300, 11211, 4444, 5930, 8080, 8081, 8082, 8083 #        # " root-"    git clone \ https://oauth2:YRGzV8Ktx2ztoZg_oZZL@git.ituse.ru/deploy/esb-infrastructure.git cd esb-infrastructure docker-compose up --build -d #      3     #   . #       web-. 

العملية

 #      . #      process-   , #     -  php- git clone \ https://oauth2:YRGzV8Ktx2ztoZg_oZZL@git.ituse.ru/deploy/clicker-noserver.git cd clicker-noserver composer update #  .       "XXXXXXXX" mv app/settings.php.dist app/settings.php #   . gnome-terminal \ --tab -e 'bash -c "php app/src/Process/noserver/singleProcess.php curl"' \ --tab -e 'bash -c "php app/src/Process/noserver/singleProcess.php timezone"' \ --tab -e 'bash -c "php app/src/Process/noserver/singleProcess.php whoer"' #  . ,     , #  : - log/list.proxy php app/src/Utils/givethejob.php ./log/list.proxy 

انتظر ، شاهد ما يحدث من خلال لوحة الويب (http: // ip-address-do-doer-machines: 8080).
ستكون النتيجة متوفرة في قائمة الانتظار الموجودة .

التكسير والتخطيط




يصف المخطط أعلاه تسلسل خطوات العملية ، والنتيجة المتوقعة لكل خطوة ، والموارد المطلوبة لإنشاء كل جزء (التفاصيل: المهمة 2 ، المهمة 3 ، المهمة 4،5،6 ).

في حالتي ، يحدث كل شيء على جهازي Ubuntu 18.04 . واحد منهم يتحكم في العملية. من ناحية أخرى ، يتم تشغيل عدة حاويات ترسية للبنية التحتية.

الأعذار والفشل


يتكون كل رمز الحزمة من ثلاثة أجزاء.
واحد منهم ليس لي (لاحظت أن هذا رمز أنيق وجميل). مصدر هذا الرمز هو packagist.org .

أنا شخصياً كتبت أخرى ، وحاولت جعلها مفهومة ومكرسة لحوالي أسبوع لهذا الجزء من الكود.

الباقي هو "إرث تاريخي صعب". تم إنشاء هذا الجزء من الكود على مدار فترة زمنية طويلة. بما في ذلك في وقت لم يكن لدي الكثير من المهارة في البرمجة.

هذا هو بالتحديد سبب موقع المستودعات على GitLab الخاص بي وحزم على Satis الخاص بي. للنشر على GitHub.com و packagist.org ، سيتطلب هذا الرمز معالجة ووثائق أكثر دقة.

جميع أجزاء الكود مفتوحة للاستخدام غير المحدود. المستودعات والحزم ستكون متاحة إلى الأبد.

ومع ذلك ، عند إعادة نشر الشفرة ، سأكون ممتنًا لك لنشر رابط لي أو لهذه المقالة.

قليلا عن العمارة


تتمثل الطريقة التي تم استخدامها لإنشاء أداتنا في كتابة (أو استخدام أداة مساعدة) لحل كل مهمة محددة. علاوة على ذلك ، لكل أداة مساعدة ، بغض النظر عن المهمة المراد حلها ، خاصيتان مشتركتان للجميع:

  • يمكن تشغيل الأداة بشكل مستقل عن الآخرين من سطر الأوامر مع المعلمات التي تحتوي على المهمة ؛
  • يمكن للأداة المساعدة إرجاع نتيجة التنفيذ إلى stdout (بعد تكوينها بطريقة معينة).

يتيح لك الحل الذي تم إنشاؤه بواسطة هذا المبدأ تغيير عدد معالجات المهام قيد التشغيل (العمال) لكل خطوة من خطوات العملية. سيؤدي عدد مختلف من العمال لكل خطوة إلى تعطل "0" للخطوات التي تتبع بسبب طول مهام معالجة الخطوات السابقة.

يعتمد الوقت المستغرق في الحصول على وحدة من نتيجة العملية (في حالتنا أنه وكيل تم التحقق منه) على عوامل خارجية (عدد الوكلاء غير المناسبين ، وزمن استجابة مورد خارجي ، إلخ).

من خلال تغيير عدد العمال لكل خطوة من خطوات العملية ، نقوم بتحويل هذا الاعتماد إلى اعتماد على عدد العمال قيد التشغيل (أي ، اعتمادًا على قدرات الحوسبة والقناة المعنية).

لمزامنة تشغيل الأجزاء المستقلة الفردية ، من الملائم استخدام خادم قائمة انتظار الرسائل باعتباره ناقل بيانات فردي. سيتيح لك تجميع نتائج الخطوات المكتملة في قائمة الانتظار ومنحهم الأداة المساعدة "الخطوة التالية" في الوقت المناسب كمدخلات.

قائمة انتظار الرسائل. MQ و ESB


كما المستوى الأدنى ( MQ ) سوف نستخدم beanstalkd . صغيرة وخفيفة الوزن وخالية من التكوين ، وهي متوفرة في حزمة deb وفي حاوية Docker ، وهي عامل قوي غير واضح. المستوى المنطقي ( ESB ) سوف ينفذ الكود في PHP .

سيتم استخدام فئتين للتنفيذ. esbTask و nextStepWorker .

esbTask

 class esbTask //   ,     { // immutable-; // "" (   ESB-),  payload //    //     "" .... } 

مثال من هذه الفئة يعمل على "معالجة" paylod من خلال خطوات العملية. يطبق مفهوم ESB عدة مبادئ / أنماط. اثنان منهم يستحقون الاهتمام بشكل منفصل:

  • حول المسار (تسلسل الخطوات) للعملية ، في كل نقطة زمنية من العملية ،
    لا أحد يعرف إلا المغلف الذي سينتقل ؛
  • يحتوي كل مغلف على ثلاثة اتجاهات محتملة للنتائج:
    • الخطوة التالية من العملية (استمرار طبيعي) ؛
    • خطوة الإيقاف (هدف الإيقاف - يتم تحديدها بواسطة الخطوة التالية ، إذا لم يكن هناك أي نقطة في مواصلة وضع العملية / الإيقاف) ؛
    • يتم تحديد الخطوة الخطأ (هدف إنهاء الطوارئ - بواسطة الخطوة التالية ، في حالة وجود خطأ عامل).

يتم تمثيل الكائن في قائمة الانتظار في json ، مخفي هنا ...
 // json- esbTask { //    (   esbTask) "_type":"App\\\\rebean\\\\payloads\\\\ESBtaskQueue", //  "task":"task:queue@XXX.XXX.XXX.XXX:11300", //    () "replyto":[ "othertask1:nextqueue1@yyy.XXX.XXX.XXX:11300", "othertask2:nextqueue2", "othertask3:nextqueue3", ], //    () "onerror":[ "error:errorsstep@zzz.XXX.XXX.XXX:11300", "error:errorsstep1", "error:errorsstep2", "error:errorsstep3" ], //     () "onstop":[ "stop:stopstep@kkk.XXX.XXX.XXX:11300", "stop:stopstep1", "stop:stopstep2", "stop:stopstep3" ], //   "payload":{ .... }, //   ... () "till":[ .... ], //     ... () //        // -  (LINUX-TimeStamp) "since":[ 1540073089.8833, ], // -     "points":1, //  .     "groupid":"" } 


nextStepWorker

تتم معالجة كل رسالة تظهر في قائمة الانتظار بواسطة العامل المسؤول عنها. للقيام بذلك ، يتم تنفيذ مجموعة الوظائف التالية:

 class nextStepWorker extends workerConstructor { //       //     esbTask //    () //    MQ- (beanstalkd) //     (Memcached) //     (MySQL) // : -  (  - ); -    stop-; -      (log, event, mq) .... } 

يتم تطبيق العمال لكل خطوة من خطوات العملية على أساس هذه الفئة. روتين كامل من معالجة ومعالجة وإرسال الخطوة التالية في الطريق ، والفصل يعتني.

الحل لكل مشكلة هو:

  1. الحصول على esbTask وتشغيل العامل.
  2. تنفيذ المنطق عن طريق تخزين النتائج في الحمولة ؛
  3. أكمل تنفيذ العامل (طارئ أو عادي - لا يهم).

إذا تم إكمال الخطوات ، فسيتم وضع النتيجة في قائمة الانتظار بالاسم المناسب وسيبدأ العامل التالي في المعالجة.

افعلها مرة واحدة. التحقق من توافر


في الواقع ، فإن إنشاء عامل لحل أي من المشاكل هو تنفيذ طريقة واحدة. مثال (مبسطة) لتطبيق حل مشكلة العمال 2 على النحو التالي:

 // app/src/Process/worker/curlChecker.php .... class curlChecker extends nextStepWorker { const PROXY_INFO = 'https://api.ipfy.me?format=json&geo=true'; const PROXY_TIMEOUT = '40'; const COMMAND = "curl -m %s -Lx http://%s:%s '%s'"; public function logic() { //    .  ..   payload extract($this->context()); //  defaults    payload  $curltimeout = $curltimeout ?? self::PROXY_TIMEOUT; $curlchecker = $curlchecker ?? self::PROXY_INFO; //     $line = sprintf( static::COMMAND, $curltimeout, $host, $port, $curlchecker ); exec($line, $info); //      // ( ,  stop-) $info = arrays::valid_json(implode('', info)); if (empty($info)) throw new \Exception("Bad proxy: $host:$port!", static::STATUS_STOP); //    payload $this->enrich(['info']) ->sets(compact('info')); } } 

يتم القيام ببعض الأسطر من التعليمات البرمجية وكل شيء و "المعار" إلى المرحلة التالية.

تحديد المنطقة الزمنية. TimeZoneDB وما هو ...


يتضمن الاختبار المتعمق للطلبات الواردة مطابقة وقت نافذة المستعرض بالوقت الذي يوجد فيه عنوان IP لمصدر الطلب.

لتجنب الشك من العدادات ، نحتاج إلى معرفة وقت الوكيل المحلي.

لمعرفة الوقت ، نأخذ خطوط الطول والعرض من نتائج الخطوة السابقة من العملية ونحصل على بيانات حول المنطقة الزمنية التي ستعمل فيها النسخة المستقبلية لنافذة المتصفح. سيتم توفير هذه البيانات لنا من قبل محترفين في مجال الوقت .

سيكون العامل المبسط لحل هذه المشكلة ( المهمة 3 ) مشابهًا تمامًا للمشكلة السابقة . الفرق الوحيد هو عنوان URL للطلب. يمكنك العثور على النسخة الكاملة في الملف:
// app / src / Process / worker / timeZone.php

قليلا عن البنية التحتية


بالإضافة إلى beanstalkd الموصوفة ، ستحتاج أداتنا إلى:

  • Memcached - لمهام التخزين المؤقت ؛
  • خادم سيلينيوم - مناسب لتشغيل برنامج سيلينيوم ويب درايف في حاوية منفصلة ويمكنك مراقبة العملية عبر VNC ؛
  • لوحات معلومات لمراقبة beanstald ، memcached ، و VNC .

للنشر السريع لكل هذا ، فإن Docker ( كيفية التثبيت على أوبونتو ) مريحة للغاية.

و "أوركسترا" بالنسبة له هو عامل إنشاء (أوامر للتثبيت) ...
 sudo apt-get -y update sudo apt-get -y install docker-compose 


تتيح لك هذه الأدوات تشغيل خوادم / عمليات تمت تهيئتها بالفعل وتهيئتها (بواسطة شخص سابق) في "حاويات" منفصلة لنظام التشغيل الأصل. للحصول على تفاصيل ، أوصي بالرجوع إلى هذه المقالة أو هذه المقالة.

لذلك ...

لبدء البنية التحتية ، تحتاج إلى عدة أوامر في وحدة التحكم:

 #   ,    docker- #     (   ) #    sudo -s git clone \ https://oauth2:YRGzV8Ktx2ztoZg_oZZL@git.ituse.ru/deploy/esb-infrastructure.git \ panels cd panels docker-compose up --build -d #   . 

نتيجة التنفيذ الناجح للأمر على الجهاز بعنوان XXX.XXX.XXX.XXX ،
سوف تتلقى مجموعة الخدمات التالية:
- XXX.XXX.XXX.XXX:11300 - شجرة الفاصولياء
- XXX.XXX.XXX.XXX:11211 - Memcached
- XXX.XXX.XXX.XXX-00-00444 - خادم السيلينيوم
- XXX.XXX.XXX.XXX:5930 - خادم VNC للتحكم في ما يحدث في Chrome
- XXX.XXX.XXX.XXX:8081 - لوحة ويب للتواصل مع Memcached (admin: pass)
- XXX.XXX.XXX.XXX:8082 - لوحة ويب للتواصل مع beanstalkd
- XXX.XXX.XXX.XXX:8083 - لوحة ويب للتواصل مع VNC (كلمة المرور: سر)
- XXX.XXX.XXX.XXX:8080 - لوحة الويب العامة

"معرفة ما إذا كان كل شيء في مكانه" ، "الدخول إلى وحدة التحكم في الحاوية" ، يمكن أن يكون "إيقاف البنية التحتية" بمثابة أوامر في المفسد.
 #   ,    docker-, #    ..../panels/ #    docker-compose ps # Name Command State Ports # ------------------------------------------------------------------------------------------------------------------------ # beanstalkd /usr/bin/beanstalkd Up 0.0.0.0:11300->11300/tcp # chrome start-cron Up 0.0.0.0:4444->4444/tcp, 0.0.0.0:5930->5900/tcp # memcached docker-entrypoint.sh memcached Up 0.0.0.0:11211->11211/tcp # nginx docker-php-entrypoint /sta ... Up 0.0.0.0:8443->443/tcp, 0.0.0.0:8080->80/tcp, # 0.0.0.0:8082->8082/tcp, 0.0.0.0:8083->8083/tcp, 9000/tcp # vnc /usr/bin/supervisord -c /e ... Up 0.0.0.0:8081->8081/tcp #       chrome docker exec -ti chrome /bin/bash #       docker-compose stop && docker rm $(docker ps -a -q) 

المهام 4،5،6 - الجمع بين في فائدة واحدة


بعد النظر في التكسير في المهام بالتفصيل ( المخطط أعلاه ) ، من السهل التأكد من أن واحدة فقط من المهام المتبقية ( المهمة 6 ) تعتمد على مورد خارجي. بأداء المهام مع أوقات تشغيل "مضمونة مشروطة" (مستقلة عن العوامل غير المنضبط) ، لن نحصل على مزايا إضافية لسرعة العملية برمتها. في هذا الصدد ، تم الجمع بين هذه المهام ( 4،5،6 ) في عامل واحد. يسمى ملف العامل:
// app / src / Process / worker / whoerChecker.php

قم بعمل إعدادات لمتصفح Chrome. الإضافات


تم تكوين Chrome بمرونة مع المكونات الإضافية.

المكون الإضافي لـ Chrome هو أرشيف يحتوي على ملف manifest.json . ويصف البرنامج المساعد. يحتوي الأرشيف أيضًا على مجموعة من JavaScript و html و css وغيرها من الملفات التي يحتاجها البرنامج المساعد ( التفاصيل ).

في حالتنا ، سيتم تنفيذ أحد ملفات JavaScript في سياق نافذة عمل Chrome وستدخل جميع الإعدادات اللازمة حيز التنفيذ.

نحتاج فقط إلى أخذ قالب البرنامج المساعد واستبدال البيانات اللازمة (بروتوكول التفاعل والعنوان والمنفذ أو المنطقة الزمنية) للخادم الوكيل قيد الاختبار في الأماكن الصحيحة.

مقتطف من الكود الذي يجعل الأرشيف:

 // app/src/Chrome/proxyHelper.php .... class proxyHelper extends sshDocker{ .... // $name -  - // $files - [ ... '   -' => '', ...] protected function buildPlugin(string $name, array $files) { $this->last = "$this->cache/$name"; if (!file_exists("$this->last")) { $zip = new \ZipArchive(); $zip->open("$this->last", \ZipArchive::CREATE | \ZipArchive::OVERWRITE); foreach ($files as $n => $data) { $zip->addFromString(basename($n), $data); } $zip->close(); } $this->all[] = $this->last; $this->all = array_unique($this->all); return $this; } .... } 

تم العثور على قالب المكون الإضافي لضبط البروكسي في بنك الخنازير لنتائج عمل الأشخاص الذين يحبون مهنتهم وتغييره في جزء البروتوكول وإضافته إلى المستودع.

نافذة تغيير الوقت


لتغيير الوقت العالمي لمثيل Chrome قيد التشغيل ، نحتاج إلى استبدال window.Date بفئة مع وظائف مماثلة ، ولكن صالحة في المنطقة الزمنية المناسبة.

إنني أقدر حقًا عمل سامبو جوستيلا . تم إنشاء البرنامج النصي للاختبار التلقائي لواجهة المستخدم ، ولكن بعد تطبيق بعض التحسينات.

هناك فارق بسيط هنا أريد أن ألفت انتباهكم إليه. يرتبط بسياق البرامج النصية الموضحة في manifest.json .

السر كله هو أن السياق العام (السياق الذي يتم فيه تشغيل البرنامج النصي الرئيسي للمكون الإضافي وتعيين الإعدادات ، على سبيل المثال ، متصل بالشبكة) معزول عن سياق علامة التبويب التي يتم تحميل الصفحة بها.

من الناحية العملية ، وجد أن التأثير على النموذج الأولي للفئة في السياق العالمي لم يؤد إلى تغييره في علامة التبويب. ومع ذلك ، بعد تسجيل البرنامج النصي في الصفحة التي تم تحميلها بالفعل وتنفيذها قبل الآخرين ، تم حل المشكلة.

يتم تمثيل الحل بواسطة جزء التعليمات البرمجية التالي:

 // app/chromePlugins/timeShift/content.js //     var s = document.createElement('script'); //        s.src = chrome.extension.getURL('timeshift.js'); //      (document.head || document.documentElement).appendChild(s); 

إعدادات الوكيل


يعد إعداد خادم وكيل في Chrome أمرًا بسيطًا إلى الحد الذي يجعلني أخفي رمز js في المفسد
 // app/chromePlugins/proxy/background.js var config = { mode: "fixed_servers", rules: { singleProxy: { scheme: "%scheme", host: "%proxy_host", port: parseInt(%proxy_port) }, bypassList: ["foobar.com"] } }; chrome.proxy.settings.set({value: config, scope: "regular"}, function () { }); function callbackFn(details) { return { authCredentials: { username: "%username", password: "%password" } }; } chrome.webRequest.onAuthRequired.addListener( callbackFn, {urls: ["&gtall_urls&lt"]}, ['blocking'] ); 


مسار الإضافات كروم


تتم تسمية جميع المكونات الإضافية وفقًا للمخطط وتتم إضافتها إلى المجلد المؤقت للجهاز الذي يتحكم في العملية.
// مخطط التسمية للمكون الإضافي الوكيل:
الوكيل - [عنوان] - [منفذ] - [بروتوكول]>
التحكم الزمني - ["-" | ""] - [shift_in_minutes_from_GMT] .zip

بعد ذلك ، نحتاج إلى تثبيت هذه المكونات الإضافية في حاوية عامل ميناء تعمل على الجهاز المسؤول عن البنية التحتية.

سنفعل هذا مع ssh.للقيام بذلك ، قابلت phpseclib (حتى نأسف له لاحقًا). مفتونًا بالسلوك غير العادي للمكتبة ، قضيت يومًا في دراستها.

سيعمل عميل وحدة التحكم ssh بشكل أفضل هنا وسيعمل بشكل أسرع ، لكن المهمة قد أنجزت بالفعل.

بالنسبة للمستوى المنخفض (العمل مع SFTP و SSH) ، تكون الفئة الأساسية مسؤولة (أدناه). سيؤدي استبدال هذه الفئة إلى استبدال phpseclib بعميل وحدة التحكم.

 // app/src/Chrome/sshDocker.php //    (DOCKER_HOST, DOCKER_USER, DOCKER_PASS) //   : app/settings.php //      .... class sshDocker { .... //  .     docker //    .         // : app/techs.php const EXEC_DOCKER = DOCKER_BIN_PATH . "/docker exec -i %s %s"; .... //     sudo    (  ),  DOCKER_USER -  protected function sudo(string $command, string $expect = '.*'){...} //     Docker-,      //       -    self::EXEC_DOCKER protected function execDocker(string $command, string $expect){...} .... } 

مشتقة من قاعدة sshDocker ومن فئة proxyHelper المعروفة بالفعل ، فهي لا تنتج المكونات الإضافية فحسب ، بل تضعها أيضًا في مجلد مؤقت من حاوية البنية التحتية.

 // app/src/Chrome/proxyHelper.php .... class proxyHelper extends sshDocker { .... public static function new(string $docker, $plugins) { return (new self($docker, $plugins)) ->setupPlugins(); } .... } 

إطلاق Chome مع الإعدادات


سيساعدنا Selenium Server في تشغيل Chrome المخصص . Selenium Server هو إطار تم إنشاؤه بواسطة فريق FaceBook خصيصًا لاختبار واجهات WEB. يتيح إطار العمل للمطور محاكاة أي إجراء مستخدم برمجيًا في نافذة متصفح (باستخدام Chrome أو Firefox ). خادم Selenium Server مُكيف للاستخدام مع العديد من اللغات وهو في الواقع أداة قياسية لكتابة البرامج النصية للاختبار. أفضل طريقة للحصول على إصدار جديد للاستخدام في المشروع:









 composer require facebook/webdriver 

التكوين التقليدي للمثيل الرئيسي لكائن Server Selenium (RemoteWebDriver) بدا مطولًا بالنسبة لي.
 // URL- $url = "https://example.com/books/196/empire-v-povest-o-nastoyashem-sverhcheloveke"; // URL,     (Selenium Server) $server = 'http://' . DOCKER_HOST . '/wd/hub'; //   ,      $options = new ChromeOptions(); $options->addArguments(array( '--disable-notifications' )); //    - $capabilities = DesiredCapabilities::chrome(); $capabilities->setCapability(ChromeOptions::CAPABILITY, $options); //        5000     URL $driver = RemoteWebDriver::create($server, $capabilities, 5000); $page = $driver->get($url); 


وبالتالي ، قمت بتقليل كل ذلك قليلاً ، مع تحسين التكوين لاحتياجاتي:

 // app/src/Process/worker/whoerChecker.php .... class whoerChecker extends nextStepWorker { //    : app/settings.php // URL Selenium Server const SELENIUM_SERVER = CHVM; //  - const DOCKER_NAME = DOCKER_NAME; .... public function config() .... //        : // $driver = RemoteWebDriver::create($server, $capabilities, 5000); $chrome = Chrome::driver( static::SELENIUM_SERVER, Chrome::capabilities(static::DOCKER_NAME, $plugins), 5000 ); .... } .... 

العين تتمسك على الفور إلى الإضافات $. الإضافات $ هي بنية بيانات مسؤولة عن تكوين الإضافات. لكل دليل واستبدال العناصر النائبة في ملفات JavaScript الإضافية.

تم وصف الهيكل في ملف التطبيق / plugs.php وهو جزء من التطبيق / settings.php للخيارات العامة.
 // app/plugs.php const PLUGS = [ 'timeshift' => [ 'path' => PROJECTPATH . '/app/chromePlugins/timeShift', 'files' => ['manifest.json', 'timeshift.js', 'content.js'], 'fields' => ['%addsminutes' => 'timeshift'] ], 'proxy' => [ 'path' => PROJECTPATH . '/app/chromePlugins/proxy', 'files' => ['manifest.json', 'background.js'], 'fields' => [ '%proxy_host' => 'host', '%proxy_port' => 'port', '%scheme' => 'scheme', '%username' => 'user', '%password' => 'pass' ] ] ]; 


تحليل الصفحة باستخدام Selenium WebDriver بسيط للغاية.

 .... $url = 'https://__/_-_'; $page = $chrome->get($url); .... //   xPath-   $xpath = '/html[1]/body[1]/div[1]/div[1]/div[1]/div[2]/div[1]/div[1]/div[1]/div[1]/strong[1]'; $element = page->findElement(WebDriverBy::xpath($xpath)); .... //   $text = $element->getText(); // HTML- $html = $element->>getAttribute('innerHTML'); .... 

كما كتبت بالفعل ، يتم تنفيذ جميع هذه الإجراءات من خلال فائدة الخطوة الثالثة ( المهمة 4،5،6 ):
// app / src / Process / worker / whoerChecker.php
في الختام لوصف العمل مع Selenium Server ، أود أن ألفت انتباهكم إلى حقيقة أنه عند استخدام هذه التكنولوجيا على نطاق صناعي (من 1000 إلى 3000 صفحة) ، فإنه من غير المألوف أن تنتهي جلسة عمل مع Selenium Server بشكل غير صحيح. النافذة هي المالك. ويمكن لهذه النوافذ تتراكم الكثير.

تم النظر في عدة طرق لمكافحة "الدبابيس". العمل "أكل" 2 أيام. الأكثر فعالية كان كرون . تحول التثبيت الصحيح والتكوين في الحاوية Docker إلى مهمة منفصلة ، وصفها بدقة وبشكل دقيق بواسطة renskiy ، في مقال مخصص لهذا الموضوع فقط (والذي فوجئت به).

تم وصف إعادة الإنشاء التلقائي لصورة Docker الأصلية وتثبيت العديد من البرامج النصية لإغلاق الدبابيس وتنظيف المكونات الإضافية غير المستخدمة في مستودع docker-compose.yml ، مستودع البنية التحتية . يتم تعيين تردد التنظيف في ملف killcron من نفس المستودع.

WebRTC


على الرغم من أننا قد حددنا بالفعل الوقت الصحيح ، وحركة المرور في متصفحنا تمر عبر وكيل ، لا يزال من الممكن اكتشافنا.

بالإضافة إلى فارق التوقيت (المتصفح وعنوان IP) ، هناك مصدران آخران لإثبات هوية "الجلوس خلف الوكيل". هذه هي تقنيات فلاش و WebRTC مضمن في المتصفح. تم تعطيل الفلاش في متصفحنا ، WebRTC ليس كذلك.

سبب كل من احتمالات الفشل هو نفسه - الحزم UDP في كل مكان وذكيا . بالنسبة إلى WebRTC ، يوجد هذان المنفذان : 3478 و 19302 .

لإيقاف خروج الكشافة من حاوية الكروم ، يتم تطبيق قاعدة iptables على الجهاز المضيف مع حاويات البنية التحتية:

 iptables -t raw -I PREROUTING -p udp -m multiport --dports 3478,19302 -j DROP 

نفس proxyHelper بتنفيذ هذه المهمة.

بقية العمال


لتحقيق الهدف بنجاح - تنفيذ "النقر" على الموقع الهدف من خلال وكيل مجهول ، نحتاج إلى عامل آخر.

سيكون نسخة مقطوعة من whoerChecker . أعتقد أن أفعل ذلك بمفردي ، باستخدام كل شيء مكتوب ، لن يكون الأمر صعبًا.

نتيجة العملية برمتها من دخول طابور الواقعة ، ويحتوي على البيانات الموجودة على "درجة" كل عدم الكشف عن هويته مصادقة عنوان الملقم الوكيل.

عند "اللعب" ضد العدادات ، فإن الشيء الرئيسي الذي يجب تذكره هو عدم الكشف عن هويتك وعدم القيام بزيارات آلية. يتم توفير الامتثال لمبدأ "لا تنفك النقرات" من خلال إمكانية تنظيم الإجراءات وفقًا لجدول زمني ، وهو مضمن في esbTask ( بما في ذلك حقل مغلف ESB الخاص بنا ).

إذا حاولت القيام بكل شيء بعناية ، فسيكون قياس ياندكس للموقع المستهدف مشابهًا للشكل التالي.



كيفية وضع كل شيء معا


لذلك ، أعطيت:

  • الأدوات المساعدة التي تكون قادرة على قبول "كمدخل" (كوسيطة سطر أوامر) esbTask في شكل سلسلة json وتنفيذ بعض المنطق ، وإرسال النتائج إلى beanstalkd ؛
  • وضع الرسائل في قائمة انتظار ( MQ ) ، استنادًا إلى beanstalkd ؛
  • آلة لينكس (آلة عملية) ؛

مع هذا "معطى" ، عادة ما أستخدم libevent و React PHP . كل هذا ، بالإضافة إلى العديد من الأدوات ، يتيح لك التحكم في عدد مثيلات المعالج (ضمن الحدود المحددة) لكل مرحلة من مراحل العملية تلقائيًا.

ومع ذلك ، بالنظر إلى حجم المقال وتفاصيل الموضوع ، سأكون سعيدًا لوصف كل هذا في مقالة منفصلة. هذه المقالة هي تقنية noserver . الاشياء المستقبلية هي " الخادم ".
يرتبط تاريخ نشره باهتمامك ، عزيزي القارئ.
. , ,… . , , , , , .

habr , . , , .

. , " server ", README.md .

في " noserver " ، ستقوم مثيل واحد بمعالجة قائمة انتظار واحدة (خطوة عملية واحدة). هذا النهج لا يمكن إلا أن تغضب الأرواح التي أستخدمها عند تصحيح الأخطاء للعمال.

اعتمادًا على سرعة المعالجة التي تحتاج إليها ، يمكنك بدء تشغيل العديد من النسخ التي تريدها "يدويًا".

قد يبدو مثل هذا:

 // app/src/Process/noserver/singleProcess.php //   ,    //   include __DIR__ . '/../../../settings.php'; use App\ESB\pipeNcacheService; use App\arrayNstring\queueDSN; use App\arrayNstring\timeSpent; use App\arrayNstring\progressString; //    $path = __DIR__ . '/../worker'; //   $queues = array_keys(WORKERS); $queue = $argv[1] ?? end($queues); $queue = strtolower($queue); if (!in_array($queue, $queues)) die("php $argv[0] <queue_name>" . PHP_EOL); //  - $progress = new progressString("Listenning... Idle: ", 40, 20); // ,      $stopwatch = timeSpent::start(); //    beanstalkd- list($worker, $task) = WORKERS[$queue]; $procid = ['procid' => posix_getpid()]; //   beanstalkd  Memcached, //     ( ) $dsn = new queueDSN($task, $queue, ...QUEUE_SERVER); //     ESB- $pnc = new pipeNcacheService($dsn); $pipe = $pnc->getPipe(); echo "Start listener for queue: $queue." . PHP_EOL; echo "Press Ctrl-C to stop listener." . PHP_EOL; //      //       while (true) { try { $job = $pipe->watch($queue) ->reserve(1); $now = new DateTime(); $opts = json_encode($pipe->getPayload($job) + $procid); $pipe->delete($job); echo PHP_EOL . "Task recived at: " . $now->format('H:i:s') . " Starting worker: $worker. "; $stopwatch = timeSpent::start(); exec("php $path/$worker $opts", $out); echo "Finished. Time spent: $stopwatch" . PHP_EOL; $stopwatch = timeSpent::start(); } catch (Throwable $exception) { echo $progress($stopwatch('%I:%S', null, $now)); } } 

البداية الغريبة للعامل ملفتة للنظر ... على الرغم من حقيقة أن كل عامل من عناصر PHP ، فقد استخدمت exec (...) .

تم ذلك لتوفير الوقت ، حتى لا يتم إنشاء عمال منفصلين لـ " noserver " أو عدم تغيير العامل لغرض البدء في وضع " server ".

بضع كلمات عن التكوين والنشر


ثوابت التكوين


ملف التكوين لمثيلك هو التطبيق / settings.php . يجب أن يتم إنشاؤه بواسطتك فورًا بعد استنساخ المستودع. للقيام بذلك ، أعد تسمية التطبيق / settings.php.dist للملف . يتم وصف جميع الثوابت داخليا.

التطبيق / settings.php ، من بين أشياء أخرى ، يتضمن ملفات مع الثوابت الأخرى.
- يحتوي التطبيق / queues.php على أسماء قوائم الانتظار والوظائف
- يحتوي التطبيق / plugs.php على وصف لمكونات Chrome الإضافية
- يحتوي التطبيق / techs.php على ثوابت محسوبة

المرافق


لتوفير الراحة في معالجة نتائج العملية ووضع المهام ، هناك العديد من الأدوات المساعدة. يتم تشغيل الأدوات المساعدة من سطر الأوامر. قدمت مع وصف الحجة. تقع: التطبيق / src / Utils .
 backup.php - يحفظ قوائم الانتظار إلى ملف
    clear.php - ينظف الطوابير
    export.php - يتم تصديره من ملف به قائمة انتظار محفوظة 
                     أزواج العنوان: ميناء
    Givethejob.php - وظائف المهام لهذه العملية 
                     (المصدر - العنوان: مربع التحرير والسرد المنفذ).
                     يمكن استبعاد بعض العناوين من القائمة
    restore.php - استعادة قائمة انتظار محفوظة 

صقل العمال


عند استخدام العاملين الكتابيين ، قد يكون من المناسب استخدام خيارات التكوين التالية:

 // app/src/Process/worker/curlChecker.php .... $worker = new curlChecker( [ //    curlChecker::WORKER => 'curlchecker', //  beanstalkd curlChecker::PIPE_HOSTPORT => implode(':', QUEUE_SERVER), //  Memcached curlChecker::CACHE_HOSTPORT => implode(':', MEMCACHED), // ,    . //    -   curlChecker::DB_SCRIPT => __DIR__ . '/../../../confdb.php', // ,       // (        -) curlChecker::INFO_START => CURL_START, // ,        // (        -) curlChecker::INFO_END => CURL_END, //  ,     //    //        curlChecker::INFO_ADDS_END => ['host', 'port'] ], ['setupworker', 'config', 'logic'] ); .... 


النشر


يفترض الدليل أن لديك جهازين تحت تصرفك مع تثبيت Ubuntu 18.04 .
واحد للبنية التحتية ( عامل ميناء ) ، والآخر لمراقبة العملية ( عملية ).

عامل ميناء

 #    root-. # ,     TCP-: # 11300, 11211, 4444, 5930, 8080, 8081, 8082, 8083 #   . sudo -s apt -y update apt -y install git snap snap install docker apt -y install docker-compose # C       # " root-"    cd ~ git clone \ https://oauth2:YRGzV8Ktx2ztoZg_oZZL@git.ituse.ru/deploy/esb-infrastructure.git cd esb-infrastructure docker-compose up --build -d #      3     #   . #       web-. 

العملية

 #      . #   . sudo apt -y update sudo apt -y install git php-common php-cli php-curl php-zip php-memcached composer # C     process-   , #     -  php- cd /var/www git clone \ https://oauth2:YRGzV8Ktx2ztoZg_oZZL@git.ituse.ru/deploy/clicker-noserver.git cd clicker-noserver composer update #  .       "XXXXXXXX" mv app/settings.php.dist app/settings.php #   . gnome-terminal \ --tab -e 'bash -c "php app/src/Process/noserver/singleProcess.php curl"' \ --tab -e 'bash -c "php app/src/Process/noserver/singleProcess.php timezone"' \ --tab -e 'bash -c "php app/src/Process/noserver/singleProcess.php whoer"' #  . ,     , #  : - log/list.proxy php app/src/Utils/givethejob.php ./log/list.proxy 

انتظر ، شاهد ما يحدث من خلال لوحة الويب (http: // ip-address-do-doer-machines: 8080).
ستكون النتيجة متوفرة في قائمة الانتظار الموجودة .

وفي الختام


والمثير للدهشة أن كتابة هذه المقالة وتحريرها استغرقتا وقتًا أطول من كتابة الكود نفسه.

في رأيي كان يمكن أن يكون على العكس من ذلك (والفرق في الوقت المناسب يمكن أن تكون عدة أضعاف)، إن لم يكن اثنين الأيديولوجيات: الرسالة قائمة الانتظار و المؤسسة على خدمة الحافلات .

سأكون سعيدًا جدًا إذا وجدت أن النهج المقدم لكتابة التطبيقات مفيد ، فإن الحمل على أجزاء مختلفة غير واضح في مرحلة التصميم.

شكرا لك

Source: https://habr.com/ru/post/ar432038/


All Articles