เก็บข้อมูล Real-time จาก Facebook Page ด้วย Google Cloud Functions และ BigQuery

ตัวอย่างจากงาน TEDxBangkok

Replay ของ reactions ต่างๆ ที่เกิดขึ้นบนโพสต์

เมื่อเดือนสิงหาคมที่ผ่านมา ผมได้รับเกียรติให้ไปเป็น speaker ในงาน TEDxBangkok โดยใน TED talk ของผมนั้น ผมได้ทำ interactive data visualization ขึ้นมาอันหนึ่ง แสดงจำนวนคนที่เข้ามากด Reaction ต่างๆ (👍🏻, ❤️, 😲) ให้กับโพสต์เปิดตัวของผมตลอดระยะเวลาเกือบหนึ่งสัปดาห์หลังจากที่โพสต์ได้ถูกปล่อยออกมา เพื่อสร้างสีสันเล็กๆ น้อยๆ ให้กับท่านผู้ชม

เนื่องจากใช้เวลาในการเขียนโค้ดเพื่อเก็บข้อมูลและทำ data visualization ไปค่อนข้างมาก (มากกว่าเวลาที่ใช้ซ้อมพูด 😂) เลยอยากจะถือโอกาสนี้ เขียน tutorial สั้นๆ สอนการเก็บข้อมูล real-time จาก Facebook Page เผื่อจะเป็นประโยชน์แก่ผู้ที่สนใจอยากจะทำอะไรคล้ายๆ กัน

Part I: ดึงข้อมูลด้วย Facebook Graph API

มีใครมากด Reaction บนโพสต์กันบ้าง?

เราสามารถดึงข้อมูลการกด reaction ต่างๆ บนโพสต์ได้ง่ายๆ โดยการส่ง GET Request ไปที่ /{post-id}/reactions

👉 ตัวอย่างการเรียกใช้ API: แนะนำให้ลองเปลี่ยนจาก reactions เป็น likes หรือ comments ดู หรือใครอยากลองเปลี่ยน parameters ใน query ก็สามารถอ้างอิงได้จากที่นี่

จะเห็นได้ว่าข้อมูลของแต่ละ reaction หรือ like นั้น จะไม่มี created_time ติดมาด้วย (แต่ถ้าเป็น comment จะมี) อย่างงี้ถ้าเราอยากรู้ว่าคนเข้ามากด like กันตอนไหนเยอะ? มากันรัวๆ หรือมากันกะปริดกะปรอย? เราควรจะทำอย่างไรดี

Webhooks

หลายๆ คนอาจจะยังไม่รู้ว่า จริงๆ แล้ว เราสามารถสร้าง Facebook application ขึ้นมา เพื่อ subscribe การแจ้งเตือนแบบ real-time เมื่อข้อมูลของผู้ใช้งานหรือเพจมีการอัพเดตได้ ผ่านทาง webhook (หากคุณมีสิทธิ์ในการเข้าถึงข้อมูลนั้น! เช่นสำหรับเพจ คุณอาจจะต้องได้สิทธิ์ manage_pages จากการเป็น admin ของเพจ เป็นต้น)

และด้วยวิธีนี้เอง เราก็จะสามารถเก็บข้อมูลได้ว่ามีใครมากด reaction อะไรให้เราตอนไหนบ้าง 👏🏻👏🏻👏🏻

คุณสามารถอ่านรายละเอียดการติดตั้ง subscription ได้จากลิงก์ด้านล่างนี้ อย่างไรก็ตาม ตอนนี้คุณจะยังไม่สามารถทำตามขั้นตอนทั้งหมดได้ เพราะเรายังไม่ได้ทำการสร้าง callback endpoint ขึ้นมารอรับการแจ้งเตือน เดี๋ยวเราจะมาทำในส่วนนี้ในหัวข้อถัดไป

หากเราทำการเชื่อมต่อ webhook สำเร็จแล้ว เราก็จะสามารถไป subscribe ข้อมูลแต่ละ field ของเพจ (หรือผู้ใช้งาน) ได้ตามภาพด้านล่าง โดยในตัวอย่างนี้เราต้องการ subscribe ข้อมูล feed ของเพจ เพื่อดักข้อมูลว่ามีใครมาโต้ตอบ หรือกด reaction อะไรบนโพสต์ต่างๆ ของเพจเราบ้าง

หมายเหตุ: ภาพประกอบมีการดัดแปลงเพื่อประหยัดพื้นที่ในการแสดงผล

