Web Scrape ไม่ใช่ Crepe.

kabelt
Super AI Engineer
Published in
4 min readDec 30, 2020

Requirements

  • ทักษะการเขียนโปรแกรมด้วยภาษา Python
  • ความรู้ด้านการจัดการกับชุดข้อมูลด้วย Pandas

Web Scraping คืออะไร?

นึกย้อนกลับไปตอนที่เราอยู่ชั้นประถม ตอนที่ความหมายของอินเทอร์เน็ตคือ sanook และ kapook ดอทคอม ตอนที่ความหมายของการทำรายงานคือการเข้ากูเกิล แล้วก๊อปปี้อะไรก็ตามที่เกี่ยวข้องกับหัวข้อนั้นๆ จากไม่กี่เว็บเพจ มาต่อๆกันเพื่อให้ได้จำนวนหน้าที่ต้องการ เวลาผ่านไปก็มีแพลตฟอร์มใหม่ๆเกิดขึ้นมามากมาย ปริมาณข้อมูลในอินเทอร์เน็ตเพิ่มมากขึ้นจนเกินจินตนาการ ความรับผิดชอบที่มากขึ้น รูปแบบความต้องการข้อมูลจากอินเทอร์เน็ตของเราก็เปลี่ยนไป แต่พวกเราส่วนใหญ่ยังสามารถเปิดดูข้อมูลจากเว็บไซต์ได้ทีละหน้าไม่ต่างจากตอนเด็กๆ

ปัญหานี้สามารถแก้ได้ง่ายๆ โดยอาศัยทักษะ Python พื้นฐาน ด้วยวิธีการที่เรียกว่า Web Scraping ซึ่งคือกระบวนการในการใช้บอทดึงข้อมูลบางอย่างออกมาจากเว็บไซต์ นักกฎหมายอาจต้องการคำพิพากษาศาลฎีกาตั้งแต่ปี 2463 จนถึงปัจจุบัน นักการตลาดอาจต้องการข้อมูล ความคิดเห็นของลูกค้าต่อผลิตภัณฑ์คู่แข่งเท่าที่จะมากได้ บ่าวสาวที่กำลังจะแต่งงานอาจกำลังมองหาเรือนหอหลังใหม่ อยากได้ข้อมูลบ้านทุกแบบ จากทุกโครงการที่กำลังประกาศขาย ก่อนที่จะตกลงปลงใจเป็นหนี้ร่วมกันไปอีก 30 ปี ซึ่งการได้มาซึ่งข้อมูลเหล่านี้ ถ้าต้องนั่งไล่เปิดเว็บไปทีละหน้า ก๊อบปี้ข้อมูลลง Spreadsheet ด้วยตนเองอาจจะใช้เวลาเป็นวันหรือหลายวัน แต่ Web Scraping สามารถทำให้เราได้ข้อมูลทั้งหมดที่ว่ามานี้ในเวลาแค่ไม่กี่นาที!

หลักการพื้นฐานของ Web Scraping คืออะไร?

ภาพที่ 1 : ตัวอย่างไฟล์ HTML

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

ซึ่งเมื่อนำไฟล์นี้ไปเปิด หรือที่เรียกว่าการนำไป “Render” บนบราวเซอร์ ก็จะได้หน้าเว็บดังภาพที่ 2 ออกมา

ภาพที่ 2 : ตัวอย่าง Webpage ที่ถูกเรนเดอร์จากไฟล์ HTML

ซึ่งเจ้าไฟล์ HTML นี้จะประกอบด้วยส่วนประกอบ หรือ “Tag” ต่างๆ ซึ่งโดยปกติแล้วผู้พัฒนาเว็บไซต์ก็จะสร้างให้แต่ละ Tag เก็บข้อมูลต่างชนิดกัน

จากในตัวอย่างข้างต้น ส่วนที่เป็นหัวข้อจะถูกเก็บไว้ในแท็ก <title> และส่วนที่เป็นเนื้อความก็จะถูกเก็บไว้ในแท็ก <p>

