top of page
ค้นหา
รูปภาพนักเขียนSathit Jittanupat

Puppeteer, how to automate Google sign in

บันทึกการทดลองใช้ Puppeteer โดยการเขียนโค้ด ให้ทำงานเป็น robot แทนคน สั่งให้เปิดโปรแกรม เรียกรายงาน แล้วส่งข้อมูลจากรายงานนั้นไปเข้า Google Sheet เพื่อนำไปแสดงเป็น dashboard ใน Data Studio อีกทีหนึ่ง


วัตถุประสงค์ที่ต้องใช้ robot เนื่องจาก dashboard มีผู้ใช้หลายคน ต่างแผนก และต่างวาระกันไป จึงไม่สามารถกำหนดได้ว่าใครจะรับผิดชอบ update ข้อมูล และทางทีมพัฒนาไม่ต้องการให้เกิดจาก update ซ้ำซ้อนกันโดยไม่จำเป็น จึงมีความคิดว่าควรทำเป็น robot แล้วทำเป็น schedule task ตั้งเวลาให้ทำงานอัตโนมัติทุกวันแทน เพื่อแก้ปัญหาดังกล่าว




Puppeteer

ทำความรู้จัก Puppeteer กันก่อน เอาแบบง่ายๆ คือกลไกที่สามารถจำลองตัวเองเป็น Chrome browser อยู่ในตัวเอง โดยไม่จำเป็นต้องมี Chrome ติดตั้งในเครื่องมาก่อน สามารถเขียนโค้ดสั่งให้เปิด web page ต่างๆ ขึ้นมาได้ เสมือนกำลังทำงานอยู่ใน browser จริง แล้วก็ยังสั่งให้จำลองการกระทำเสมือนเป็นคนใช้งาน จริง เช่น click mouse หรือ ป้อนข้อมูลผ่าน keyboard


ตัวอย่างการประยุกต์ใช้ robot เพื่อทำงานแทนมนุษย์ มีทั้งสายสีขาว เอามาช่วยลดงานซ้ำซากในองค์กร ที่เคยต้องใช้คนทำก็เปลี่ยนมาใช้ robot จำลองแทนคน หรือที่ใช้กันมากคือทำ web scraping เก็บข้อมูลโดยอ่านจากหน้าเว็ปอื่นมาตรงๆ เช่น ราคาน้ำมัน, ราคาทอง, ราคาหุ้น ฯลฯ ส่วนสายสีเทาหน่อย ก็จะเอามาใช้เพื่อเอาเปรียบผู้อื่น เช่น การแย่งจองซื้อตั๋วหรือสินค้าในช่วงโปรโมชั่น จะได้เลิกแปลกใจว่าทำไม ขนาดรอเฝ้านับถอยหลังวินาทีแรกแล้ว ก็ไม่เคยกดซื้อได้ทัน เพราะคุณอาจกำลังแข่งกับ robot



โดยทั่วไปการพัฒนางานในองค์กร มักมี process ที่ซับซ้อนกว่าการแย่งจองซื้อของ นักพัฒนาที่รู้ Business Logic จะไม่เชี่ยวชาญเขียนโค้ด ส่วนผู้ที่เป็น Dev เชี่ยวชาญเขียนโค้ดก็จะไม่เข้าใจ Business Logic ดีพอ ดังนั้น robot ที่นิยมกันในองค์กรคือ UiPath, Automate Anywhere และผู้ท้าชิงล่าสุด Microsoft Power Automate จะมีลักษณะเป็น low code ไม่จำเป็นต้องเขียนโค้ดได้ เพื่อให้นักพัฒนาที่รู้ Business Logic ก็สามารถสร้าง robot มาใช้ได้ ข้อแรกเปลี่ยนทีสำคัญ ซอฟต์แวร์เหล่านี้ ตั้งราคาไว้สูง และค่าจ้างนักพัฒนาภายนอกก็สูงตามด้วย ในแง่ความคุ้มค่าจึงมีแต่องค์กรใหญ่ที่มีปริมาณงานมากเท่านั้นที่ลงทุนแล้วคุ้มค่ากว่าจ้างพนักงานแบบเดิม


