PhantomJS คืออะไร ? + สอนวิธีใช้

วันนี้เราจะมาพูดถึง tool ที่กำลังได้รับความนิยมมากอีกตัวหนึ่งนั่นก็คือ PhantomJS โดยปกติแล้ว เวลาเราจะเข้าเว็บเราก็จะต้องเปิด web browser ขึ้นมา แล้วก็ใส่ url ลงไป แต่ PhantomJS นั้นจะแตกต่างจาก web browser อื่นๆ ตรงที่มันจะต้องรันผ่าน command-line เราลองมาดูกันว่าความสามารถของ PhantomJS นั้นจะคุ้มค่ากับการหายไปของ GUI หรือเปล่า ?

PhantomJS คืออะไร ?

อย่างที่เกริ่นไปแล้วว่า PhantomJS นั้นเป็น tool ที่ใช้สำหรับเข้าเว็บเหมือนๆ กับ Chrome, Internet Explorer หรือ Firefox เลย แม้ฟังแล้วอาจดูเหมือนไม่มีอะไรน่าสนใจนัก แต่ความพิเศษของมันนั้นอยู่ตรงที่การรันผ่าน command-line ซึ่งมาพร้อมกับ JavaScript API ที่จะทำให้เราสามารถจัดการกับผลลัพธ์ของเว็บนั้นๆ ได้ด้วย

แล้ว PhantomJS ทำอะไรได้บ้าง ?

ด้วยความสามารถในการจัดการกับผลลัพธ์ของหน้าเว็บได้ คนจึงนิยมนำ PhantomJS ไปใช้ในงานต่างๆ ดังนี้

  • Testingใช้ควบคู่กับ Test Framework อย่าง QUnit หรือ Jasmine
  • Screen Captureเซฟภาพหน้าเว็บเป็นไฟล์รูปได้ รวมไปถึงกราฟิกอย่าง SVG หรือ Canvas
  • Page Automationทำ DOM Manipulation กับหน้าเว็บหลังจากที่โหลดมาแล้วได้
  • Network Monitoringสามารถตรวจดู network traffic เพื่อนำข้อมูลไปวิเคราะห์ได้

เมื่อดูจากความสามารถของ PhantomJS เราอาจจะเริ่มคุ้นๆ กับบริการที่มีลักษณะคล้ายๆ แบบนี้มาก่อน ในหัวข้อต่อไป เราจะมาลองใช้ PhantomJS สร้างบริการดังกล่าวขึ้นมาใช้เองดู

ลองใช้ PhantomJS

ติดตั้ง PhantomJS

เพื่อความสะดวกในการใช้งาน ให้เราติดตั้ง PhantomJS จาก npm ของ Node.js ได้เลย (สามารถอ่านพื้นฐานเกี่ยวกับการใช้ Node.js ได้ที่ Node.js คืออะไร ?)

ลองรัน PhantomJS

เมื่อได้ติดตั้ง PhantomJS ในรูปแบบ package ของ Node.js แบบ global ไปแล้ว เราก็จะสามารถใช้คำสั่งของ PhantomJS ได้ในทุกๆ ที่เลย โดยรูปแบบของคำสั่งจะเป็นแบบนี้

ก่อนอื่นให้เราสร้างไฟล์ someScript.js ขึ้นมาก่อน แล้วลองใส่โค้ดง่ายๆ แบบนี้ลงไป

จากนั้นก็เอาไฟล์นี้ไปวางไว้ในโฟลเดอร์ myProject ของเรา ตามโครงสร้างนี้

ทีนี้เราจะลองให้ PhantomJS อ่าน script ที่เราเขียนเอาไว้ในไฟล์ someScript.js ก่อนอื่นก็ให้เราเข้าไปในโฟลเดอร์ myProject ด้วยคำสั่งด้านล่างนี้

เมื่อเข้าไปในโฟลเดอร์งานของเราแล้ว ก็ให้ลองรันคำสั่งของ PhantomJS ได้เลย

