
خليفة Undetected-Chromedriver. يوفر إطار عمل سريع للغاية لأتمتة الويب، وكشط الويب، والروبوتات، وأي أفكار إبداعية أخرى تعوقها عادةً أنظمة مكافحة الروبوتات المزعجة مثل Captcha / CloudFlare / Imperva / hCaptcha.
التواصل المباشر يوفر مقاومة أفضل ضد جدران حماية تطبيقات الويب (WAF’s)، بينما يحصل الأداء على دفعة هائلة. هذه الوحدة، على عكس undetected-chromedriver، غير متزامنة بالكامل.
ما يجعل هذه الحزمة مختلفة عن الحزم الأخرى المعروفة، هو التحسين لتبقى غير مكتشفة لدى معظم حلول مكافحة الروبوتات.
نقطة التركيز الأخرى هي سهولة الاستخدام والنمذجة السريعة، لذا توقع أن يعمل الكثير -كما هو-،
مع وجود قيم افتراضية لأفضل الممارسات لمعظم معاملات الدوال.
باستخدام سطر أو سطرين، تكون جاهزة للعمل، مع توفير إعدادات بأفضل الممارسات افتراضيًا.
وتقوم بتنظيف الملفات التي تم إنشاؤها (الملف الشخصي) بعد ذلك.
من المعروف أنها تعمل مع
بينما سهولة الاستخدام والراحة أمر مهم، من السهل أيضًا تخصيص كل شيء بالكامل باستخدام المجموعة الكاملة من نطاقات CDP والأساليب والأحداث المتاحة.
لا اعتماد على ملف chromedriver الثنائي أو على Selenium
جاهزة للعمل في سطر واحد من التعليمات البرمجية*
تستخدم ملفًا شخصيًا جديدًا في كل تشغيل، وتنظف عند الخروج
حفظ وتحميل ملفات تعريف الارتباط إلى ملف لتجنب تكرار خطوات تسجيل الدخول المملة
tab.find("sometext")
tab.find_all("sometext")
tab.select("a[class*=something]")
tab.select_all("a[href] > div > img")
بحث ذكي وفعّال عن العناصر، بواسطة المحدد أو النص، بما في ذلك محتوى iframe.
يمكن استخدام هذا أيضًا كشرط انتظار لظهور عنصر، حيث سيعيد المحاولة
طوال مدة حتى يتم العثور عليه. لذا يمكن استخدام await tab.select('body')
كمؤشر على ما إذا كانت الصفحة قد تم تحميلها.
تبحث طريقة find وفقًا للنص، لكنها لن تعيد أول عنصر مطابق بشكل ساذج،
بل ستطابق المرشحين وفقًا لأقرب طول نص مطابق (الأقصر يفوز)،
وهذا يجعل عمليات البحث مثل tab.find('accept all') تعيد زر ملفات تعريف الارتباط الفعلي بدلاً من
سكربت في الترويسات
يمكنه الاتصال بجلسة تصحيح أخطاء chrome قيد التشغيل
__repr__ وصفي للعناصر، يمثل العنصر بتنسيق html
دالة مساعدة لتحويل مثيل undetected_chromedriver.Chrome قيد التشغيل إلى مثيل nodriver.Browser والمتابعة من هناك
محشوة بالمساعدين والدوال المساعدة لمعظم العمليات الأكثر استخدامًا وأهمية
تمت إعادة كتابة أجزاء لاستخدام اتصالات مسطحة في البروتوكول.
لماذا؟
- يتم تضمين iframes في معظم العمليات.
- حصلت tab على دالة جديدة: await tab.get_frames()
والتي ستعيد Iframes قابلة للفحص.
- ستشمل find() إطارات iframes، لذا يمكنك حتى البحث عن "تحقق من أنك إنسان" و
النقر على مربع التحقق في تحديات js.
نظرًا لأن هذا تطلب قدرًا كبيرًا من إعادة الكتابة، يرجى الاختبار بدقة، خاصة إذا كنت تدير مشاريع كبيرة.
tab.xpath(selector, timeout=2.5)ابحث عن العقد باستخدام محدد xpath! انظر tab xpath في وثائق api
tab.cf_verify()يعثر على مربع الاختيار وينقر عليه بنجاح يعمل هذا فقط عندما لا تكون في وضع الخبير. مدمج حاليًا باللغة الإنجليزية فقط يتطلب تثبيت حزمة opencv-python
tab.bypass_insecure_connection_warning()دالة مساعدة لتحذير الصفحة غير الآمنة. على سبيل المثال عندما تكون الشهادة غير صالحة.
tab.open_external_debugger()تتيح لك فحص التبويب دون كسر اتصالك
tab.get_local_storage()الحصول على محتوى التخزين المحلي
tab.set_local_storage(dict)تعيين محتوى التخزين المحلي
tab.add_handler(someEvent, callback)قد تقبل دالة الاستدعاء وسيطًا واحدًا (event)، أو وسيطين (event, tab).
start(expert=True)تقوم ببعض الاختراقات للمستخدمين الأكثر خبرة. تعطل أمان الويب والتجارب الأصلية، كما تضمن أن تكون shadow-roots مفتوحة دائمًا. لكن هذا يجعلك أكثر قابلية للاكتشاف!
تحتاج إلى تثبيت chrome (أو متصفح قائم على chromium) ويفضل أن يكون في الموقع الافتراضي على الجهاز الذي تستخدم فيه هذه الحزمة.
عند التشغيل على جهاز بدون شاشة، مثل AWS أو أي بيئة أخرى لا يوجد بها عرض، من الأفضل استخدام أداة Xvfb لمحاكاة شاشة. بدلاً من ذلك، يمكن استخدام هذه الحزمة في وضع بدون شاشة.
pip install nodriver
pip install -U nodriver
الهدف من هذا المشروع (تمامًا مثل undetected-chromedriver، في وقت ما منذ زمن بعيد) هو إبقاؤه قصيرًا وبسيطًا، بحيث يمكنك فتح محرر أو جلسة تفاعلية بسرعة، كتابة أو لصق بضعة أسطر والانطلاق.
import nodriver as uc
async def main():
browser = await uc.start()
page = await browser.get('https://www.nowsecure.nl')
... further code ...
if __name__ == '__main__':
# since asyncio.run never worked (for me)
uc.loop().run_until_complete(main())
سأستبعد الكود التمهيدي غير المتزامن هنا
from nodriver import *
browser = await start(
headless=False,
user_data_dir="/path/to/existing/profile", # by specifying it, it won't be automatically cleaned up when finished
browser_executable_path="/path/to/some/other/browser",
browser_args=['--some-browser-arg=true', '--some-other-option'],
lang="en-US" # this could set iso-language-code in navigator, not recommended to change
)
tab = await browser.get('https://somewebsite.com')
سأستبعد الكود التمهيدي غير المتزامن هنا
from nodriver import *
config = Config()
config.headless = False
config.user_data_dir="/path/to/existing/profile", # by specifying it, it won't be automatically cleaned up when finished
config.browser_executable_path="/path/to/some/other/browser",
config.browser_args=['--some-browser-arg=true', '--some-other-option'],
config.lang="en-US" # this could set iso-language-code in navigator, not recommended to change
)
import nodriver
async def main():
browser = await nodriver.start()
page = await browser.get('https://www.nowsecure.nl')
await page.save_screenshot()
await page.get_content()
await page.scroll_down(150)
elems = await page.select_all('*[src]')
for elem in elems:
await elem.flash()
page2 = await browser.get('https://twitter.com', new_tab=True)
page3 = await browser.get('https://github.com/ultrafunkamsterdam/nodriver', new_window=True)
for p in (page, page2, page3):
await p.bring_to_front()
await p.scroll_down(200)
await p # wait for events to be processed
await p.reload()
if p != page3:
await p.close()
if __name__ == '__main__':
# since asyncio.run never worked (for me)
uc.loop().run_until_complete(main())
أتمتة إنشاء حساب Twitter/X
A more concrete example, which can be found in the ./example/ folder,
shows a script to create a twitter account
```python
import random
import string
import logging
logging.basicConfig(level=30)
import nodriver as uc
months = [
"january",
"february",
"march",
"april",
"may",
"june",
"july",
"august",
"september",
"october",
"november",
"december",
]
async def main():
driver = await uc.start()
tab = await driver.get("https://twitter.com")
# wait for text to appear instead of a static number of seconds to wait
# this does not always work as expected, due to speed.
print('finding the "create account" button')
create_account = await tab.find("create account", best_match=True)
print('"create account" => click')
await create_account.click()
print("finding the email input field")
email = await tab.select("input[type=email]")
# sometimes, email field is not shown, because phone is being asked instead
# when this occurs, find the small text which says "use email instead"
if not email:
use_mail_instead = await tab.find("use email instead")
# and click it
await use_mail_instead.click()
# now find the email field again
email = await tab.select("input[type=email]")
randstr = lambda k: "".join(random.choices(string.ascii_letters, k=k))
# send keys to email field
print('filling in the "email" input field')
await email.send_keys("".join([randstr(8), "@", randstr(8), ".com"]))
# find the name input field
print("finding the name input field")
name = await tab.select("input[type=text]")
# again, send random text
print('filling in the "name" input field')
await name.send_keys(randstr(8))
# since there are 3 select fields on the tab, we can use unpacking
# to assign each field
print('finding the "month" , "day" and "year" fields in 1 go')
sel_month, sel_day, sel_year = await tab.select_all("select")
# await sel_month.focus()
print('filling in the "month" input field')
await sel_month.send_keys(months[random.randint(0, 11)].title())
# await sel_day.focus()
# i don't want to bother with month-lengths and leap years
print('filling in the "day" input field')
await sel_day.send_keys(str(random.randint(0, 28)))
# await sel_year.focus()
# i don't want to bother with age restrictions
print('filling in the "year" input field')
await sel_year.send_keys(str(random.randint(1980, 2005)))
await tab
# let's handle the cookie nag as well
cookie_bar_accept = await tab.find("accept all", best_match=True)
if cookie_bar_accept:
await cookie_bar_accept.click()
await tab.sleep(1)
next_btn = await tab.find(text="next", best_match=True)
# for btn in reversed(next_btns):
await next_btn.mouse_click()
print("sleeping 2 seconds")
await tab.sleep(2) # visually see what part we're actually in
print('finding "next" button')
next_btn = await tab.find(text="next", best_match=True)
print('clicking "next" button')
await next_btn.mouse_click()
# just wait for some button, before we continue
await tab.select("[role=button]")
print('finding "sign up" button')
sign_up_btn = await tab.find("Sign up", best_match=True)
# we need the second one
print('clicking "sign up" button')
await sign_up_btn.click()
print('the rest of the "implementation" is out of scope')
# further implementation outside of scope
await tab.sleep(10)
driver.stop()
# verification code per mail
if __name__ == "__main__":
# since asyncio.run never worked (for me)
# i use
uc.loop().run_until_complete(main())