TL;DR
ใครบอกว่า Bot เป็นเรื่องยาก? เรื่องยากความจริงแล้วก็แค่เพราะเราไม่รู้ /me เขียนบทความนี้ เพื่อให้ทุกคนลอง แล้วจะพบว่าการเขียน Bot เป็นเรื่องง่ายกว่าที่คิด
#ภาษาอังกฤษวันละคำ วันนี้ ภูมิใจเสนอคำว่า “SPIDER” ออกเสียงว่า สะ-ไป-เด้อ แปลว่า “แมงมุม” #อีกรอบนะฮะ “SPIDER” แปลว่า “แมงมุม”
แต่สำหรับหลายๆคน คงเข้าใจต่างออกไป #แล้วมันคืออะไร
จริงๆแล้ว WebBOT, SPIDER, CLAWER ในมุมมองของบางคน ไม่ใช่อะไรที่เกินไปกว่า โปรแกรมคอมพิวเตอร์ ที่ไล่เปิดเปิดเวปไซท์ขึ้นมา เพื่อเก็บรวบรวมข้อมูลต่างๆ จากนั้น ก็ ไต่ต่อจากลิงค์อยู่ในเวปไซท์ที่เปิดนั้น ไปเรื่อยๆ ไม่เหนื่อย #ก็มันเป็นแค่โปรแกรมหนิ #แต่ควรมีดีเลย์นะ
ตัวอย่างดังๆ ก็อย่างเช่น Googlebot , Bingbot ที่คอยรวบรวมเวปไว้สำหรับ #search ที่เราใช้ๆกันทุกวัน #กูเกิลพังไปฉันคงมีชีวิตอยู่ไม่ได้
ซึ่งการจะสร้างมันขึ้นมาก็ไม่ได้ยากอย่างที่คิด ลองมาดูกัน
Requirements
Python
//already installed in Ubuntu
Pip
wget https://bootstrap.pypa.io/get-pip.py;
sudo python get-pip.py;
Requests
sudo pip install requests
Beautiful Soup
sudo pip install beautifulsoup4
Basic Principle
ก่อนที่จะทำแบบนี้ ก่อนอื่น ต้องมาทำความเข้าใจ การทำงานของ Website กันก่อน website ที่เราเล่นๆทุกวันนี้ ส่วนใหญ่สื่อสารในรูปแบบที่ชื่อว่า HTTP ซึ่งเป็นรูปแบบที่คอมใช้ในการสื่อสารกัน #เหมือนกับภาษา เช่น ถ้าเป็นคนไทยคุยกัน ก็จะสื่อสารกันด้วยรูปแบบที่ชื่อว่า THAI
แต่ หลักการของ HTTP แต่ต่างจากภาษาทั่วๆไป คือ มันแบ่งคอมเป็น 2 ประเภท คือ #client และ #server ซึ่ง website จะอยู่ในเครื่อง server ส่วน web browser เช่นพวก #Chrome #Safari #InternetExplorer จะเป็น client
ซึ่งเมื่อใส่ URL ที่ต้องการเข้าไปไป client จะไปถาม server ว่าเวปไซท์นี้มีเนื้อหายังไง ซึ่ง server ก็จะตอบเป็น HTML code #พร้อมรายละเอียดอื่นๆด้วย
#ตัวอย่าง HTML
<html>
<head> </head>
<body> </body>
</html>
หลังจากนั้น #WebBrowser จะมีหน้าที่ แปลความ HTML #มาแสดงเป็นภาพสวยๆ ด้วยสิ่งที่เรียกว่า “Render Engine” ดังนั้น แต่ละ browser อาจจะแปลไม่เหมือนกันก็ได้ โดยเฉพาะ #InternetExplorer ที่มีปัญหาบ่อยๆ เพราะว่า ไม่ยอมแปลตามมาตรฐาน ทำให้บางเวปเปิดที่ brower อื่นแล้วสวย พอเปิดใน #InternetExplorer แล้วเน่า
ซึ่ง #SPIDER ของเราก็จะทำในลักษณะที่คล้ายๆกัน คือ
- ส่ง HTTP ถามไปยัง url เป้าหมาย
- แปลความ HTML ที่ได้รับ
Let’s Start
ส่ง HTTP ถามไปยัง URL เป้าหมาย
เริ่มต้นด้วยการส่งไปถามข้อมูลจากหน้าเวปธรรมดาที่ไม่ต้องการ login อย่าง google.com สามารถทำได้ง่ายๆเพียง
import requests
r = requests.get('https://www.google.com')
print r.text
หาทุกอย่างเป็นไปได้ด้วยดี ก็จะเห็น HTML code เต็มไปหมดเลย~
แต่ #ในชีวิตจริงไม่ได้ง่ายแบบนั้น หลายๆเวปที่จำเป็นต้องกรอก username/password หรือ form รูปแบบต่างๆ #แล้วฉันจะทำยังไง? #แต่มันก็ไม่ได้ยากอย่างที่คิดหรอกนะ
ซึ่งเราจะใช้ Chrome เป็นเครื่องมือในการแกะรอยครั้งนี้ #ตามวิธีต่อไปนี้
- เปิด chrome แล้วพิมเวปที่เราจะ login
- กด ctrl+shift+J เพื่อ เปิด console ขึ้นมา
- กดเลือก tab Network
- ลองกรอกฟอร์มแล้วส่ง ข้อมูล มั่วๆ จะเห็นว่า มันเกิดการส่งข้อมูล จากนั้นหาก้อนที่เป็นข้อมูลที่กรอกไป
-
หากกดเข้าไปดูก็จะได้ข้อมูลครบทุกอย่างที่เราต้องการ ซึ่งจะประกอบด้วย
- Url ที่เป้าหมายสำหรับการ login
- ชนิดของคำถามที่จะส่งไปหา server มักจะเจอเพียง GET [ใช้ requests.get], POST [ใช้ requests.post]
- ข้อมูลที่ต้องส่งไปเพื่อ login
- ลุยโค้ดกันเลย
import requests
with requests.Session() as session:
payload = {"member%5Bemail%5D": "....",
"member%5Bcrypted_password%5D": "...",
"persistent%5Bremember%5D": "1",
"action": "login",
"redirect":"Lw%3D%3D"}
r = session.post("http://pantip.com/login/authentication", data=payload)
print r.text
- สังเกตุได้ว่า โค้ดค่อยข้างเปลี่ยนไปมาก #เพราะอะไร? สิ่งที่สำคัญที่มาพร้อมกับการ login นอกจาก การส่งข้อมูลแล้ว มันก็คือ การบอกให้ระบบรู้ว่า เรายังคงอยู่ในฐานะที่ login อยู่ #ฉันยังไม่ได้ออกจากระบบ ซึ่งนั้นจำเป็นจะต้องมีการเก็บ Session ซึ่งเก็บสถาณะให้ระบบสามารถตรวจสอบได้
สำหรับใครที่สนใจ Requests ท่ายากกว่านี้ คลิ๊ก ศึกษา Requests เพิ่มเติม
แปลความ HTML ที่ได้รับ
หลังจากที่ผ่านความยากลำบากเพื่อให้ได้ HTML จาก server แล้ว #งานต่อมา คือ การแปลความหมายของ HTML #ควรจะเริ่มยังไงดี
พูดถึงมาตั้งนานละ HTML HTML HTML แล้ว ไอ้ HTML #คืออะไร?
HTML เป็น #MarkupLanguage ซึ่งหมายถึง ภาษาสำหรับการแสดงผลโดยไม่มีการคำนวนเข้ามาเกี่ยวข้อง ดังนั้นจึงเป็นไปไม่ได้ที่จะมีใครมาบอกว่า ผมเขียนโปรแกรม #เครื่องคิดเลข ด้วยHTML สิ่งที่ทำให้เวปเกิดการ movement คือส่วนที่เป็น #javascript, #coffeescript, #dart … ต่างหาก
โครงสร้าง HTML เป็นโครงสร้างที่อยู่ในรูปแบบที่เรียกว่า #tree
โดยสิ่งที่อยู่ใน <> จะเรียกว่า #tag เช่น <html> , <body> , <p> , แต่ละ #tag ต้องมี tag เปิด และ tag ปิด แต่ อาจจะไม่มี tag ปิดบ้าง #นิสหน่อย ซึ่งเกิดจาก ความขี้เกียจทาง #ประวัติศาสตร์อันยาวนาน ของ HTML นอกจากนี้ ก็คือ สิ่งที่เป็นส่วนขยายเรียกว่า #attribute เช่น
<a href="www.google.com"> ... </a>
#href เป็น attributeของ tag <a>
โดย attr href มีค่า = "www.google.com"
หลักจากเข้าใจแล้วว่า #HTML คืออะไร แต่จะรู้ได้อย่างไรว่า จุดที่เราสนใจ คือ tag อะไร #เข้าประเด็น
เราจะยังคงสามารถใช้ Chrome เป็นเครื่องมือในการแกะรอยได้เช่นเดียวกัน #หนิมันไว้เปิดเวปหรือไว้แฮ๊กวะ
- ให้ click ขวาในส่วนที่เราสนใจ เลือกหัวข้อ Inspect Element
- เลือก tag ให้ตรงตามที่ต้องการ โดยดูจากแรงเงา #สีน้ำเงิน
- ศึกษารูปแบบโค้ดจาก console ที่ขึ้นมา
เมื่อรู้แล้วว่า ส่วนที่สนใจคือ tag อะไร ก็เริ่ม ใช้ #BeautifulSoup กันได้เลยยย ซึ่ง BeautifulSoup เป็น library ที่ใช้ในการแปลความ HTML ให้ออกมาอยู่ในรูปแบบ tree ซึ่งสามารการใช้ค้นหา tag ที่ต้องการ โดย
body = soup.findAll("body")
ซึ่งจะได้มาเป็น list ตัวแทนของ tag <body> และ สามารถดึง ข้อความใน tag หรือ attribute ได้โดย
body = soup.findAll("body")
print body[0].text <span class="tag-en"> #แสดงค่าข้อมูลที่อยู่ภายใน</span> tag
print body[0][“class"] <span class="tag-en"> #แสดงค่า</span> attribute class ของ tag
่ศึกษา BeautifulSoup เพิ่มเติม ซึ่งเมื่อนำมาประกอบกับโค้ดเดิมจะได้
import requests
from bs4 import BeautifulSoup
with requests.Session() as session:
payload = {"member%5Bemail%5D": "....",
"member%5Bcrypted_password%5D": "...",
"persistent%5Bremember%5D": "1",
"action": "login",
"redirect":"Lw%3D%3D"}
r = session.post("http://pantip.com/login/authentication", data=payload)
r = session.get("http://pantip.com/tag/ชีวิตวัยรุ่น")
soup = BeautifulSoup(r.text)
tag_a = soup.findAll('a')
for tag in tag_a:
print tag["href"]
หากทุกอย่างเป็นไปอย่างถูกต้อง #มันจะไม่บั๊คนะ เราจะได้ลิงค์ทั้งหมดปรากฏ #เย้ #จบซะที
… END …
แต่อย่างไรก็ตามทั้งหมดนี้ ก็เป็นเพียง #Basic เบื้องต้นของการทำ #SPIDER ในฉบับสมบูรณ์ยังมีอีกหลายส่วนที่ต้องศึกษา เช่น การทำให้โปรแกรมสามารถไต่ไปยังลิงค์ต่อไปได้อย่างต่อเนื่อง #เพิ่มอีกนิสเดียว, การคัดกรองลิงค์, การป้องกันไม่ให้เจอลิงค์กับดัก #คืออะไรหว่า #ไม่บอกหรอก และอีกมากมาย~
สุดท้ายนี้ ขอฝากคำพูดนึงไว้
ปล. ขออนุญาต และขอขอบคุณ Pantip.com ที่เป็นตัวอย่างในครั้งนี้