หากเราพบข้อความ “Siam HTML” แสดงออกมาที่ command-line ก็แปลว่าเราพร้อมใช้ PhantomJS แล้ว

Workshop – ลองใช้ PhantomJS

จากตัวอย่างง่ายๆ ก่อนหน้านี้ทำให้เรารู้แล้วว่า การใช้งาน PhantomJS นั้นก็แค่เขียนโค้ด JavaScript ลงในไฟล์ แล้วก็สั่งให้ PhantomJS รันไฟล์นั้นผ่าน command-line เท่านั้นเอง ทีนี้เรามาลองดูตัวอย่างการใช้ JavaScript API ที่ PhantomJS มีมาให้กันดีกว่า

1. Page Loading

อย่างแรกเลยเราลองมาดูความสามารถพื้นฐานของ PhantomJS กันก่อน นั่นก็คือการเปิดหน้าเว็บนั่นเอง โดยเราจะสามารถระบุ URL ของหน้าเว็บที่ต้องการจะเปิดได้ พร้อมกับกำหนด callback function เพื่อที่จะให้ทำอะไรบางอย่าง เมื่อหน้าเว็บนั้นได้ถูกโหลดมาเรียบร้อยแล้ว ลองดูตัวอย่างโค้ดด้านล่างนี้

2. Screen Capture

สมมติเราอยากจะเซฟหน้าเว็บนั้นๆ ออกมาเป็นไฟล์ภาพ เราก็แค่เพิ่มโค้ดลงไปใน callback function เพียงไม่กี่บรรทัดแบบนี้

หากเราไม่อยากกำหนด URL ลงไปในโค้ดเลย เราก็อาจจะให้มันอ่านจาก argument ที่เราจะส่งเข้าไปตอนรัน PhantomJS ก็ได้ ให้เราแก้โค้ดเป็นแบบนี้

ทีนี้เวลาเราจะรัน ก็ให้เรากำหนด URL และชื่อของไฟล์รูปที่ต้องการจะเซฟไปด้วย แบบนี้

จากโค้ดด้านบน จะได้ว่า http://www.siamhtml.com และ siamhtml จะเป็น argument ตัวที่ 1 และ 2 ตามลำดับ (url และ filename)

3. Page Automation

เราสามารถจัดการกับ DOM ของหน้าเว็บนั้นๆ ได้ โดยจะทำผ่านฟังก์ชัน evaluate() สมมติเราอยากรู้ว่า title ของหน้าเว็บนั้นคืออะไร เราก็จะเขียนแบบนี้

จากตัวอย่างด้านบน จะสังเกตว่าเราดึง title มาโดยการใช้ jQuery ซึ่งถ้าหน้าเว็บนั้นๆ มีการใช้ jQuery อยู่แล้วก็จะไม่มีปัญหาอะไร แต่ถ้ายังไม่มี เราก็จะต้องใส่ jQuery ให้มันก่อนโดยใช้ includeJS() แบบนี้

และจากความสามารถเกี่ยวกับ DOM Manipulation นี้เอง ที่ทำให้เราสามารถใช้ PhantomJS ในการทำ Page Automation ได้ เช่น หลังจากโหลดหน้าเว็บมาแล้ว ก็ให้กรอกข้อความลงในฟอร์ม แล้วสั่งให้ submit ฟอร์มนั้นๆ เป็นต้น หรือจะใช้เพื่อประโยชน์ในการ test ฟังก์ชันต่างๆ ก็ได้

4. Network Monitoring

นอกจากนั้น เรายังสามารถดูได้อย่างละเอียดว่าในการโหลดหน้าเว็บนั้นๆ มา มีข้อมูล request และ receive อะไรบ้าง ซึ่งจะมีประโยชน์มากในการใช้วิเคราะห์เรื่อง performance ของหน้าเว็บ ให้เราลองรันโค้ดด้านล่างนี้