จากพื้นฐานนี้ เมื่อเราต้องการดึงข้อมูลส่วนหนึ่งส่วนใดออกมาจากหน้าเว็บ สิ่งที่เราต้องทำก็แค่…

  1. ให้บอทไปดึง HTML มาจากเว็บเป้าหมาย
  2. ดูว่าข้อมูลที่เราต้องการอยู่ในแท็กใด แล้วสั่งให้บอทไปดึงข้อมูลจากแท็กนั้น
  3. บันทึกข้อมูลที่ได้ลงฐานข้อมูล

เพียงแค่นี้เราก็สามารถดึงข้อมูลที่เราต้องการออกมาได้แล้วครับ

ทุกเว็บนี่ใช้วิธีดึงข้อมูลแบบเดียวกันหมดเลยไหม?

ปกติแล้วรูปแบบการ Render หน้าเว็บมีอยู่ด้วยกัน 3 รูปแบบครับ

  1. static site rendering เช่น เว็บที่เราเห็นเมื่อสิบปีก่อน
  2. server side rendering เช่น sanook.com
  3. client side rendering เช่น ไทยชนะ.com

ซึ่งเครื่องมือในการ Scraping ก็มีหลักๆ 3 ตัว ได้แก่ Selenium, Scrapy, และ BeautifulSoup ซึ่งในบทความนี้เราจะใช้ BeautifulSoup ซึ่งใช้งานง่ายที่สุด และสามารถดึงข้อมูลได้ดีจากทั้งเว็บประเภท static site rendering และ server side rendering ต่อไปเรามาลองลงมือทำกันเลยครับ

โจทย์ของเราคืออะไร และข้อมูลที่เราต้องการมีอะไรบ้าง?

คำถามที่เรากำลังลองพยายามหาคำตอบคือ “ข้าราชการทหารตำรวจระดับสูงมีความสัมพันธ์กับกลุ่มธุรกิจต่างๆอย่างไร?” โดยใช้ข้อมูลสาธารณะจากตลาดหลักทรัพย์แห่งประเทศไทย

ข้อมูลที่เราต้องการได้แก่

  • รายชื่อบริษัททุกบริษัท ที่จดทะเบียนอยู่ใน SET/MAI, อักษรย่อ, ราคาปัจจุบัน, มูลค่าบริษัทตามราคาตลาด,​ ประเภทธุรกิจ
  • รายชื่อกรรมการบริหารของบริษัท
  • รายชื่อผู้ถือหุ้นใหญ่พร้อมทั้งจำนวนหุ้นที่ถืออยู่
ภาพที่ 3 : หน้า URL รวมรายชื่อบริษัทในหมวดอักษร A

การดึงรายชื่อบริษัททุกบริษัท ที่จดทะเบียนอยู่ใน SET/MAI

ก่อนที่เราจะดึงข้อมูลอะไรก็ตามออกมา อันดับแรกต้องทำความเข้าใจโครงสร้างของเว็บไซต์นั้นๆ เพื่อดูว่าเราจะสามารถหาข้อมูลแต่ละชนิดที่ต้องการได้จาก URL ใด เมื่อเข้าไปที่ ลิงค์นี้ เราก็จะพบรายชื่อบริษัทต่างๆ ที่อยู่ในหมวดอักษร “A”

ภาพที่ 4 : การสร้าง URL ของแต่ละหน้ารายชื่อบริษัทตามหมวดอักษร

ในกรณีนี้ที่เราต้องการรายชื่อบริษัทจากทุกหมวดอักษร สิ่งที่ต้องทำก็เพียงแค่ เขียนลูปเพื่อสร้าง URL ของแต่ละหมวดอักษรขึ้นมาดังภาพที่ 4

ภาพที่ 5 : การตรวจสอบว่าข้อมูลที่เราต้องการอยู่ในแท็กใดผ่าน Inspect