ติดตั้งแอปพลิเคชันให้กับเพจ

หลังจากที่เราสร้าง Facebook application เพื่อ subscribe ข้อมูลจากเพจ(ใดๆ)เรียบร้อยแล้ว ขั้นตอนสุดท้าย ก็คือการติดตั้งแอปให้กับเพจที่เราต้องการจะเก็บข้อมูล โดยการส่ง POST request ไปที่ /{page_id}/subscribed_apps ด้วย access token ของเพจที่ต้องการติดตั้งสำหรับแอปของเรา (ดูรายละเอียดเพิ่มเติมได้ที่นี่) ถ้าหากเราต้องการให้แอปของเราเก็บข้อมูลจากหลายๆ เพจที่เราดูแลอยู่ เราก็สามารถทำซ้ำแบบเดียวกันนี้กับเพจอื่นๆ ได้เช่นกัน

Access token ของเพจเพจหนึ่งสำหรับแต่ละแอปพลิชันนั้นจะไม่เหมือนกัน ใน Graph API Explorer เราสามารถสร้าง access token ที่ถูกต้องได้โดย

  1. เลือกแอปพลิเคชันที่คุณจะใช้เก็บข้อมูล (dropdown box อันบนสุด)
  2. สร้าง access token สำหรับเพจที่เราต้องการจะเก็บข้อมูล (dropdown box อันถัดลงมา)

สุดท้าย ถ้าเราส่ง GET request ไปที่ /{page_id}/subscribed_apps ก็จะได้ผลดังภาพด้านล่าง

หากเราติดตั้งแอปให้เพจเราได้สำเร็จด้วย POST request เราก็จะได้ response กลับมาดังภาพด้านล่าง

ถ้าเราลองส่ง GET request ไปอีกที เราก็จะเห็นว่าแอปพลิเคชันของเราเข้าไปอยู่ในลิสต์เรียบร้อยแล้ว


เมื่อสักครู่เรายังค้างกันอยู่ที่ callback endpoint สำหรับรอรับการแจ้งเตือน ในหัวข้อถัดไป เราจะมา implement ในส่วนนี้กันบน Google Cloud Platform

Part II: เก็บข้อมูลด้วย Google Cloud Functions และ Google BigQuery

Google Cloud Functions

Google Cloud Function คือ ฟังก์ชันที่เราเขียนขึ้นมาเพื่อตอบสนองการ trigger จาก event อะไรบางอย่าง เช่น มีคนส่ง HTTP(S) request เข้ามา หรือมีการเพิ่มไฟล์ใน Cloud Storage โดยฟังก์ชันนี้จะถูกนำไปรันด้วย Node.js บน infrastructure ของ Google ทำให้เราไม่ต้องกังวลกับการเปิดเครื่องตั้ง server อันใหม่ (serverless) ปัญหาเรื่องความปลอดภัย (security) หรือการขยายระบบเพื่อรองรับจำนวนผู้ใช้งานที่มากขึ้น (scalability)

ใครที่มาจากฝั่ง Amazon ก็อาจจะคุ้นเคยกับ AWS Lambda ที่มีความสามารถคล้ายๆ กันอยู่แล้ว

HTTP Functions

เมื่อมีคนมากด reaction ให้กับโพสต์บนเพจที่เรากำลังดักเก็บข้อมูล Facebook ก็จะส่ง HTTPS POST request พร้อมกับ JSON payload ว่าใครมากด กด action อะไร ฯลฯ ไปที่ callback URL ที่เรากำหนดไว้ตอนติดตั้ง webhook

สิ่งที่เราจะทำในขั้นตอนต่อไปก็คือ การเขียน HTTP function หรือ cloud function ที่สามารถ trigger ผ่าน HTTP request ได้นั่นเอง

นี่คือตัวอย่างฟังก์ชันที่มีการจัดการกับ HTTP request มาตรฐาน ซึ่งก็จะมีการตรวจสอบว่า request ที่เข้ามาเป็นประเภทไหน GET หรือ PUT หลังจากนั้นก็จะมีการส่ง response กลับไป พร้อมกับ status code ที่เหมาะสม (200, 403, หรือ 500)

