以前の会社では、Twitter、LinkedIn、Mastodon、Bluesky、Reddit などのソーシャル メディア全体のメトリクスを追跡するバッチ ジョブを開発しました。その後、自分の「ペルソナ」用にそれを複製できることに気付きました。問題は、一部のメディアが、必要なメトリクス用の HTTP API を提供していないことです。LinkedIn で必要な は次のとおりです。 メトリクス 長い間検索しましたが、上記のメトリクスへの API アクセスは見つかりませんでした。長い間、毎朝手動でメトリクスをスクレイピングしていましたが、最終的にこの面倒な作業を自動化することにしました。そこで学んだことは次のとおりです。 背景 この仕事は Python で行われるため、同じ技術スタックを維持したいと考えています。簡単に調べた後、Python を含むいくつかの言語 API を備えたブラウザ自動化ツールである 見つけました。Playwright の主な使用例はエンドツーエンドのテストですが、テストコンテキスト外でブラウザを管理することもできます。 Playwright を 私は依存関係を管理するために Poetry を使用しています。Playwright のインストールは次のように簡単です: poetry add playwright この時点で、Playwright は使用できる状態になっています。Playwright は、 と の 2 つの異なる API を提供しています。私の使用例では、最初の API で十分です。 同期 API 非同期 API 足を濡らす 私は開発に段階的にアプローチするのが好きです。 以下は API の抜粋です: これは次のコードに変換されます。 from playwright.sync_api import Browser, Locator, Page, sync_playwright with (sync_playwright() as pw): #1 browser: Browser = pw.chromium.launch() #2 page: Page = browser.new_page() #3 page.goto('https://www.linkedin.com/login') #4 page.locator('#username').press_sequentially(getenv('LINKEDIN_USERNAME')) #5 page.locator('#password').press_sequentially(getenv('LINKEDIN_PASSWORD')) #5 page.locator('button[type=submit]').press('Enter') #6 page.goto('https://www.linkedin.com/dashboard/') #4 metrics_container: Locator = page.locator('.pcd-analytic-view-items-container') metrics: List[Locator] = metrics_container.locator('p.text-body-large-bold').all() #7 impressions = atoi(metrics[0].inner_text()) #8 # Get other metrics browser.close() #9 オブジェクトを取得します。 playwright ブラウザ インスタンスを起動します。複数のブラウザ タイプが利用可能ですが、私は気まぐれで Chromium を選択しました。特定のブラウザを事前にインストールしておく必要があることに注意してください 。 (例: playwright install --with-deps chromium デフォルトでは、ブラウザは で開き、表示されません。デバッグを容易にするために、最初は表示して実行することをお勧めします: 。 ヘッドレス headless = True 新しいブラウザウィンドウを開きます。 新しい場所に移動します。 指定された入力フィールドを見つけて、資格情報を入力します。 指定されたボタンを見つけて押します。 指定された 要素を検索します。 すべての 最初の要素の内部テキストを取得します。 クリーンアップするにはブラウザを閉じます。 クッキーの保存 上記は期待通りに動作しました。唯一の欠点は、スクリプトを実行するたびに LinkedIn からメールが届いたことです。 こんにちは、ニコラス。 で「Remember me」を正常に有効化しました。デバイスで「Remember me」がどのように機能するかについて詳しくは、こちらをご覧ください。 <city>、<region>、<country> の新しいデバイス HeadlessChrome、<OS> カンファレンスでは にも会いました。彼は Web スクレイピングを専門としており、この分野のほとんどの人がブラウザ プロファイルを活用していると教えてくれました。実際、LinkedIn にログインすると、認証トークンが Cookie として保存され、期限が切れるまで再度認証する必要はありません。幸い、Playwright は メソッドでそのような機能を提供しています。 JavaCro Fabien Vauchelles launch_persistent_context 上記の 次のように置き換えることができます。 launch with sync_playwright() as pw: playwright_profile_dir = f'{Path.home()}/.social-metrics/playwright-profile' context: BrowserContext = pw.chromium.launch_persistent_context(playwright_profile_dir) #1 try: #2 page: Page = context.new_page() #3 page.goto('https://www.linkedin.com/dashboard/') #4 if 'session_redirect' in page.url: #4 page.locator('#username').press_sequentially(getenv('LINKEDIN_USERNAME')) page.locator('#password').press_sequentially(getenv('LINKEDIN_PASSWORD')) page.locator('button[type=submit]').press('Enter') page.goto('https://www.linkedin.com/dashboard/') metrics_container: Locator = page.locator('.pcd-analytic-view-items-container') # Same as in the previous snippet except Exception as e: #2 logger.error(f'Could not fetch metrics: {e}') finally: #5 context.close() Playwright は指定されたフォルダーにプロファイルを保存し、実行ごとに再利用します。 例外処理を改善します。 ページを開くこともできます。 BrowserContext ダッシュボードに移動しようとします。認証されていない場合は LinkedIn によってログイン ページにリダイレクトされ、その後認証できるようになります。 結果がどうであれ、コンテキストを閉じます。 この時点では、最初に両方の資格情報を使用して認証するだけで済みます。その後の実行では、状況によって異なります。 現実に適応する 上記のコードが確実に動作しないことに驚きました。最初の実行では動作し、その後の実行ではときどき動作しました。実行をまたいでブラウザ プロファイルを保存しているため、認証が必要な場合、LinkedIn はログインではなくパスワードのみを要求します。コードはログインを入力しようとするため、この場合は失敗します。修正は非常に簡単です。 username_field = page.locator('#username') if username_field.is_visible(): username_field.press_sequentially(getenv('LINKEDIN_USERNAME')) page.locator('#password').press_sequentially(getenv('LINKEDIN_PASSWORD')) 結論 私は Python の専門家ではありませんが、Playwright で望みどおりの成果を上げることができました。同期 API を使うことを選んだのは、コードが少し理解しやすくなり、パフォーマンス要件もなかったからです。使用したのは Playwright が提供する基本機能だけです。Playwright ではテストのコンテキストでビデオを録画できます。これは、CI パイプラインの実行中にテストが失敗した場合に非常に便利です。 さらに進むには: 劇作家 ビデオ録画 2024年1月19日に で最初に公開されました A Java Geek