วัตถุประสงค์หลักของ Puppeteer ทำมาเพื่อให้ โปรแกรมเมอร์สามารถสร้าง process ของ automated test โปรแกรมที่เป็น web app ของตัวเองได้ ดังนั้นการสร้าง robot โดยใช้ Puppeteer จึงต้องพึ่งพิงความสามารถในการเขียนโค้ดด้วย ไม่ต้องคาดหวังสิ่งอำนวยความสะดวกในระดับ user และไม่มีการรับประกัน แลกกับการใช้งานฟรี หรือกล่าวง่ายๆ คือ เรากำลังเอาลองเครื่องมือของโปรแกรมเมอร์มาใช้กับภาคธุรกิจ


Google sign in

กลับมาเข้าเรื่องที่จั่วหัวไว้ เราจำเป็นต้องใช้ Google Account เพื่อ sign in เพราะมีขั้นตอนทำงานที่ส่งข้อมูลไปเขียนใส่ Google Sheet แต่ประเด็นที่สำคัญคือ Google Account เองก็พยายามป้องกันตัวเองในแง่ของความปลอดภัยต่อผู้ใช้ที่เป็นเจ้าของบัญชี ไม่อยากให้มีการใช้ bot ในการ sign in เพราะอาจเป็นการแอบอ้างเอาบัญชีของคนอื่นมาใช้เพื่อวัตถุประสงค์ที่ไม่ดีก็ได้


ความท้าทายของบรรดานักพัฒนาที่ใช้ Puppeteer จึงอยู่ที่ ทำอย่างไรจะสามารถเขียนโค้ดให้ sign in อัตโนมัติ หลายคนบอกว่ามันคือ เกมแมวกับหนู หากไปค้นหาคำว่า “puppeteer google sign in” จะมีคำแนะนำวิธีหลากหลายตลอดหลายปีที่ผ่านมา แล้วส่วนใหญ่ก็จบด้วยคอมเมนท์สุดท้ายว่า “ตอนนี้ใช้อย่างนั้นไม่ได้แล้ว” เพราะว่าวิธีนั้นน่าจะเป็นวิธีที่ไม่พึงประสงค์ ดังนั้น Google Account ก็พยายามปรับปรุงและปิดช่องโหว่ดังกล่าว


ต่อไปนี้คือ สิ่งที่เรียนรู้จากความพยายามหาวิธี sign in ด้วย Puppeteer ที่ Google Account ยินยอมให้ผ่านได้


Automatic sign in script

ตัวอย่าง sign in script อาศัยตัวอย่างจากนักพัฒนาที่แชร์ไว้ใน gist.github.com แล้วเอามาปรับปรุงเพิ่มเติมดังนี้

const SECOND = t => t * 1000 ;
const googleSignIn = async (gpage, email, password) => {
  await gpage.waitForSelector('#identifierId', { timeout: SECOND(5) });
  await gpage.type('#identifierId', email);
  await gpage.waitForTimeout( SECOND(1) );
  await gpage.keyboard.press('Enter');
  await gpage.waitForTimeout( SECOND(1) );
  await gpage.waitForSelector('input[name="password"]', { timeout: SECOND(5) });
  await gpage.waitForTimeout( SECOND(1) );
  await gpage.type('input[name="password"]', password);
  await gpage.waitForTimeout( SECOND(1) );
  await gpage.keyboard.press('Enter');
  // wait for 2FA flow
}

Domain gmail.com

สำหรับบัญชีของบุคคลทั่วไป ที่ใช้ domain gmail.com เมื่อใส่ email ในขั้นตอนแรกแล้ว ไม่สามารถไปต่อขั้นตอนใส่ password ได้


เราจึงทดลองตามที่นักพัฒนาอื่นมักแนะนำ คือให้ติดตั้ง package puppeteer-extra-plugin-stealth พบว่าไปต่อใส่รหัสผ่านได้ (โดยที่ Google Account ก็ยังสามารถตรวจพบว่าเป็น robot) แต่ไม่เลือกใช้วิธีนี้ เนื่องจากเป็น third party code


