ในปัจจุบันข้อมูลที่มีอยู่มากมายบนเวปไซต์ต่างๆ กำลังกลายเป็นหนึ่งในแหล่งข้อมูลที่สำคัญที่ช่วยสร้างความได้เปรียบทางด้านข้อมูล ทำให้การตัดสินใจต่างๆ ทำได้อย่างมีประสิทธิภาพมากยิ่งขึ้น เช่น การเก็บข้อมูลตลาด E-Commerce เพื่อเรียนรู้สินค้าขายดี หรือ ข้อมูลลูกค้าบน Social Media ที่บ่งบอกถึง Insight ของกลุ่มลูกค้า
แต่ไม่ใช่ทุกข้อมูลจะอยู่ในรูปแบบตารางที่ Copy มาใช้งานได้ง่ายๆ! จะดีกว่าไหม ถ้าเราสามารถเก็บข้อมูลจำนวนมากนี้ จัดการให้อยู่ในรูปแบบที่ใช้งานได้ง่าย และนี่คือ สิ่งที่ Web Scraping ช่วยทำให้เกิดขึ้นได้!
วันนี้ซิปป้าได้เรียบเรียงขั้นตอนการทำ Web Scraping ด้วย Python เอาไว้ และแปะบทความเกี่ยวกับการทำ Web Scraping ด้วย No Code และการใช้ AI เข้ามาช่วยเหลือ เป็น Guideline สำหรับทุกคนที่สนใจทำ Web Scraping เพื่อนำข้อมูลจากเวปไซต์ต่างๆ มาสร้างความได้เปรียบทางด้านข้อมูล ที่ทำตามแล้วได้ผลงานทันที และถ้าทำตัวอย่างนี้ได้ สามารถทำได้กับทุกเวปไซต์เลย! เป็นยังไงมาดูกัน!
หัวข้อในบทความนี้
การทำ Web Scraping ด้วย No Code + AI
ถ้าการเขียนโค้ด Python ไม่น่าสนใจสำหรับคุณสามารถใช้เครื่องมือ No Code ดึงข้อมูล และใช้ AI เตรียมข้อมูลต่อให้ได้ในบทความนี้ Webscraping ดึงข้อมูลหน้าเว็บลง Excel ด้วย No Code + AI ใน 3 ขั้นตอน
Web Scraping เทคนิคการดึงข้อมูลจากหน้าเวป
สำหรับข้อมูลที่แสดงเป็นข้อมูลสาธารณะอยู่บนหน้าเวป หากย้อนไปแต่ก่อนที่ยังไม่มีเครื่องมืออะไร หากเราต้องการข้อมูลเหล่านี้มาใช้งาน คงจะต้องนั่งคัดลอกส่วนที่ต้องการ มาแปะใน Excel ทำซ้ำๆ ไปเรื่อยๆ จนครบทั้งหน้าเวป ทำให้หลายๆ โปรเจคแทบเป็นไปไม่ได้ เพราะกว่าจะได้ข้อมูลมาใช้เวลานานมากๆ
การทำ Web Scraping ด้วย Python
แต่ในปัจจุบันมีเครื่องมือต่างๆ รวมไปถึง Library ของ Python ที่ช่วยทำให้การเก็บข้อมูลจากหน้าเวป และจัดการให้อยู่ในรูปแบบที่นำไปใช้ได้ง่าย ที่เราสามารถเรียกใช้ได้ง่ายๆ ทำให้การนำข้อมูลจากเวปไซต์ มาใช้เพื่อประกอบการตัดสินใจต่างๆ เป็นไปได้ง่ายขึ้น เข้าถึงคนทั่วไปอย่างเราๆ มากขึ้น
องค์ประกอบข้อมูล website ประกอบไปด้วย 2 อย่าง
ข้อมูลส่วนต่างๆ ที่นำมาประกอบบนหน้าเวป ไม่ว่าจะเป็นข้อความ, ลิ้งค์, ภาพ หรือข้อมูลอื่นๆ
HTML หรือโค้ดที่นำข้อมูลต่างๆ มาแปะในจุดต่างๆ ที่จะเป็นโค้ดที่ตัว browser นำมาใช้เพื่อกำหนดตำแหน่งต่างๆ ของข้อมูล
โดย Web Scraping คือ เทคนิคในการทำความเข้าใจตัวพื้นฐานของ HTML ของเวปไซต์ และใช้คำสั่งเพื่อดึงข้อมูลที่ต้องการที่อยู่ใน HTML ออกมา
HTML และ HTML Tag
HTML Tag เป็นส่วนย่อยของโค้ด HTML ซึ่งทำหน้าที่เป็นเหมือนโฟลเดอร์ ที่ใช้เก็บข้อมูลต่างๆ เอาไว้ โดยมีโครงสร้างที่ซ้อนๆ กันในลักษณะเดียวกันกับโฟลเดอร์บนคอมพิวเตอร์ ซึ่งในการดึงข้อมูลที่ต้องการ จะต้องอาศัยการระบุตำแหน่งของ HTML Tag ที่ต้องการ ผ่านการระบุรายละเอียดของ HTML Tag ที่ต้องการ ที่ประกอบด้วย ชื่อ และ attribute ต่างๆ
โดยหลักการที่สำคัญที่สุดในการทำ Web Scraping คือ การระบุตำแหน่งที่อยู่ของ HTML Tag ที่เก็บข้อมูลเอาไว้ ให้ Python หรือเครื่องมือที่กำลังใช้งาน สามารถเข้าไปยังตำแหน่งของ Tag ที่ต้องการ ก่อนที่จะส่งคำสั่งดึงข้อมูลจากตำแหน่งนั้นออกมา และนำไปจัดรูปแบบให้อยู่ในรูปแบบตารางต่อไป
โดยใน HTML Tag ใดๆ จะมีข้อมูลเบื้องต้นอยู่ 3 อย่างที่ประกอบไปด้วย
ชื่อ Tag โดยจะเป็นข้อมูลแรกที่เห็นอยู่ด้านซ้ายสุดของ Tag
ชื่อ Attribute โดยจะเป็นข้อมูลที่เขียนไว้หน้า = ซึ่ง Attribute เป็นเหมือนค่าต่างๆ ที่สามารถใช้เพื่อตั้งค่าการทำงานของ Tag นั้นๆ
Value ของ Attribute ใดๆ โดยจะระบุหลัง = คู่กับ Attribute เป็นค่าที่มีการตั้งไว้แตกต่างกัน เพื่อบันทึกข้อมูลที่แตกต่างกัน
โดยข้อมูลของ 1) ชื่อ Tag จะต้องมีอยู่ในทุก Tag แต่ 2) Attribute และ 3) Value ของ Attribute จะมีหรือไม่มีก็ได้ แล้วแต่ Tag
เริ่มต้นที่ Request-Response Cycle
ในการทำ Web Scraping เริ่มต้นจากการส่งคำสั่งเพื่อขอข้อมูลจากเวปไซต์มาใช้งานกับ Python โดยเราจะทำการเลียนแบบกระบวนการที่เรียกว่า request-response cycle หรือคือการขอข้อมูลของ website จาก server นั่นเอง
โดย request คือ กระบวนการขอข้อมูลจาก server ที่เปรียบเสมือนเวลาที่เรานำลิ้งค์ของ website ไปวางในช่อง url หรือ เวลาที่เรากดลิ้งค์ของ website
และ response คือ กระบวนการส่งข้อมูลจาก server กลับมายัง browser ของเรา โดย browser จะทำการตีความข้อมูลที่ได้รับโดยเฉพาะ HTML ที่ browser จะอ่านโค้ด HTML แล้ว นำข้อมูลที่ได้รับมาเรียงกันเป็นหน้าเวปที่สวยงาม
ติดตั้ง และนำคำสั่ง requests มาใช้
requests เป็นชุดคำสั่งที่รวมคำสั่งสำหรับการส่งคำสั่งทำงานกับ server เพื่อทำงานกับข้อมูลของเวปไซต์ โดยเราจะใช้เพื่อขอข้อมูลของเวปไซต์ที่ต้องการ
สำหรับ requests เป็น Library หรือชุดคำสั่งสำเร็จรูปซึ่งหากเราต้องการใช้งานจะต้องติดตั้งผ่าน !pip install บน Jupyter Notebook โดยการติดตั้งทำครั้งเดียวเพื่อดาวน์โหลดคำสั่งนี้มาบันทึกไว้บนคอมพิวเตอร์
In [1]:
!pip install requests
หากมีการติดตั้งเรียบร้อยจะมีข้อความแจ้งประมาณนี้ที่บอกว่า Requirement already satisfied อาจมีรายละเอียดที่แตกต่างกันไปบ้าง หากยังไม่เคยติดตั้งจะปรากฏเป็นหลอดแสดงเปอร์เซ็นต์การดาวน์โหลด
Requirement already satisfied: requests ...
เมื่อมีคำสั่ง requests แล้วจะต้องมีการนำเข้าคำสั่ง requests มาใช้งาน ต้องทำทุกครั้งเมื่อเปิดไฟล์คำสั่งเมื่อต้องการใช้งาน
In [2]:
import requests
requests ข้อมูลจากเวปไซต์ที่ต้องการ
การขอข้อมูลจากเวปไซต์ที่ต้องการจะทำผ่านคำสั่ง requests.get() ที่ระบุตัว url ของเวปไซต์เป็น string object ใส่เป็น argument โดยจะได้ข้อมูลออกมาเป็น response object ที่มี HTTP Code กำกับ สำหรับเวปไซต์ที่มีการส่งข้อมูลกลับมาเรียบร้อยจะมี HTTP Code 200 ส่งกลับมา
สร้าง string object ที่เก็บลิ้งค์ที่ต้องการขอข้อมูลไว้ในตัวแปร url
In [3]:
url = 'https://www.checkraka.com/house/quicksearch_order=update%2CDESC&page=1'
url
ใช้คำสั่ง requests.get() ระบุเวปไซต์ที่ต้องการเป็น argument เพื่อ request ข้อมูล โดยจะได้ข้อมูลมาในรูปแบบของ response object
In [4]:
data = requests.get(url)
data
Out [4]:
<Response [200]>
ข้อมูลที่ได้จากการ request ข้อมูล
สำหรับ response object ที่ได้รับมาหลังรันคำสั่ง requests.get() จะใช้คำสั่ง .text เพื่อดึง HTML ของเวปไซต์ที่ได้รับมาให้ออกมาอยู่ใน string object เพื่อนำไปใช้งานต่อ
สำหรับเวปไซต์ใดๆ ก็ตามที่จะนำมาทำงานด้วยในลักษณะนี้ จะต้องเช็คก่อนว่า ข้อมูลที่เราต้องการนั้นอยู่ใน HTML ที่ปรากฏขึ้นมาหรือไม่ โดยการใช้ search ง่ายๆ ผ่าน browser หรือ กด ctrl + f
เพราะสำหรับการทำงานของบาง website จะไม่สามารถทำการขอข้อมูลลักษณะนี้ เพื่อให้ได้ข้อมูลที่พร้อมใช้ ซึ่งจะเหมาะกับชุดคำสั่งในรูปแบบอื่นๆ
In [5]:
data.text
Out [5]:
'\t<!DOCTYPE html>\r\n<html lang="th">\r\n<head>\r\n\t<title>บ้านใหม่ทุกโครงการ เรียงตามข้อมูลล่าสุด หน้าละ 10 โครงการ ราคา-โปรโมชั่นล่าสุด | เช็คราคา.คอม</title>...</html>'
เมื่อเช็คเรียบร้อยว่ามีข้อมูลที่กำลังต้องการดึงจากเวปไซต์ในข้อมูลที่ได้มาจาก response object เราก็จะได้ HTML ที่พร้อมสำหรับการทำ Web Scraping แล้ว
ดึงข้อมูลด้วย BeautifulSoup
เมื่อได้ HTML ที่พร้อมใช้จากการทำ requests.get() มาแล้ว เราจะนำ HTML นี้มาใช้งานกับชุดคำสั่ง BeautifulSoup ที่จะช่วยแปลงข้อมูลเป็น object ที่เหมาะกับการทำ web scraping ที่รวบรวมคำสั่งเพื่อการระบุตำแหน่งของ Tag ที่เราต้องการดึงข้อมูลให้ง่ายกว่าการทำงานกับ string object
ติดตั้ง และนำคำสั่ง BeautifulSoup มาใช้
ติดตั้งผ่าน !pip install เช่นเดียวกัน และหากมีการติดตั้งไว้เรียบร้อยแล้วจะมีข้อความแจ้งประมาณว่า Requirement already satisfied ที่อาจมีรายละเอียดต่างจากตัวอย่างบ้าง แต่หากยังไม่เคยติดตั้ง จะมีแถบดาวน์โหลดข้อมูลขึ้นมา
In [6]:
!pip install bs4
Requirement already satisfied: bs4 ...
เช่นเดียวกันคำสั่ง bs4 เมื่อต้องการนำมาใช้งาน จะต้อง import เข้ามา ในทุกครั้งที่เปิด Jupyter Notebook ขึ้นมาใหม่
แปลง HTML ที่อยู่ในรูปแบบของ String เป็น Beautifulsoup
สำหรับการจัดการข้อมูล HTML โดยเฉพาะการทำ web scraping การใช้งาน BeautifulSoup object จะช่วยให้เราสามารถเข้าถึงคำสั่งในการดึงข้อมูลที่ต้องการได้ง่ายๆ ใช้เพียงไม่กี่คำสั่ง ซึ่งจะง่ายกว่าการดึงข้อมูลจาก HTML ที่อยู่ในรูปแบบของ String
โดยการแปลงข้อมูล HTML ที่อยู่ในรูปแบบของ String ให้เป็น BeautifulSoup Object ทำได้ผ่านคำสั่ง bs4.BeautifulSoup() ที่รับ HTML ที่อยู่ในรูปแบบ String และสร้างข้อมูลใหม่เป็น BeautifulSoup Object ที่เก็บข้อมูล HTML เอาไว้
การแปลงข้อมูล HTML ที่อยู่ในรูปแบบของ String เป็น BeautifulSoup Object ด้วยคำสั่ง bs4.BeautifulSoup() เราจะได้ HTML ที่เก็บอยู่ใน BeautifulSoup Object
In [7]:
soup = bs4.BeautifulSoup(data.text)
soup
Out [7]:
<!DOCTYPE html>
<html lang="th">
<head>
<title>บ้านใหม่ทุกโครงการ เรียงตามข้อมูลล่าสุด หน้าละ 10 โครงการ ราคา-โปรโมชั่นล่าสุด | เช็คราคา.คอม</title>
...
</body>
</html>
เมื่อ HTML ที่พร้อมใช้อยู่ในรูปแบบของ BeautifulSoup Object แล้ว เราจะสามารถใช้คำสั่งต่างๆ เพื่อทำการระบุข้อมูลที่อยู่ใน HTML ออกมาได้อย่างแม่นยำ และตรงกับข้อมูลที่ต้องการได้ง่าย
การค้นหา "Tag ที่เก็บ 1 รายการ" เอาไว้
เมื่อเราได้ข้อมูลที่พร้อมใช้คำสั่งเพื่อดึงข้อมูลมาแล้ว สิ่งที่ต้องทำถัดไป คือการระบุให้ Python ทราบว่าจะดึงข้อมูลที่อยู่ใน Tag ไหน โดยเราจะต้องหา "Tag ที่เก็บ 1 รายการ" ให้เจอ
โดยหลักการหา "Tag ที่เก็บ 1 รายการ" ให้เจอ ต้องเล่าย้อนไปถึงการเลือกหน้าเวปไซต์ที่เหมาะกับการดึงข้อมูลหรือทำ web scraping นั่นคือหน้าเวปที่มีการแสดงข้อมูลใน pattern หน้าตาซ้ำๆ อย่างเวป E-Commerce ที่มีหลายๆ สินค้าเรียบเรียงกันใน 1 หน้า, Social Media ที่มีโพสท์/ข้อความแต่ละอันเรียบเรียงกันด้วยโครงสร้างซ้ำๆ เดิม หรือเวปเปรียบเทียบราคาที่ใช้เป็นตัวอย่าง ที่มีการแสดงข้อมูลแต่ละสินค้าอยู่ในโครงสร้างคล้ายๆกัน
หน้าเวปไซต์เหล่านี้มักมีการใช้โครงสร้างของโค้ด หรือ HTML ที่มีลักษณะซ้ำๆ กันเช่นเดียวกัน ทำให้เราสามารถเลือก "Tag ที่เก็บ 1 รายการ" ระบุรายละเอียดของ Tag นั้น และใช้คำสั่งเพื่อดึงข้อมูลที่มีโครงสร้าง Tag คล้ายๆ กัน เพื่อดึงข้อมูลจากทุกรายการออกมาได้ในภายหลัง
โดย "Tag ที่เก็บ 1 รายการ" จะเป็น Tag ที่เมื่อระบุได้เหมาะสมจะต้องมีคุณสมบัติอยู่ 2 อย่าง
จะต้องครอบคลุมพื้นที่การแสดงผลของข้อมูล 1 รายการ ที่เปรียบเทียบอยู่กับข้อมูลทั้งหมดในหน้าเวปนั้น
ข้อมูลที่เหมาะสมจะมีโครงสร้างที่เหมือนกันในทุกรายการ สามารถใช้รายละเอียดเดียว ดึงข้อมูลได้ทุกรายการ
และการระบุ Tag ที่ต้องการเราจะระบุข้อมูล 3 อย่างได้แก่
ชื่อ Tag
Attribute ที่ต้องการระบุ
Value ของ Attribute นั้นๆ
In [8]:
all_unit_tag = 'div'
all_unit_attribute = 'class'
all_unit_value = 'content c44'
ค้นหา Tag ที่ต้องการ ด้วย .find()
เมื่อได้รายละเอียดของ "Tag ที่เก็บ 1 รายการ" แล้ว เราจะทำการให้ Python เข้าไปค้นหา Tag นั้นจากข้อมูลจากทั้งเวป หรือข้อมูล HTML ที่อยู่ใน BeautifulSoup Object นั่นเอง ผ่านคำสั่ง .find() ที่จะมีการค้นหา Tag ตามรายละเอียดที่กำหนด โดยจะเลือกหยิบ Tag แรกที่เจอ โดยมีลำดับการค้นหาจาก Tag ที่อยู่ด้านบนของ HTML ทั้งหมดไล่ลงมาด้านล่าง โดยเราจะกำหนดรายละเอียดของ Tag ทั้ง 3 อย่างในลักษณะนี้ (ชื่อ tag, {ชื่อ attribute:ค่า attribute}) และนำข้อมูลนี้กำหนดเป็น argument สำหรับคำสั่ง .find()
โดยจะได้ข้อมูลเป็น HTML แค่ในส่วนที่ตรงกับรายละเอียดของ Tag ที่ต้องการ หรือการตัด HTML มาแค่ส่วนที่ค้นหานั่นเอง ซึ่งทำให้การจัดการกับข้อมูลง่ายขึ้น แทนที่จะต้องทำงานกับข้อมูลทั้งเวปไซต์ ก็จะเหลือการทำงานกับข้อมูลแค่ส่วนที่เป็น 1 ข้อมูล
In [9]:
first_unit_element = soup.find(all_unit_tag,{all_unit_attribute:all_unit_value})
first_unit_element
<div class="content c44">
...
<div class="name"><a href="/house/sansiri/siri-place/1450457/" target="_blank">สิริ เพลส แอร์พอร์ต ภูเก็ต (Siri Place Airport)</a></div>
...
</li>
</ul>
</div>
เมื่อเราได้ข้อมูล Tag ที่เก็บ 1 รายการเอาไว้ เราก็จะนำข้อมูลนี้ไปสกัดหาข้อมูลที่เป็นส่วนประกอบของ 1 รายการต่อไป เช่น ชื่อสินค้า และราคา
ค้นหา Tag ที่เก็บข้อมูลที่ต้องการใน "Tag ที่เก็บ 1 รายการ"
เมื่อได้ข้อมูล Tag ที่เก็บ 1 รายการมาเรียบร้อย เราจะทำการระบุข้อมูลส่วนที่ต้องการจากข้อมูลทั้งหมด เช่น ชื่อสินค้า จากสินค้า 1 รายการ ซึ่งเราสามารถทำได้ในลักษณะเดียวกันกับการดึง 1 รายการจาก เวปไซต์ ผ่านคำสั่ง .find()
โดยเริ่มต้นจากการค้นหา 1) ชื่อ Tag 2) Attribute 3) และ Value ของ Attribute ที่เหมาะสม ที่ครอบคลุมพื้นที่การแสดงผลของข้อมูลที่ต้องการดึง และมีโครงสร้างที่เหมือนกันในแต่ละข้อมูล สามารถใช้รายละเอียดเดียว ข้อมูลที่ต้องการได้จากทุกข้อมูล
กำหนดรายละเอียด Tag สำหรับชื่อรายการสินค้า
ซึ่ง Tag ที่ต้องการ อาจมีแค่ชื่อ Tag โดยไม่มี Attribute และ Value ของ Attribute ที่เหมาะสมก็ได้
In [10]:
title_tag = 'a'
ค้นหา Tag จากใน Tag ของ 1 รายการสินค้า
เมื่อได้ Tag ที่เก็บข้อมูลที่ต้องการไว้แล้ว เราจะใช้คำสั่ง .find() ในการดึง Tag ที่เก็บข้อมูลนั้นไว้ แต่เปลี่ยนจากการดึงข้อมูลจากทั้งเวปไซต์ เป็นการค้นหาข้อมูลของ 1 รายการ
และผลลัพธ์ที่ได้ เราจะได้ข้อมูลเป็นส่วนที่ย่อยลงจาก Tag ที่เก็บ 1 รายการมาอีกที ทำให้เราได้ข้อมูลที่ตรงกับที่ต้องการมากยิ่งขึ้น โดยข้อมูลนี้จะยังอยู่ใน Tag Object ที่จะต้องส่งคำสั่งสกัดข้อมูลออกมาอีกครั้ง
In [11]:
first_name_element = first_unit_element.find(title_tag)
first_name_element
Out [11]:
<a href="/house/sansiri/siri-place/1450457/" target="_blank">สิริ เพลส แอร์พอร์ต ภูเก็ต (Siri Place Airport)</a>
สกัดข้อมูลที่ต้องการออกจาก Tag
เมื่อได้ Tag ที่เก็บข้อมูลของ 1 รายการ ที่ต้องการไว้เรียบร้อย เราจะใช้คำสั่งต่างๆ เพื่อดึงข้อมูลออกมาจาก Tag โดยหากข้อมูลที่เก็บอยู่เป็นข้อมูลที่เป็น Text หรือข้อความ ที่เราสามารถ copy จากหน้าเวปผ่านการลากเมาส์ครอบ แล้ว copy ออกมาได้ เราจะใช้คำสั่ง .text เพื่อดึงข้อมูลส่วนนั้นออกมาให้อยู่ในรูปแบบของ String Object
In [12]:
first_name_element.text
Out [12]:
'สิริ เพลส แอร์พอร์ต ภูเก็ต (Siri Place Airport)'
การค้นหาข้อมูลเพิ่มเติมจาก 1 รายการ
ใน Tag ที่เก็บ 1 รายการไม่ได้มีเพียงแค่ข้อมูลอย่างเดียว แต่ประกอบไปด้วยข้อมูลหลายอย่างของสินค้าใน 1 รายการนั้น ซึ่งเมื่อนำไปใช้จริง หากต้องการดึงข้อมูลหลายอย่างออกมา เราจะใช้การดึงข้อมูลทีละอย่าง ผ่านการระบุ 1) ชื่อ Tag 2) Attribute 3) Value ของ Attribute จนครบข้อมูลที่ต้องการ
กำหนดรายละเอียด Tag สำหรับราคารายการสินค้า
สำหรับข้อมูลตัวอย่างเราจะดึงข้อมูลราคามาเพิ่มเติม ซึ่งเช่นเดียวกันป็นการดึงข้อมูลชื่อรายการสินค้า เราจะระบุรายละเอียดที่เหมาะสมก่อน
In [13]:
price_tag = 'div'
price_attribute = 'class'
price_value = 'price'
ดึง Tag ที่ต้องการจาก Tag รายการสินค้า
และใช้คำสั่งเดียวกัน คือ .find() ที่กำหนดรายละเอียดของ Tag ที่ต้องการค้นหา ซึ่งจะได้ข้อมูลมาเป็น Tag ที่มีการเก็บข้อมูลตามรายละเอียดที่กำหนด ซึ่งจะใช้เพื่อสกัดข้อมูลต่อไป
In [14]:
first_price_element = first_unit_element.find(price_tag,{price_attribute:price_value})
first_price_element
Out [14]:
<div class="price">เริ่มต้น 1.99 ลบ. <span>(ณ. วันที่ 25/7/2022)</span></div>
เทคนิคการสกัดข้อความให้ได้แค่ส่วนใน Tag ปัจจุบัน
สำหรับ Tag ที่เลือกมา จะสังเกตเห็นว่าข้อความที่เก็บอยู่ใน Tag มีแค่บางส่วนเท่านั้นที่เป็นข้อมูลที่ตรงกับสิ่งที่ต้องการ หรือคือเป็นราคา ซึ่งข้อมูลที่ต้องการอยู่ในส่วนของ Tag ที่ดึงมา ไม่รวมส่วนของข้อความที่อยู่ใน Tag ที่อยู่ใน Tag ที่เลือกมาอีกที (Tag ที่ชื่อว่า span) สำหรับกรณีนี้ เราสามารถดึงข้อความจาก Tag ปัจจุบันอย่างเดียว โดยไม่ดึงข้อความอื่นๆ ใน Tag ออกมาได้ด้วยคำสั่ง .find() โดย กำหนด text=True เพื่อดึงข้อความเฉพาะส่วนที่สนใจ
In [15]:
first_price_element.find(text=True)
Out [15]:
'เริ่มต้น 1.99 ลบ. '
เมื่อสามารถระบุข้อมูลทุกอย่างที่ต้องการได้จาก 1 รายการ เราจะทำการบันทึกข้อมูลเหล่านี้ลงใน Dictionary ซึ่งข้อมูลใน 1 Dictionary จะกลายเป็นข้อมูล 1 แถวที่เราจะรวบรวมขึ้นเป็นตารางอีกที
บันทึกข้อมูล 1 รายการลง Dictionary
Dictionary เป็นโครงสร้างข้อมูลที่มีการเก็บข้อมูลคล้ายคลึงกับการเก็บข้อมูลสำหรับข้อมูล 1 แถว นั่นคือ 1 แถวมีข้อมูลที่หลากหลายจากหลายคอลัมน์ ที่มีความแตกต่างกัน ตามคอมลัมน์ของข้อมูลนั้นๆ
ใน Dictionary ก็จะมีการเก็บข้อมูลที่มีการระบุสิ่งที่เรียกว่า key-value pair สำหรับการบันทึกข้อมูลที่เก็บได้มาคู่กับ key ที่ข้อมูลนี้จะถูกนำไปสร้างเป็นคอลัมน์ในอนาคตนั่นเอง
สร้าง Dictionary สำหรับการบันทึกข้อมูล
โดยการบันทึกข้อมูลลง Dictionary สำหรับเป็นตัวแทนของข้อมูล 1 แถว เริ่มต้นจากการสร้าง Dictionary ที่ไม่มีข้อมูลขึ้นมาก่อน
In [16]:
data_dict = dict()
บันทึกข้อมูลที่ต้องการลง Dictionary ตามข้อมูลที่เก็บมา
และทำการนำข้อมูลที่ดึงมาได้ใส่เข้าไปใน Dictionary โดยมีการกำหนด key ที่ต้องการเก็บข้อมูลนั้นๆ (หรือจินตนาการว่าสิ่งนี้คือ คอลัมน์ของตารางในอนาคต) เช่น ชื่อรายการสินค้าเก็บไว้ใน key ที่ชื่อว่า title และราคาเก็บไว้ใน key ที่ชื่อว่า price จะสามารถเขียนเป็นคำสั่งได้ในลักษณะนี้
In [17]:
data_dict['title'] = first_name_element.text
data_dict['price'] = first_price_element.text
เมื่อบันทึกข้อมูลลง Dictionary แล้ว เราก็จะได้ข้อมูลของ 1 แถวมาเก็บไว้เรียบร้อย
In [18]:
data_dict
Out [18]:
{'title': 'สิริ เพลส แอร์พอร์ต ภูเก็ต (Siri Place Airport)',
'price': 'เริ่มต้น 1.99 ลบ. (ณ. วันที่ 25/7/2022)'}
ซึ่งข้อมูล 1 Dictionary จะถูกนำไปสร้างเป็นข้อมูล 1 แถวในตารางที่จะใช้เก็บข้อมูลทั้งหมด ซึ่งเมื่อเราทราบวิธีการดึงข้อมูล 1 รายการออกมาแล้ว เราจะทำการใช้คำสั่งเพื่อทำงานกับข้อมูลทุกรายการ และทำคำสั่งดึงข้อมูล และบันทึกลง Dictionary ซ้ำจนครบกับทุกข้อมูล
การดึงข้อมูลทุกรายการที่มีอยู่บนหน้าเวป¶
เมื่อเราสามารถกำหนด Tag ที่เก็บข้อมูล 1 รายการได้เหมาะสม เราสามารถใช้รายละเอียดของ Tag ที่เก็บข้อมูล 1 รายการมาใช้สำหรับการดึงทุกรายการที่อยู่บ้านหน้าเวปได้ผ่านคำสั่ง .find_all() โดยมีการใช้งาน การกำหนด argument ลักษณะเดียวกับการใช้งาน .find()
ดึงทุกรายการด้วย .find_all()
โดยเราจะได้ข้อมูลของทุกรายการมาอยู่ในรูปแบบของ List ที่เก็บ Tag ต่างๆ เอาไว้
In [19]:
all_unit_element = soup.find_all(all_unit_tag,{all_unit_attribute:all_unit_value})
all_unit_element
Out [19]:
[<div class="content c44">
...
<div class="name"><a href="/house/sansiri/siri-place/1450457/" target="_blank">สิริ เพลส แอร์พอร์ต ภูเก็ต (Siri Place Airport)</a></div>
...
</ul>
</div>]
ใช้ For Loop เข้าไปทำงานกับทีละรายการ ดึงข้อมูล และบันทึกลง List
และเมื่อได้ Tag ที่เก็บข้อมูลแต่ละรายการเอาไว้ เราก็จะทำการดึงข้อมูลทีละรายการออกมา และนำข้อมูลแต่ละรายการมาสกัดหาข้อมูลที่ต้องการนั่น คือ ชื่อสินค้าในแต่ละรายการ และราคาของสินค้าชิ้นนั้น
ซึ่งข้อมูลของสินค้าแต่ละรายการจะถูกบันทึกลง Dictionary เป็นตัวแทนของข้อมูลแต่ละแถว ซึ่งข้อมูลแต่ละแถวต้องถูกบันทึกลงข้อมูล List อีกครั้ง ผ่านการใช้คำสั่ง .append() เพื่อบันทึกข้อมูลแต่ละแถวซ้อนกัน ก่อนนำไปสร้างเป็นตาราง
ดังนั้นการทำงานกับทุกรายการที่อยู่ในรูปแบบของ List จึงต้องมีการสร้าง List ใหม่ที่ไม่มีข้อมูลเพื่อใช้บันทึกข้อมูลของแต่ละรายการที่จะเกิดขึ้น และใช้ For Loop เข้าไปดึงข้อมูลแต่ละรายการออกจาก List ของรายการทั้งหมด
In [20]:
data_list = []
for unit in all_unit_element:
data_dict = dict()
data_dict['title'] = unit.find(title_tag).text
data_dict['price'] = unit.find(price_tag,{price_attribute:price_value}).text
data_list.append(data_dict)
ข้อมูลสุดท้ายที่จะได้ คือ List ของ Dictionary ที่เก็บข้อมูลทุกรายการไว้ใน List ที่มีแต่ละรายการเก็บไว้ใน Dictionary ซึ่งเป็นรูปแบบที่พร้อมเปลี่ยนให้เป็นตาราง
In [21]:
data_list
Out [21]:
[{'title': 'สิริ เพลส แอร์พอร์ต ภูเก็ต (Siri Place Airport)',
'price': 'เริ่มต้น 1.99 ลบ. (ณ. วันที่ 25/7/2022)'},
...,
{'title': 'พฤกษ์ลดา ทางด่วนรามอินทรา-จตุโชติ (Prueklada Ramindra Expressway-Chatuchot)',
'price': '6 - 9 ลบ. (ณ. วันเปิดตัว)'}]
การเข้าถึงทุกหน้าเวปที่อยู่บนเวปไซต์
ด้วยโครงสร้างของเวปไซต์ที่มีหน้าตาซ้ำๆ กันทุกหน้า เมื่อเราสามารถดึงข้อมูลจาก 1 หน้าเวปไซต์ได้ เราก็สามารถดึงข้อมูลจากทุกหน้าเวปไซต์ได้ด้วยคำสั่งเดียวกัน หากแต่เราต้องมีการเข้าถึงทุกเวปไซต์ให้ได้ เพื่อนำคำสั่งที่เราสร้างเอาไว้ ไปดึงข้อมูลจากแต่ละหน้าเวป หนึ่งในวิธีการเข้าถึงทุกหน้าเวปไซต์ คือ การสร้างลิ้งค์สำหรับทุกเวปไซต์ที่เราต้องการเข้าไปทำงานด้วย ซึ่งสำหรับในตัวอย่างของเราสามารถสร้างตัวลิ้งค์ที่มีการเปลี่ยนแปลงตัวเลขหน้าเวปให้ครบทุกหน้า และนำแต่ละหน้ามาทำตามคำสั่งเพื่อดึงข้อมูลแต่ละหน้าที่เขียนไว้เรียบร้อยได้เลย
การใช้ While Loop สร้างเงื่อนเปลี่ยนตัวเลข เพื่อใช้สร้างเป็น url
การสร้างลิ้งค์ที่มีการเปลี่ยนแปลงตัวเลขตามหน้าที่เปลี่ยนไปสามารถใช้เงื่อนไขอย่าง While Loop เพื่อเปลี่ยนตัวเลขของเลขหน้าไปเรื่อยๆ จนครบจำนวนที่กำหนดได้
In [22]:
page = 1
while page < 369:
print(page)
page += 1
เราจะเห็นตัวเลขแสดงขึ้นมาตามการเปลี่ยนแปลงที่เกิดขึ้นใน while loop ซึ่งเราจะนำตัวเลขที่เปลี่ยนแปลงนี้ไปประกอบเป็น url ที่มีการเปลี่ยนหน้าไปเรื่อยๆ
1
2
3
...
368
การประกอบตัวเลขเข้ากับ url เพื่อสร้าง url ของแต่ละหน้า
โดยเราจะนำ url ที่ตัดเลขหน้าออก มาประกอบตัวกับเลขที่แปลงเป็นตัว String เพื่อให้สามารถเชื่อมกลายเป็น url ได้ โดยนำคำสั่งเข้าไปใน while loop เพื่อให้มีการรันตัวเลขใน url อัตโนมัติ
In [23]:
page = 1
while page < 369:
url = 'https://www.checkraka.com/house/?quicksearch_order=update%2CDESC&page=' + str(page)
print(url)
page += 1
While Loop เมื่อใส่คำสั่งในการสร้าง url เข้าไป ก็จะปรากฏเป็นหน้าเวปแต่ละหน้าที่รันเลขตามหน้าเลขจนครบทั้งเวปไซต์
https://www.checkraka.com/house/?quicksearch_order=update%2CDESC&page=1
https://www.checkraka.com/house/?quicksearch_order=update%2CDESC&page=2
https://www.checkraka.com/house/?quicksearch_order=update%2CDESC&page=3
...
https://www.checkraka.com/house/?quicksearch_order=update%2CDESC&page=368
การเก็บข้อมูลจากทั้งเวปไซต์
เมื่อเราได้การเข้าถึงหน้าเวปทุกหน้าผ่านลิ้งค์ที่สร้างขึ้นมาได้แล้ว สามารถดึงข้อมูลแต่ละหน้าบันทึกไว้ใน List ได้แล้ว เราสามารถนำทุกส่วนมาประกอบกัน เพื่อสร้างเป็นการทำงานที่เข้าไปเก็บข้อมูลจากทั้งเวปไซต์ได้ผ่านการคลิกแค่คลิกเดียว!
ประกอบคำสั่งให้เก็บข้อมูลได้จากทั้งเวปไซต์
โดยส่วนนี้จะมีการจัดเรียงคำสั่งต่างๆ ในส่วนต่างๆ ดังนี้ และเพิ่มส่วนของการ print() ข้อความที่แจ้งว่ากำลังทำงานกับหน้าไหนอยู่เพื่อติดตามผล
In [24]:
#ที่เก็บข้อมูลของทั้งเวปไซต์
data_list = []
#การเข้าถึงลิ้งค์ของทุกเวปไซต์
page = 1
while page < 369:
url = 'https://www.checkraka.com/house/?quicksearch_order=update%2CDESC&page=' + str(page)
print(url)
page += 1
#ดึงข้อมูลของ 1 หน้าเวป
data = requests.get(url)
#แปลงเป็น BeautifulSoup
soup = bs4.BeautifulSoup(data.text)
#รายละเอียดข้อมูล 1 รายการ
all_unit_tag = 'div'
all_unit_attribute = 'class'
all_unit_value = 'content c44'
#รายละเอียดข้อมูลชื่อสินค้าในรายการนั้นๆ
title_tag = 'a'
#รายละเอียดข้อมูลราคาในสินค้ารายการนั้นๆ
price_tag = 'div'
price_attribute = 'class'
price_value = 'price'
#ดึงทุกรายการ
all_unit_element = soup.find_all(all_unit_tag,{all_unit_attribute:all_unit_value})
#ดึงข้อมูลทีละรายการบันทึกลง List
for unit in all_unit_element:
data_dict = dict()
data_dict['title'] = unit.find(title_tag).text
data_dict['price'] = unit.find(price_tag,{price_attribute:price_value}).text
data_list.append(data_dict)
#แจ้งเบื้องต้นว่าทำงานถึงหน้าไหน
print('Completed page no. ...', page)
Scraping page no. ... 1
Scraping page no. ... 2
Scraping page no. ... 3
...
Scraping page no. ... 368
ข้อมูล List ของ Dictionary ที่เก็บข้อมูลทั้งเวปไซต์
ข้อมูลจากการเก็บข้อมูลมาจากทั้งเวปไซต์ จะอยู่ในรูปแบบของ List ของ Dictionary ที่ List เป็นตัวแทนของข้อมูลแต่ละแถวที่เรียงซ้อนกัน และ Dictionary ข้างในแต่ละตัวเป็นตัวแทนของข้อมูลที่จะอยู่ในแต่ละแถวของตาราง
In [25]:
data_list
Out [25]:
[{'title': 'สิริ เพลส แอร์พอร์ต ภูเก็ต (Siri Place Airport)',
'price': 'เริ่มต้น 1.99 ลบ. '},
...]
บันทึกข้อมูลลง DataFrame
สำหรับการบันทึกข้อมูลลง Excel สามารถทำได้ผ่านการแปลงข้อมูลให้อยู่ใน DataFrame Object ที่สร้างผ่านการใช้ Pandas Library ซึ่งเราสามารถติดตั้ง และนำมาใช้งานได้ง่ายๆ ผ่านคำสั่ง !pip install
ติดตั้ง และนำ Pandas มาใช้งาน
Pandas เป็น Library ที่รวบรวมคำสั่งสำหรับการทำงานกับข้อมูลตารางไว้อย่างหลากหลาย สามารถติดตั้งผ่าน !pip install ได้เลย
In [26]:
!pip install pandas
Requirement already satisfied: pandas ...
เมื่อติดตั้งแล้ว สามารถนำเข้ามาใช้งานได้ผ่าน import โดยจะนิยมตั้งชื่อเล่นให้ Pandas ผ่านคำสั่ง as ให้เป็นชื่อ pd
In [27]:
import pandas as pd
แปลงข้อมูลเป็น DataFrame
สำหรับข้อมูลที่ต้องใช้สำหรับการบันทึกออกไปเป็น Excel จะต้องเตรียมข้อมูลให้อยู่ในรูปแบบของ DataFrame เสียก่อน ซึ่งข้อมูลที่เราจัดเก็บมาในรูปแบบของ List ของ Dictionary ส่วนนี้ สามารถแปลงเป็น DataFrame ได้ผ่านคำสั่ง .DataFrame() ที่รับ argument เป็นข้อมูล List ของ Dictionary ที่เก็บข้อมูลของแต่ละรายการเอาไว้ได้เลย ซึ่งจะได้ผลลัพธ์เป็นข้อมูลที่อยู่ใน DataFrame Object ซึ่งสามารถแปลงเป็น Excel ได้ในภายหลัง
In [28]:
data_df = pd.DataFrame(data_list)
data_df
Out [28]:
บันทึกข้อมูลลง Excel
สำหรับการบันทึกข้อมูลในตาราง DataFrame ลง Excel เราจะมีประเด็นที่สำคัญที่สุดคือการสร้างที่อยู่สำหรับการบันทึกไฟล์ โดยเราจะทำการสร้าง String Object ที่เก็บที่อยู่ไฟล์โดยสำหรับที่อยู่ไฟล์ของ Window OS จะมีการใช้สัญลักษณ์ \ ซึ่งจะมีปัญหาต่อการใช้งาน ซึ่งจะต้องทำการแปลง String Object ที่เก็บที่อยู่เป็น Raw String ผ่านการเติม r'' ไว้ด้านหน้า String อีกประเด็นสำคัญที่ต้องเช็คคือ ที่อยู่ของไฟล์ Excel ที่ต้องการบันทึกจะต้องเป็นที่อยู่ของไฟล์ Excel ไม่ใช่ ที่อยู่ของโฟลเดอร์ที่เก็บไฟล์ Excel ที่ต้องการ โดยเราจะกำหดนชื่อไฟล์ Excel ที่ต้องการบันทึกลงไปในที่อยู่ที่กำหนด และใส่นามสกุลไฟล์ .xlsx ซึ่งเป็นนามสกุลของ Excel
In [29]:
file_location = r'C:\Users\acer\Desktop\youtube\00 web scraping\00 material\Condo.xlsx'
เมื่อเตรียมที่อยู่เรียบร้อย เราจะบันทึก DataFrame ลงไปใน Excel ด้วยคำสั่ง .to_excel() และใส่ที่อยู่ที่เป็น Raw String ลงเป็น argument
In [30]:
data_df.to_excel(file_location)
เมื่อรันคำสั่งบันทึกลง Excel จะมีการสร้างไฟล์ Excel ตามชื่อ และที่อยู่ที่กำหนดไว้ สามารถนำข้อมูลไปใช้งานต่อผ่าน Excel หรือใช้ Python จัดการต่อ ก็สามารถทำตามต้องการได้เลย!
หลักการทำงานกับเวปอื่น
สำหรับการปรับใช้งานกับเวปอื่นที่สนใจ สามารถใช้หลักการค้นหา 1 รายการข้อมูล และสกัดข้อมูลที่ต้องการได้ลักษณะเดียวกัน โดยใช้การเปลี่ยนลิ้งค์เป็นลิ้งค์ที่สนใจ, เปลี่ยนรายละเอียดของ 1 รายการ และเปลี่ยน หรือเพิ่มเติมรายละเอียดของ Tag ที่เก็บข้อมูลส่วนต่างๆ เพื่อสกัด และบันทึกข้อมูลลง Excel ได้ตามโครงสร้างของเวปได้เลย!
ช่วยเราสร้างบทความที่ดีขึ้น
ผ่านการให้ข้อมูล และฟีดแบคเกี่ยวกับบทความนี้!
ผู้สอนของคุณในบทเรียนนี้
สวัสดีครับผมซิปป้า แอดมินของเพจ Ultimate Python ครับ นอกจาก Content ดีๆ แบบนี้ ผมทำธุรกิจทางด้านการจัดเทรนนิ่งให้กับองค์กร, เป็นที่ปรึกษาสำหรับบริษัท SME ที่ต้องการสร้างระบบข้อมูล และการทำ Automation หากมีท่านใดที่มีเพื่อน หรือกำลังต้องการบริการเหล่านี้ สามารถแนะนำผมได้เลยนะครับ
นอกจากนี้ผมยังมีแพ็คเก็จ CDB | Citizen Developer Bootcamp ที่ผมจะนำความรู้ทั้งหมดที่ทุกท่านสนใจ ที่ออกเป็นคอนเทนต์ต่างๆ สร้างเป็นคอร์สเรียนให้ทุกท่านได้เรียน ได้ลองทำ และมีผลงานจริง ที่สมัครครั้งเดียวรับอัพเทคอร์สได้ตลอดอายุคอร์ส
หากต้องการติดต่อผม เพื่อจัดอบรม ปรึกษาการทำโปรเจคขององค์กร
สามารถโทร 09-626262-40 (ติดต่อคุณแพรว) ได้เลยนะครับ
Comments