
Undetected-Chromedriverの後継。Web自動化、Webスクレイピング、ボット、そして通常Captcha / CloudFlare / Imperva / hCaptchaのような迷惑なアンチボットシステムによって妨げられるその他の創造的なアイデアのための高速なフレームワークを提供します。
直接通信により、Webアプリケーションファイアウォール(WAF)に対する耐性がさらに向上し、 パフォーマンスも大幅に向上します。 このモジュールは、undetected-chromedriverとは異なり、完全に非同期です。
このパッケージが他の既知のパッケージと異なる点は、 ほとんどのアンチボットソリューションに対して検出されないように最適化されていることです。
もう一つの重点は、使いやすさと迅速なプロトタイピングです。そのため、多くのメソッドパラメータにはベストプラクティスのデフォルト値が設定されており、多くのことがそのまま動作することを期待してください。
1行または2行のコードで起動し、デフォルトでベストプラクティスの設定が適用されます。また、作成されたファイル(プロファイル)は終了後にクリーンアップされます。
以下で動作することが確認されています:
使いやすさと利便性は重要ですが、 利用可能なCDPドメイン、メソッド、イベントの全配列を使用して、すべてを完全にカスタマイズすることも簡単です。
chromedriverバイナリやSeleniumへの依存なし
1行のコードで起動可能*
実行ごとに新しいプロファイルを使用し、終了時にクリーンアップ
ログイン手順を繰り返さないためにクッキーをファイルに保存/読み込み
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')のような検索で、ヘッダー内のスクリプトではなく実際のCookieボタンが返されます。
実行中のChromeデバッグセッションに接続可能
要素をHTMLとして表現する、説明的な__repr__
実行中のundetected_chromedriver.Chromeインスタンスをnodriver.Browserインスタンスに変換して続行するユーティリティ関数
最も使用され重要な操作のためのヘルパーおよびユーティリティメソッドが豊富
プロトコルでフラット接続を使用するように一部を書き換えました。
なぜか?
- iframeがほとんどの操作に含まれるようになりました。
- タブに新しいメソッド: await tab.get_frames()
これにより、検査可能なIframeが返されます。
- find()はiframeを含むようになったため、「verify you are human」を検索して、JSチャレンジの確認チェックボックスをクリックすることもできます。
この書き換えにはかなりの修正が必要だったため、特に大規模なプロジェクトを実行する場合は、十分にテストしてください。
tab.xpath(selector, timeout=2.5)xpathセレクタを使用してノードを見つけます! APIドキュメントのtab xpathを参照
tab.cf_verify()チェックボックスを見つけて正常にクリックします これはエキスパートモードでない場合にのみ機能します。 現在は英語のみ組み込み済み opencv-pythonパッケージのインストールが必要です
tab.bypass_insecure_connection_warning()安全でないページの警告用の便利メソッド。 例えば、証明書が無効な場合など。
tab.open_external_debugger()接続を切断せずにタブを検査できます
tab.get_local_storage()localstorageの内容を取得
tab.set_local_storage(dict)localstorageの内容を設定
tab.add_handler(someEvent, callback)コールバックは1つの引数(イベント)、または2つの引数(イベント、タブ)を受け取ることができます。
start(expert=True)より経験豊富なユーザー向けのハッキングを行います。ウェブセキュリティとオリジントライアルを無効にし、シャドウルートが常に開いていることを保証します。ただし、検出されやすくなります!
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", # 指定すると、終了時に自動クリーンアップされません
browser_executable_path="/path/to/some/other/browser",
browser_args=['--some-browser-arg=true', '--some-other-option'],
lang="en-US" # navigatorのiso-language-codeを設定します。変更は推奨しません
)
tab = await browser.get('https://somewebsite.com')
ここでは非同期のボイラープレートは省略します
from nodriver import *
config = Config()
config.headless = False
config.user_data_dir="/path/to/existing/profile", # 指定すると、終了時に自動クリーンアップされません
config.browser_executable_path="/path/to/some/other/browser",
config.browser_args=['--some-browser-arg=true', '--some-other-option'],
config.lang="en-US" # navigatorのiso-language-codeを設定します。変更は推奨しません
)
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 # イベントが処理されるのを待つ
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アカウント作成の自動化
より具体的な例が ./example/ フォルダにあり、
Twitterアカウントを作成するスクリプトを示しています
```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")
# 静的な待機秒数ではなく、テキストが表示されるのを待つ
# 速度の問題で常に期待通りに動作するとは限りません
print('"create account"ボタンを見つけています')
create_account = await tab.find("create account", best_match=True)
print('"create account" => クリック')
await create_account.click()
print("メール入力フィールドを見つけています")
email = await tab.select("input[type=email]")
# 場合によっては、代わりに電話番号が求められるためメールフィールドが表示されない
# その場合は、"use email instead"という小さなテキストを見つける
if not email:
use_mail_instead = await tab.find("use email instead")
# クリック
await use_mail_instead.click()
# 再度メールフィールドを見つける
email = await tab.select("input[type=email]")
randstr = lambda k: "".join(random.choices(string.ascii_letters, k=k))
# メールフィールドにキー送信
print('"email"入力フィールドに入力中')
await email.send_keys("".join([randstr(8), "@", randstr(8), ".com"]))
# 名前入力フィールドを見つける
print("名前入力フィールドを見つけています")
name = await tab.select("input[type=text]")
# 再度ランダムテキストを送信
print('"name"入力フィールドに入力中')
await name.send_keys(randstr(8))
# タブには3つのselectフィールドがあるため、アンパッキングを使用して
# 各フィールドに代入
print('"month"、"day"、"year"フィールドを1回で見つけています')
sel_month, sel_day, sel_year = await tab.select_all("select")
# await sel_month.focus()
print('"month"入力フィールドに入力中')
await sel_month.send_keys(months[random.randint(0, 11)].title())
# await sel_day.focus()
# 月の長さやうるう年を気にしたくない
print('"day"入力フィールドに入力中')
await sel_day.send_keys(str(random.randint(0, 28)))
# await sel_year.focus()
# 年齢制限を気にしたくない
print('"year"入力フィールドに入力中')
await sel_year.send_keys(str(random.randint(1980, 2005)))
await tab
# Cookieの同意バーも処理
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("2秒スリープ")
await tab.sleep(2) # 現在どの部分にいるかを視覚的に確認
print('"next"ボタンを見つけています')
next_btn = await tab.find(text="next", best_match=True)
print('"next"ボタンをクリック中')
await next_btn.mouse_click()
# 続行する前にボタンが現れるのを待つ
await tab.select("[role=button]")
print('"sign up"ボタンを見つけています')
sign_up_btn = await tab.find("Sign up", best_match=True)
# 2番目のボタンが必要
print('"sign up"ボタンをクリック中')
await sign_up_btn.click()
print('残りの「実装」は範囲外です')
# これ以降の実装は範囲外
await tab.sleep(10)
driver.stop()
# メールでの確認コード
if __name__ == "__main__":
# since asyncio.run never worked (for me)
# 私は以下を使用
uc.loop().run_until_complete(main())