ในบริษัทก่อนหน้านี้ ฉันได้พัฒนาชุดงานที่ติดตามเมตริกต่างๆ ในโซเชียลมีเดีย เช่น Twitter, LinkedIn, Mastodon, Bluesky, Reddit เป็นต้น จากนั้นฉันก็ตระหนักว่าฉันสามารถทำซ้ำงานดังกล่าวสำหรับ "ตัวตน" ของตัวเองได้ ปัญหาคือสื่อบางแห่งไม่มี HTTP API สำหรับเมตริกที่ฉันต้องการ นี่คือ เมตริก ที่ฉันต้องการใน LinkedIn:
ฉันค้นหาเป็นเวลานานแต่ไม่พบการเข้าถึง API สำหรับเมตริกข้างต้น ฉันรวบรวมข้อมูลเมตริกด้วยตนเองทุกเช้าเป็นเวลานาน และในที่สุดก็ตัดสินใจทำให้ภารกิจที่น่าเบื่อนี้กลายเป็นระบบอัตโนมัติ นี่คือสิ่งที่ฉันได้เรียนรู้
งานนี้เป็นงานเกี่ยวกับ Python ฉันจึงอยากทำงานด้านเทคโนโลยีเดียวกัน หลังจากค้นคว้าข้อมูลอย่างรวดเร็ว ฉันก็พบ Playwright ซึ่งเป็นเครื่องมืออัตโนมัติสำหรับเบราว์เซอร์ที่มี API ภาษาต่างๆ สองสามภาษา รวมถึง Python กรณีการใช้งานหลักของ Playwright คือการทดสอบแบบครบวงจร แต่ยังสามารถจัดการเบราว์เซอร์นอกบริบทการทดสอบได้อีกด้วย
ฉันใช้ Poetry เพื่อจัดการสิ่งที่ต้องพึ่งพา การติดตั้ง Playwright ง่ายเหมือนดังนี้:
poetry add playwright
ณ จุดนี้ Playwright ก็พร้อมใช้งานแล้ว โดยมี 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 ซึ่งจะไม่แสดงขึ้นมา ฉันแนะนำให้เปิดแบบมองเห็นได้ตั้งแต่เริ่มต้นเพื่อให้แก้ไขจุดบกพร่องได้ง่ายขึ้น: headless = True
เปิดหน้าต่างเบราว์เซอร์ใหม่
นำทางไปยังตำแหน่งใหม่
ค้นหาช่องป้อนข้อมูลที่ระบุและกรอกข้อมูลประจำตัวของฉัน
ค้นหาปุ่มที่ระบุแล้วกด
ระบุตำแหน่งองค์ประกอบที่ระบุ ทั้งหมด
รับข้อความภายในขององค์ประกอบแรก
ปิดเบราว์เซอร์เพื่อทำความสะอาด
ข้างต้นนั้นใช้งานได้ตามที่คาดหวัง ข้อเสียอย่างเดียวคือฉันได้รับอีเมลจาก LinkedIn ทุกครั้งที่ฉันรันสคริปต์:
สวัสดี นิโคลัส
คุณได้เปิดใช้งาน Remember me บนอุปกรณ์ HeadlessChrome ใหม่แล้ว <OS> ใน <เมือง> <ภูมิภาค> <ประเทศ > เรียนรู้เพิ่มเติมเกี่ยวกับการทำงานของ Remember me บนอุปกรณ์
ฉันได้พบกับ Fabien Vauchelles ที่งานประชุม JavaCro เขาเป็นผู้เชี่ยวชาญด้านการสแกนเว็บและบอกฉันว่าคนส่วนใหญ่ในสาขานี้ใช้โปรไฟล์เบราว์เซอร์ หากคุณเข้าสู่ระบบ LinkedIn คุณจะได้รับโทเค็นการตรวจสอบสิทธิ์ที่จัดเก็บเป็นคุกกี้ และคุณไม่จำเป็นต้องตรวจสอบสิทธิ์อีกครั้งก่อนที่โทเค็นจะหมดอายุ โชคดีที่ Playwright นำเสนอฟีเจอร์ดังกล่าวด้วยเมธอด 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 ฉันชอบใช้ Sync API มากกว่าเพราะทำให้โค้ดเข้าใจง่ายขึ้นเล็กน้อย และฉันก็ไม่มีข้อกำหนดด้านประสิทธิภาพใดๆ ฉันใช้เฉพาะฟีเจอร์พื้นฐานที่ Playwright เสนอ Playwright อนุญาตให้บันทึกวิดีโอในบริบทของการทดสอบ ซึ่งมีประโยชน์มากเมื่อการทดสอบล้มเหลวระหว่างการดำเนินการ CI pipeline
ไปต่อเลย:
เผยแพร่ครั้งแรกบน A Java Geek เมื่อวันที่ 19 มกราคม 2024