ต่อมาสำหรับการดึงรายชื่อของหุ้นแต่ละตัวออกมาจาก URLs ข้างต้น อย่างที่กล่าวไปว่าเราจำเป็นที่จะต้องหาว่าข้อมูลที่เราต้องการอยู่ใน TAG ใด สำหรับผู้ใช้ Chrome สามารถหาอย่างง่ายดายโดยทำการเลือกข้อมูลส่วนที่เราต้องการจากนั้นคลิ๊กขวาเลือก Inspect ดังภาพที่ 5 ด้านบน

ภาพที่ 6 : หน้าต่างแสดงไฟล์ raw HTML แสดงแท็กที่มาของข้อมูลนั้นๆ

เมื่อคลิ๊ก Inspect ก็จะมีหน้า Developer Tools แทรกขึ้นมาดังภาพที่ 6 ที่จะแสดงว่าข้อมูลที่เราเลือกทำการ Inspect นั้นอยู่ในแท็กไหน อย่างเช่นกรณีนี้ชื่อของบริษัทก็จะอยู่ในแท็ก <td> เราก็จะเก็บข้อมูลตรงนี้ไว้เพื่อเป็นเป้าหมายให้ BeautifulSoup ของเราทำการค้นหาต่อไป

ภาพที่ 7 : ตัวอย่างการใช้ดึง HTML จาก URL โดยใช้ requests และการหาข้อมูลในแท็กโดยใช้ bs.find_all

เมื่อเรารู้แล้วว่าข้อมูลที่เราต้องการอยู่ในแท็กไหน ก็ลองเขียนโค้ดดึงข้อมูลดูได้เลยครับ จากภาพด้านบนในบรรทัดที่ 4 เป็นการใช้ requests เพื่อดึงไฟล์ HTML มาจาก URL จากนั้นทำการ parsing และดึงข้อมูลออกมาจากแท็กที่เราต้องการในบรรทัดที่ 5–6 จะเห็นได้ว่าข้อมูลที่ออกมา ค่อนข้างน่าพอใจ BeautifulSoup สามารถดึงข้อมูลออกมาจากแท็กที่เรากำหนดไว้ได้

ภาพที่ 8 : ตัวอย่างการใช้เมธอด .get_text() ดึงเฉพาะข้อมูลออกมาจากแท็ก

อย่างไรก็ตามสิ่งที่เราต้องการจริงๆ มีเพียงแค่ข้อมูลที่อยู่ข้างในแท็ก ตรงนี้เราสามารถใช้เมธอด .get_text() ดึงเฉพาะตัวข้อมูลออกมาได้ดังภาพที่ 8

ซึ่งจากภาพด้านบนจะเห็นได้ว่าชื่อย่อ ชื่อเต็ม และตลาดที่แต่ละบริษัทจดทะเบียนอยู่มันเรียงกันตามแพทเทินบางอย่าง ตรงนี้เราสามารถใช้ทักษะ Python พื้นฐานมาจัดกลุ่มให้มันอยู่ด้วยกันดังภาพที่ 9 ได้เลยครับ

ภาพที่ 9 : ตัวอย่างการจัดกลุ่มผลลัพท์ตามประเภท

เมื่อนำโค้ดทั้งหมดมาประกอบร่างกัน ผลลัพท์ที่ได้ก็จะเป็นดังภาพด้านล่างครับ

ภาพที่ 10 : ตัวอย่างชื่อบริษัท ชื่อย่อ ตลาดที่ทำการซื้อขายที่ได้จากการ Scraping

ใช้เวลาประมวลผลแค่ไม่กี่วินาที ก็ได้รายชื่อบริษัททั้งหมดกว่า 800 บริษัทในตลาดหลักทรัพย์มาแล้ว อะไรจะง่ายปานนั้น ^^

การดึงมูลค่าบริษัทตามราคาตลาด ประเภทธุรกิจ และรายชื่อกรรมการบริหาร

ภาพที่ 11 : การ Inspect เพื่อหาแท็กและคลาส ของมูลค่าบริษัทและประเภทธุรกิจ