เมื่อลองดูผลลัพธ์ที่ได้ เราก็จะเห็นข้อมูลดิบออกมามากมาย ซึ่งเราสามารถนำมาคำนวณเพื่อทำเป็นรายงานได้

Bonus – ใช้ PhantomJS ทำหน้าเพื่อ SEO ให้กับ SPA

รู้จักกับ SPA

อย่างที่เราทราบกันดีว่าการทำเว็บที่มีหน้าเดียวหรือ Single-page Application(SPA) เช่น การใช้ AngularJS นั้น ไม่ค่อยส่งผลดีในแง่ของ SEO เท่าไรนัก เพราะเว็บลักษณะนี้มักจะใช้ JavaScript ในการโหลดเนื้อหาแบบ dynamic ทำให้สิ่งที่ crawler ได้ไปนั้นมีแต่หน้าเปล่าๆ

HTML Snapshot

วิธีแก้ก็คือ เราจะต้องสร้างหน้าขึ้นมาอีกหน้าหนึ่ง สำหรับให้ crawler มา index โดยเฉพาะ หรือที่เรียกว่าการทำ HTML Snapshot โดยหน้าที่ว่านี้จะต้องมีเนื้อหาที่ครบถ้วน เพื่อให้ crawler ได้เนื้อหาที่ถูกต้องไป index แต่การจะมาทำ HTML Snapshot ให้ครบทั้งเว็บไซต์นั้นไม่ใช่เรื่องง่ายเลย

Google ทำอย่างไรกับ AJAX

ก่อนอื่นเรามาทำความเข้าใจกับการ crawl หน้าเว็บที่เป็น AJAX ของ Google กันก่อน แต่เดิมนั้น crawler ของ Google ไม่สามารถ index เนื้อหาที่ใช้ AJAX ได้ แต่ในปัจจุบัน Google ก็ได้กำหนดวิธีที่จะทำให้เนื้อหาแบบ AJAX สามารถถูก index ได้แล้ว

วิธีที่ว่านั้นก็คือ เราจะต้องบอก crawler ว่าเว็บเราเป็น AJAX นะ โดยการใส่สิ่งที่เรียกว่า fragment ลงไปใน URL ซึ่ง fragment ที่ว่านั้นก็คือเครื่องหมาย “!” ที่อยู่ตามหลัง “#” นั่นเอง ลองดูตัวอย่างนี้

เมื่อ crawler เจอ URL แบบนี้ มันจะตีความว่าหน้านี้เป็นหน้า AJAX ที่ทำให้รองรับการ crawl แล้ว แทนที่มันจะไป crawl หน้าปกติ มันก็จะไป request อีก URL แทน ตามรูปแบบด้านล่างนี้

เราจะเห็นว่า crawler นั้นจะไปแก้ URL ของเรา โดยการแทนที่ fragment ด้วย _escaped_fragment_ ซึ่งสิ่งนี้เองที่ทำให้เราสามารถแยกแยะได้ว่า request ที่เข้ามานั้นมาจาก crawler หรือไม่

แต่ถ้าเราไม่อยากใส่ fragment เราก็สามารถใช้วิธีใส่ meta tag นี้เอาไว้ที่ head element ก็ได้

โค้ดด้านบนจะเป็นการบอกว่าหน้าเว็บนี้ มี fragment เป็น “!” ซึ่งก็คือ fragment เปล่าๆ นั่นเอง หาก crawler เจอโค้ดนี้มันก็จะตีความหน้าเว็บนี้เหมือนกับการใส่ fragment ตามปกติไว้ที่ URL เลย

ใช้ PhantomJS สร้าง HTML Snapshot ให้ Crawler

เมื่อเราสามารถแยก request ที่มาจาก crawler ออกจาก request ที่มาจากผู้ใช้งานทั่วไปได้ เราก็จะอาศัยมันในการสั่งให้ PhantomJS สร้าง HTML Snapshot ให้กับ URL นั้นๆ ให้เราไปดัก URL ที่ web server เอา หากพบว่ามี _escaped_fragment_ อยู่ใน URL ก็ให้ทำ proxy เข้าเครื่องหรือ port ที่รัน PhantomJS อยู่