เมื่อทดลองเปลี่ยนไปใช้บัญชีที่เป็น Google Workspace (G-Suite เดิม) ที่ไม่ใช่ domain gmail.com พบว่าสามารถใส่ email และ password ได้ โดยไม่ต้องใช้ plugin stealth


การใส่ password ก็ไม่ง่ายนัก ดูเหมือนจะมีกลไกบางอย่างป้องกันอยู่ โดยจุดที่ต้องหลบเล็กน้อย คือ หากใช้ input[type="password"] บางครั้งจะเกิดอาการ password ตกหล่นใส่ได้ไม่ครบแบบไม่แน่นอนด้วย ต้องหลบไปใส่ password ใน element input[name="password"] ที่ซ่อนอยู่แทน (ตามโค้ดตัวอย่างข้างบน)


2 Steps verification (2FA)

ดังที่อธิบายมาแล้ว puppeteer ไม่ต้องแตะต้อง Chrome ที่เราใช้งานปกติ แต่ทำงานด้วย Chromium engine ใน sandbox ของตัวเอง ดังนั้นเมื่อ sign in แล้ว จะเหมือนกับกำลังเพิ่งใช้คอมพิวเตอร์ครั้งแรก ต้องมีการยืนยันตัวตนขั้นสอง


เราไม่สามารถหลีกเลี่ยงขั้นตอนนี้ได้ แต่มีวิธีที่ทำให้ยืนยันครั้งเดียว เหมือนกับ Chrome ปกติ ที่จำคอมพิวเตอร์ที่เคยผ่าน 2FA แล้วจะไม่ถามซ้ำ หากเรียกใช้อีก โดยใช้ launch options userDataDir ระบุ path เก็บ user profile สำหรับ Puppeteer เอาไว้ (default คือ ไม่เก็บ ทำให้ทุกครั้งที่ sign in โดนถาม 2FA)



Google prompts

การรับรหัสยืนยัน 2FA ผ่าน SMS เป็นวิธีที่ลำบากสำหรับการทำ automation เพราะต้องรอรับรหัสจากผู้ใช้อยู่ดี โชดดีที่ปัจจุบันนี้มีบริการ Google prompts ช่วยให้เราสามารถยืนยัน 2FA โดยใช้โทรศัพท์มือถือหรือแท็บเล็ตที่ใช้ แอนดรอยด์ และมี Google Play Service หากใช้ iPhone หรือ iPad จะต้องติดตั้ง Smart Lock App และ Gmail App



Scenario

สรุปภาพการทำงานของ robot ที่คิดไว้คือ เมื่อมีการใช้งานเรียกใช้งาน Puppeteer หลังจาก sign in ใส่ email และ password แล้ว จอ sign in ยังไม่ปิดลง เฉพาะครั้งแรกจะต้องรอ 2FA โดยเจ้าของบัญชีจะต้องอนุมัติด้วยมือถือก่อน จอ sig in จึงปิดลงไปอัตโนมัติ ซึ่ง Puppeteer ก็ใช้วิธีเช็คว่า หากจอนี้ยังไม่ปิด แสดงว่า 2FA ยังไม่ผ่าน ยังไม่ต้องทำงานขั้นต่อไป


เมื่อมีการเรียกใช้งาน Puppeteer ครั้งต่อไป เนื่องจากมีการใช้ launch options userDataDir จึงไม่มีการถามหา 2FA อีก ดังนั้น robot ที่สร้างด้วย Puppeteer จึงถูกปลุกให้ทำงานทุกวันโดยไม่รบกวนเจ้าของ Google Account อีก


อ้างอิง

Puppeteer

Puppeteer Quick Start

Puppeteer Developer Document

Puppeteer-extra

Chromium command line switches



ดู 1 ครั้ง0 ความคิดเห็น

โพสต์ล่าสุด

ดูทั้งหมด

留言


Post: Blog2_Post
bottom of page