ในการดึงมูลค่าบริษัท และประเภทธุรกิจ เมื่อเปิดเข้าไปในหน้าข้อมูลของแต่ละบริษัท อย่างเช่นในลิงค์นี้ แล้วทำการ Inspect จะพบว่าข้อมูลดังกล่าวอยู่ในแท็ก <div> ในคลาสที่มีชื่อว่า “col-xs-9 col-md-5”

ภาพที่ 12 : ตัวอย่างการดึงข้อมูลในแท็ก div คลาส “col-xs-9 col-md-5"

จากข้อมูลดังกล่าวเมื่อเราลองใช้เมธอด find_all() ของ Beautiful Soup ในการดึงข้อมูลจากแท็กและคลาสดังกล่าวก็จะได้ผลดังภาพที่ 12

ภาพที่ 13 : ตัวอย่างการดึงมูลค่าบริษัท และประเภทธุรกิจ

สังเกตุได้ว่ามูลค่าบริษัทนั้นจะอยู่ใน element ที่ 3 ส่วนประเภทธุรกิจนั้นจะอยู่ใน element ที่ 6 ของ result_by_calss ซึ่งเราสามารถนำข้อมูลตรงนี้ไปใช้งานต่อ เพื่อดึงข้อมูลเฉพาะส่วนที่เราต้องการได้ดังภาพที่ 13

ภาพที่ 14 : การ Inspect หาแท็กและคลาสสำหรับข้อมูลเกี่ยวกับกรรมการบริษัท

ในหน้า URL เดียวกันเลื่อนมาด้านล่างเราก็จะพบกับข้อมูลรายชื่อกรรมการบริหารเมื่อทำการ Inspect ดูจะพบว่าข้อมูลดังกล่าวอยู่ในแท็ก <div> ในคลาสชื่อ “col-xs-6” ดังภาพที่ 14

ภาพที่ 15 : ผลลัพธ์ที่ได้จากการดึงข้อมูลกรรมการบริหาร

และเมื่อลองดึงด้วยเมธอด .find_all() ก็จะได้ผลลัพธ์ออกมาดังภาพที่ 15

ภาพที่ 16 : ผลลัพธ์ที่ได้จากการดึงข้อมูลกรรมการบริหาร หลังกรองเฉพาะชื่อบุคคล

อย่างไรก็ตาม สิ่งที่เราต้องการมีเพียงแค่รายชื่อของกรรมการบริหาร เราไม่ได้ต้องการตำแหน่งของแต่ละคน ตรงนี้เราสามารถใช้พื้นฐาน Python เลือกเฉพาะ element ที่เป็นชื่อคน ซึ่งมีคุณลักษณะพิเศษ คือสามารถแบ่งด้วย space ออกมาได้เป็น 3 elements ดังบรรทัดที่ 6 ในภาพที่ 16

ภาพที่ 17 : ผลลัพธ์จากการดึงรายชื่อ มูลค่าบริษัท ประเภทธุรกิจ และกรรมการบริหาร

และเมื่อนำโค้ดทั้งหมดมาประกอบกันก็จะได้ผลลัพธ์ดังภาพที่ 17

การดึงรายชื่อผู้ถือหุ้นรายใหญ่ จำนวนหุ้นที่ถืออยู่ และราคาหุ้นปัจจุบัน

เหมือนเดิมเลยครับ เพียงแค่เราเปิดไปที่หน้านี้แล้วทำการ Inspect จะพบว่าข้อมูลสองรายการดังกล่าวอยู่ในแท็ก <td> เหมือนกัน ดังภาพที่ 18

ภาพที่ 18 : การ Inspect หาที่อยู่ของรายชื่อผู้ถือหุ้น และจำนวนหุ้น

แต่ต่างจากในกรณีก่อนๆ ตรงที่ แทนที่เราจะสามารถหาข้อมูลจากคลาสได้ ในกรณีนี้เราจะต้องหาข้อมูลจาก style และ align แทน อย่างในกรณีนี้ ชื่อผู้ถือหุ้นจะอยู่ใน style ที่ชื่อว่า “text-align:left;” ส่วนจำนวนหุ้นที่ท่านนั้นๆถืออยู่จะอยู่ในการ align แบบ “right”