ตัวอย่างโค้ดที่รองรับ HTTP request มาตรฐาน (https://cloud.google.com/functions/docs/writing/http)

เพื่อให้รองรับการทำงานร่วมกับ webhook ของ Facebook เราจะต้องรับมือกับ HTTP request 2 ประเภทด้วยกัน

  1. Verification Request ซึ่งเป็น GET request ที่ส่งมาเพื่อ verify callback URL ว่าสามารถทำงานได้ โดยเราจะต้องทำการตรวจสอบ hub.verify_token ว่าตรงกับที่เรากำหนดไว้ และตอบกลับด้วยค่า hub.challenge ลองดูตัวอย่างได้จากโค้ดจริงด้านล่าง (lines 42–49)
  2. Update Notifications หรือการแจ้งเตือนเมื่อมีการเปลี่ยนแปลงของข้อมูล อย่างที่อธิบายไปข้างต้นแล้วว่า มันจะมาเป็น HTTPS POST request พร้อมกับ JSON payload ลองดูตัวอย่างได้จากโค้ดจริงด้านล่าง ในฟังก์ชัน processData()

Google BigQuery

เมื่อเราได้รับข้อมูลใหม่ผ่านทาง webhook เราก็จะต้องทำการเก็บข้อมูลลงในฐานข้อมูลเพื่อนำไปวิเคราะห์ในภายหลัง โดยในตัวอย่างนี้ผมเลือกใช้ Google BigQuery

Google BigQuery คือ บริการ data warehouse ของ Google ที่ออกมารองรับการจัดเก็บและประมวลผมข้อมูลปริมาณมากๆ (Big data!) โดยเราสามารถจัดการกับข้อมูลด้วยภาษา SQL ที่ทุกคนน่าจะคุ้นเคยกันดีอยู่แล้ว

จุดเด่นของ Google BigQuery ก็คือ ความเร็วในการประมวลผล มันสามารถประมวลผลข้อมูลขนาด terabytes ภายในไม่กี่วินาที (1 TB = 1,024 GB) หรือขนาด petabytes ภายในไม่กี่นาที (1 PB = 1,024 TB) นอกจากนี้เรายังไม่ต้องกังวลกับการเปิดเครื่องตั้ง database server ขึ้นมาใหม่ (serverless อีกแล้ว!) และปัญหาต่างๆ ในการดูแลระบบ (database administration)

เราสามารถเชื่อมต่อ cloud function ของเราเข้ากับ BigQuery ได้ง่ายๆ ด้วย library @google-cloud/bigquery ลองดูตัวอย่างจากโค้ดด้านล่างในฟังก์ชัน insertRows()

โค้ดจริง 🔥

ก่อนที่โค้ดนี้จะใช้งานได้จริง คุณจะต้องทำการสร้าง dataset ไว้ใน BigQuery ให้เรียบร้อยเสียก่อน ผ่าน Web UI หรือ BigQuery command line tools:

bq mk [YOUR_DATASET_NAME]

เมื่อเรามีฟังก์ชันที่พร้อมใช้งานแล้ว ขั้นตอนสุดท้ายก็คือการ deploy ขึ้น Google Cloud Platform ด้วยคำสั่งหน้าตาประมาณนี้

gcloud beta functions deploy helloGET --stage-bucket [YOUR_STAGING_BUCKET_NAME] --trigger-http

Note: ผมข้ามรายละเอียดเล็กๆ น้อยๆ ในการ setup project บน Google Cloud Platform หรือการติดตั้ง cmd tool ต่างๆ ไป เนื่องจากผู้อ่านส่วนใหญ่น่าจะพอมั่วๆ เองได้ แต่ถ้าหากใครต้องการแบบละเอียดๆ ลองทำตาม official tutorial เหล่านี้ดูครับ

หรือถ้าใครไม่ถูกกับภาษาอังกฤษ แบบไทยๆ ก็มีครับ 😆http://www.somkiat.cc/deploy-function-on-google-cloud-platform/

Putting Together

เมื่อเรา deploy cloud function ของเราเสร็จสมบูรณ์แล้ว เราก็จะได้ URL สำหรับไว้ใช้ trigger ฟังก์ชันของเรา ตามภาพด้านล่างนี้

เราก็สามารถนำ URL นี้ ไปกำหนดเป็น Callback URL เพื่อติดตั้ง webhook ของ Facebook application ของเรา


ถ้าคุณทำตามทุกขั้นตอนได้อย่างถูกต้อง ข้อมูล interactions บน feed ของเพจที่คุณดักข้อมูลอยู่ก็จะถูกจัดเก็บลงใน Google BigQuery รอให้คุณนำไปวิเคราะห์ต่อไป!


ไม่อยากพลาดสาระดีๆ แบบนี้ ติดตามพวกเราได้ที่ FB เพจ Skooldio