อย่าลืมว่า PhantomJS นั้นจะต้องสามารถแปลง URL ที่มี _escaped_fragment_ กลับเป็น URL เดิมก่อนที่ crawler จะแปลงมาได้ด้วย เพื่อที่จะทำ HTML Snapshot ได้ถูก ในส่วนของการรับ request จาก crawler เราก็อาจใช้ Node.js มาสั่งให้ PhantomJS ทำงาน โดยจะรับ argument เป็น URL ของ request ที่เข้ามาที่ถูกแปลงกลับไปแล้วนั่นเอง

หลังจากที่ PhantomJS โหลด URL นั้นมาได้แล้ว เราก็อาจเซฟให้เป็นไฟล์ html ไว้ก็ได้ พอมี request เข้ามาอีก ก็ให้ใช้ Node.js เช็คดูก่อนว่ามีไฟล์ html ของ URL นั้นสร้างเอาไว้แล้วหรือยัง ถ้ามีอยู่แล้วก็ให้อ่านไฟล์นั้นแล้ว return กลับไปได้เลย จะได้ไม่ต้องมารัน PhantomJS ให้เสียเวลา หรือเราอาจจะเก็บลงใน memcache แล้วตั้งเวลาหมดอายุแทนการเซฟไฟล์ลง disk ก็ได้ (สำหรับเนื้อหาของการใช้ Node.js ขออนุญาตแยกเป็นอีกบทความ แต่หากใครอยากศึกษาก่อน สามารถอ่านวิธีใช้ Node.js รัน PhantomJS คร่าวๆ ได้ที่เว็บหลัก)

ตัวอย่างการใช้ PhantomJS เซฟหน้าเว็บเป็นไฟล์ HTML

สำหรับการเซฟหน้าเว็บเป็นไฟล์นั้นสามารถทำได้ง่ายๆ เลย ลองดูตัวอย่างโค้ดนี้

แต่อย่าลืมว่าเว็บที่เป็นแบบ AJAX นั้น อาจมีเนื้อหาบางส่วนที่จะโหลดมาทีหลัง วิธีแก้ปัญหาก็คือให้เราใช้ฟังก์ชัน waitFor() เข้ามาช่วย แบบนี้

จะเห็นว่าเราสามารถกำหนดเงื่อนไขได้เองว่าจะให้เริ่มทำอะไรตอนไหน จากตัวอย่างด้านบน เราจะสั่งให้เซฟหน้าเว็บเป็นไฟล์ก็ต่อเมื่อ #ajax_content ถูกโหลดมาแล้วนั่นเอง

บทสรุปการใช้ PhantomJS

เราคงจะได้เห็นแล้วว่าความสามารถ PhantomJS นั้นน่าสนใจมากแค่ไหน โดยเฉพาะการทำ HTML Snapshot ให้กับ SPA ถึงแม้ว่าสำหรับ Front-end Engineer แล้ว เราอาจจะไม่ค่อยได้ใช้ PhantomJS เท่าไรนัก แต่จริงๆ แล้ว เราอาจจะเคยใช้มันโดยที่ไม่รู้ตัวเลยก็ได้ เพราะ PhantomJS นั้นได้ถูกนำไปใช้ใน tool ต่างๆ ที่ช่วยในการทำเว็บไซต์มากมาย โดยเฉพาะ tool สำหรับ test หน้าเว็บ รวมไปถึง tool อื่นๆ ที่เกี่ยวกับการวิเคราะห์ preformance อีกด้วย

(Visited 9,951 times, 1 visits today)

One Response to “PhantomJS คืออะไร ? + สอนวิธีใช้”

  1. ผมเคยเอาไปใช้ทำ Screenshot สำหรับ HTML5 Banner แต่มีปัญหาเรื่องฟอนต์ ไม่รู้เพิ่มฟิวเจอร์หรือยังครับ ?

Leave a Reply