ภาพที่ 19 : ตัวอย่างโค้ดการดึงรายชื่อผู้ถือหุ้น และจำนวนหุ้น

ซึ่งเราก็นำข้อมูลตรงนี้ไปประยุกต์ใช้กับเมธอด .find_all() โดยแทนที่จะระบุ “..class=” อย่างในบรรทัดที่ 10,14 ของภาพที่ 17 เราก็ระบุ style และ align ลงไปแทน อย่างในบรรทัดที่ 9,12 ในภาพที่ 19

ภาพที่ 20 : ตัวอย่างผลลัพธ์ที่ได้หลังจากที่ดึงข้อมูลทุกอย่างที่ต้องการเสร็จเรียบร้อย

เพียงเท่านี้เราก็จะได้รายชื่อผู้ถือหุ้นใหญ่ กับจำนวนหุ้นที่พวกเขาถืออยู่ออกมาแล้ว

สุดท้ายสำหรับราคาหุ้นปัจจุบันก็ทำเหมือนกันเลยครับ แต่เพื่อให้ tutorial นี้สมบูรณ์แบบขึ้นอีกนิด ส่วนราคาหุ้นปัจจุบันนี้ผมขออนุญาตไม่แชร์โค้ด ขอเป็น Challenge ให้ผู้อ่านได้ลองไปทำฝึกฝีมือกันดู ผลลัพธ์สุดท้ายที่ได้ก็จะออกมาหน้าตาประมาณภาพที่ 20 ครับ ^^

มีนายทหาร นายตำรวจคนไหน นั่งเป็นบอร์ด/เป็นผู้ถือหุ้นใหญ่ ในบริษัทใดบ้าง?

ภาพที่ 21 : บริษัทที่มีนายทหาร/นายตำรวจ เป็นกรรมการบริหาร เรียงตามมูลค่าบริษัท

ในที่นี้สิ่งที่เราต้องการคือทราบว่ามีนายทหารตำรวจคนไหนมีตำแหน่งเป็นกรรมการ หรือเป็นผู้ถือหุ้นใหญ่ในบริษัทอะไรบ้าง ในกรณีนี้เราสามารถค้นหาจากรายชื่อทั้งสองรายการที่เราได้มา โดยใช้คำนำหน้าชื่อ ยศ ของทหาร,ตำรวจ ได้เลยครับ ซึ่งจากผลที่ออกมาผมพบว่าจากประมาณ​ 800 กว่าบริษัทในตลาดหลักทรัพย์ มีบริษัทที่มีนายทหาร/นายตำรวจ เป็นกรรมการบริษัทถึงเกือบ 140 บริษัท และจากบริษัทดังกล่าว 10 บริษัทที่มีขนาดใหญ่ที่สุดตามมูลค่าตลาดปัจจุบันก็มีรายการดังภาพที่ 21

ภาพที่ 22 : สิบอันดับนายทหาร/ตำรวจ ที่มีสินทรัพย์เป็นหุ้นมูลค่ามากที่สุด

ในส่วนของการเป็นผู้ถือหุ้นใหญ่ของบริษัท สิบอันดับคนในเครื่องแบบที่รวยหุ้นมากที่สุดก็เป็นดังภาพที่ 22 จะเห็นได้ว่ามีนายตำรวจท่านหนึ่งมีทรัพย์สินที่เป็นหุ้น มีมูลค่า ณ. วันที่บทความนี้ถูกเขียนขึ้นถึงเกือบหมื่นล้าน โอ้วววว..

สุดท้ายถ้าผู้อ่านท่านใดเห็นว่าสิ่งที่อธิบายไปไม่ถูกต้อง มีข้อเสนอแนะอะไร สงสัยจุดไหน หรือนำข้อมูลที่ได้ไปวิเคราะห์ต่อแล้วได้ insight อะไร ก็คอมเมนท์หรือหลังไมค์มาแชร์กันได้เลยนะครับ แล้วพบกันใหม่โอกาสหน้าครับ.

--

--