Web Scraping เจาะลึกการดึงข้อมูลจากเว็บไซต์ด้วย Python

Web Scraping with Selenium and BeautifulSoup

nattakit pinyorattanakit
5 min readJul 26, 2023
Photo by Lee Campbell on Unsplash

Introduction
Web Scraping เป็นกระบวนการที่ใช้ในการดึงข้อมูลจากเว็บไซต์โดยอัตโนมัติ เพื่อนำไปใช้ในการวิเคราะห์ข้อมูลหรืองานอื่น ๆ ที่มีประโยชน์ในด้านต่าง ๆ วิธีนี้เป็นที่นิยมในการเก็บข้อมูลขนาดใหญ่เพื่อใช้ในงานทางธุรกิจ การวิจัย หรือการตลาด

โดยเราจะใช้ Selenium & BeautifulSoup ที่เป็นไลบรารีที่สามารถใช้งานร่วมกันเพื่อทำ Web Scraping ที่มีความซับซ้อน โดยสามารถใช้ Selenium เพื่อควบคุมเบราว์เซอร์ในการนำเสนอหน้าเว็บและดำเนินการต่างๆ เช่น การส่งคำสั่งให้ คลิก พิมพ์ เลื่อนเมาส์ ซูมเข้า ซูมออก อันนี้คือจะสั่งด้วย Selenium

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

ในบทความนี้ผมจะสร้างบอทดึงข้อมูลจากเว็บไซต์ของ Shopee Thailand ซึ่งเป็นหน้าหลักของ Shopee ที่ให้บริการซื้อขายออนไลน์กันแบบเรียลไทม์

ทุกท่านสามารถทำตามไปพร้อมๆ กันได้เลยครับ :)

ในครั้งนี้เราจะทำงานบน Jupyter notebook เนื่องจากเวลาเราทำงานกับตัวโปรแกรมที่เราโหลดมามันต้องทำงานคู่กับโปรแกรมที่อยู่บนเครื่อง ดังนั้นเราจะใช้ตัวโปรแกรมที่ลงบนเครื่องเลยจะง่ายกว่า

let’s get started

step 1: เช็คเวอร์ชันของ Google Chrome

ไปที่ https://chromedriver.chromium.org/downloads เพื่อโหลด chromedriver ให้ตรงกับเวอร์ชั่นของเครื่องที่เราใช้งาน

(ในที่นี้ผมเลือกเป็น win32.zip) และหลังจากนั้นแตกไฟล์ Zip ไปที่ folder ที่เราสร้าง
ภาพหลังจากแตกไฟล์เรียบร้อย

step 2: สร้าง folder บน Jupyter notebook เพื่อเก็บงานเอาไว้กด New -> Python3 เพื่อเริ่มการทำงานใน folder (ในที่นี้ผมสร้าง folder บน Dasktop และตั้งชื่อว่าดึงข้อมูล)

step 3: ติดตั้งโมดูล selenium และ import library ที่จะใช้งาน

!pip install selenium

from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager

หลังจากนั้นใช้คำสั่งนี้ เพื่อสร้างอินสแตนซ์เบราว์เซอร์ ซึ่งจะเป็นการเริ่มต้นใช้งานเบราว์เซอร์ Google Chrome

driver = webdriver.Chrome()
ผลลัพธ์ที่ได้

เมื่อมีเราได้ Google Chrome (driver) ที่สร้างขึ้นแล้ว ก็สามารถใช้งาน Selenium WebDriver เพื่อควบคุมเบราว์เซอร์ คลิกปุ่ม กรอกข้อมูล หรือตรวจสอบสิ่งต่างๆ บนหน้าเว็บได้

step 4: เปิดหน้าเว็บไซต์ของ Shopee

driver.get('https://shopee.co.th/')
ผลลัพธ์ที่ได้

หลังจากที่เราเข้าหน้าเว็บของ shopee ได้แล้ว ตามปกติเวลาคนที่เข้าหน้าเว็บมาแล้วจะต้องทำอยู่สองอย่างก็คือ 1. กดปิดเพื่อเพื่อเข้าไปเลือกสินค้า 2. กดเลือกภาษาที่จะใช้งานแล้วไปเลือกซื้อสินค้า ในกรณีนี้เราจะใช้คำสั่งให้บอทกดไปที่ เลือกภาษา:ไทย

step 5: ใช้ XPath เพื่อค้นหา Element ที่เราต้องการ
เราต้องเข้าใจก่อนว่าหน้าตาเว็บที่เราเห็นนั้น กับหน้าตาเว็บที่คอมพิวเตอร์รู้นั้นต่างกัน
เราอาจจะเห็นว่าหน้าเว็บ shopee มีหน้าตาที่สวยงามดูใช้งานง่าย แต่สิ่งที่คอมพิวเตอร์เห็นนั้นจะเต็มไปด้วย code ต่างๆ ประกอบด้วย html, css และแท็กต่าง ๆเป็นต้น

กด F12 -> คลิกลูกศรซ้ายบนของแทบดังรูปเพื่อดู Elements ที่อยู่ในนั้น

เมื่อคลิกแล้วเราจะเห็นว่าเมื่อเอาเมาส์ไปวางตรงไหนก็จะขึ้น เงาสีฟ้าๆออกมาแสดงให้เห็นว่าแท็กของ code อยู่ที่จุดไหน และคลิกไปที่ตำแหน่งนั้นเพื่อ copy XPath

จะเห็นว่ามีเงาสีฟ้าอยู่ที่ตำแหน่งนี้ จากนั้นคลิกขวาแล้วเลือก Copy fullXpath

เมื่อเราได้ copy XPath มาแล้ว /html/body/div[2]/div[1]/div[1]/div/div[3]/div[1]/button คือ XPath ที่ใช้ในการระบุตำแหน่งของภาษาไทยบนหน้าเว็บไซต์ จากนั้นเราจะเก็บไว้ในตัวแปร
thai_button

# ใช้ XPath เพื่อค้นหา Element ที่เราต้องการ
from selenium.webdriver.common.by import By
thai_button = driver.find_element(By.XPATH, '/html/body/div[2]/div[1]/div[1]/div/div[3]/div[1]/button')

หลังจากเราเลือกตำแหน่งเสร็จแล้ว ต่อไปจะเป็นการคลิกปุ่มเพื่อกดยืนยันครับ

# ทำการแสดงผล (เช่นคลิกปุ่ม)
thai_button.click()
พลลัพธ์ที่ได้

จะเห็นว่าหน้าต่างที่เลือกภาษาหายไปแล้วเนื่องจากเราใช้คำสั่งคลิกเลือกไปแล้วนั่นเอง !!

ต่อมาเราจะทำวิธีการเดิม โดยให้บอทกดปิดตรงเครื่องหมายกากบาท
กด F12 -> คลิกลูกศรซ้ายบนของแทบดังรูปเพื่อดู Elements ที่อยู่ในนั้น

เราก็จะเห็น Elements ที่ต้องการแล้ว(ลูกศรสีน้ำเงิน) แต่ว่าความสนุกในครั้งนี้คือ เรายังไม่สามารถ copy XPath ได้แบบตรงๆ เพราะว่ามี shadow-root(ตรงลูกศรสีแดง) เนื่องจาก shopee เป็นเว็บที่มีการซ่อนตัวของ code เอาไว้ ตรง shadow-root คือเราไม่สามารถเอาตำแหน่งมาใส่ xpath แบบธรรมดาได้ จำเป็นต่องใช้คำสั่งพิเศษเอา

หลักการก็คือ ถ้าหากเราต้องการจะเข้าไปดึงข้อมูลที่ซ่อนอยู่ (shadow-root) เราต้องเลือก folder ใหญ่ ที่เก็บข้อมูลที่ถูกซ่อนเอาไว้ จากนั้นเราค่อยเขียนคำสั่งหาว่าใน folder นี้มีคำสั่งที่ถูกซ่อนหรือป่าว ซึ่งเป็นคำสั่งพิเศษ

step 6: ใช้ python เพื่อเรียก JavaScript มาทำงานกับหน้าเว็บ
copy ในส่วนของแท็กที่เก็บตัวที่ถูกซ่อนเอาไว้(ลูกศรสีแดง) ที่ข้างในมีสิ่งที่เราต้องการ

driver.execute_script('return document.querySelector("shopee-banner-popup-stateful")')

เป็นคำสั่งที่ใช้ JavaScript เข้าไปหาสิ่งที่เราระบุและดึงออกมาให้เรา

ต่อไปใช้คำสั่งเพื่อหาว่าใน shadow-root นี้มีข้อมูลที่ถูกซ่อนไว้ไหม
ถ้ามี ให้เลือก querySelector และใส่ข้อมูลที่อยู่ใน shadow-root เข้ามาโดยใส่ชื่อ div. และตามด้วยค่า valuse ของ attribute ดังนี้

driver.execute_script('return document.querySelector("shopee-banner-popup-stateful").shadowRoot.querySelector("div.shopee-popup__close-btn")')

เราก็จะได้ข้อมูลออกมาและนำไปใส่ไว้ในตัวแปร close_button เพื่อ click ปิดหน้าต่าง

close_button = driver.execute_script('return document.querySelector("shopee-banner-popup-stateful").shadowRoot.querySelector("div.shopee-popup__close-btn")')
close_button.click()
ผลลัพธ์ที่ได้ ปิดตัวป๊อปอัพเรียบร้อย :)

จากนั้นเราจะกำหนดคำสั่งไปที่แทบค้นหาตามสัญชาตญาณของคน เมื่อเข้าใช้งานในเว็บ ทำตามขั้นตอนเดิม
กด F12 -> คลิกลูกศรซ้ายบนของแทบดังรูปเพื่อดู Elements ที่อยู่ในนั้น
เมื่อคลิกแล้วเราจะเห็นว่าเมื่อเอาเมาส์ไปวางตรงไหนก็จะขึ้น เงาสีฟ้าๆออกมาแสดงให้เห็นว่าแท็กของ code อยู่ที่จุดไหนและคลิกไปที่ตำแหน่งนั้นเพื่อ copy XPath
และเขียนคำสั่งดังนี้

search = driver.find_element(By.XPATH, '/html/body/div[1]/div/header/div[2]/div/div[1]/div[1]/div/form/input')

step 7: ใช้คำสั่ง Keys
ต่อมาเราจะพิมพ์คีย์เวิร์ดที่เราต้องการหาลงไป ในตอนนี้ผมจะหาคำว่ารองเท้า
โดยใช้คำสั่ง

search.send_keys('รองเท้า')
ผลลัพธ์ที่ได้

หลังจากที่เราพิมพ์ข้อความเสร็จ เราก็ต้องกด Enter เราจำเป็นที่จะต้องใช้คำสั่ง Keys

from selenium.webdriver.common.keys import Keys

search.send_keys(Keys.ENTER)

มันก็จะกด Enter ตามคีย์เวิร์ดที่เราต้องการ

ผลลัพธ์ที่ได้

เมื่อบอทค้นหาเสร็จเรียบร้อยเราก็ต้องการเก็บข้อมูลจากหน้าเว็บ
ก่อนอื่นต้องทำความเข้าใจกับหน้าเว็บก่อนว่ามันทำงานอย่างไรอย่าง
เพราะการเก็บข้อมูลจาก shopee นั้นไม่ง่าย เนื่องจากข้อมูลบางส่วนที่แสดงให้เราเห็นนั้นยังโหลดมาไม่ครบ เราจะมองไม่เห็นข้อมูลบางส่วนเพราะมันจะแสดงข้อมูลแต่ที่เราเห็นเท่านั้น ที่ไม่เห็นบนหน้าเว็บมันจะไม่โหลดให้เช่นนี้

เมื่อเลื่อนดูสินค้าจะไม่เห็นข้อมูลบางส่วน เนื่องจากระบบจะแสดงให้เห็นเฉพาะข้อมูลที่บนหน้าจอจับได้

step 8: ใช้คำสั่ง JavaScript เช่นเคยในการซูมออกเพื่อโหลดข้อมูล
ในกรณีนี้เราจะทำการ ซูมออกเพื่อให้เห็นทุกข้อมูล พอเราเห็นทุกข้อมูลก็จะโหลดได้ทุกข้อมูล พอเราโหลดได้ทุกข้อมูล เราก็จะเก็บได้ทุกข้อมูล

# เราจะใช้คำสั่ง JavaScript เช่นเคยในการซูมออก
driver.execute_script("document.body.style.zoom='10%'")
ผลลัพธ์ที่ได้ ข้อมูลมาครบแล้ว!!

step 9: ดึง html ของ browser
ใช้คำสั่งที่ดึง html ของ browser ที่เปิดอยู่ออกมา และเก็บไว้ในตัวแปร data

data = driver.page_source

step 10: ติดตั้ง BeautifulSoup เพื่อเลือกข้อมูลออกมาในรูปแบบที่เราต้อง

!pip install bs4
import bs4

# ใส่เข้าไปในตัวแปร soup และแสดงออกมา
soup = bs4.BeautifulSoup(data)
soup

# output ที่ได้จะเป็นข้อมูลของ ภาษา html ที่อยู่บนเว็บไซต์

หลังจากที่เราโหลดข้อมูลมาแล้ว ก็จะซูมกลับเข้าให้สามารถระบุข้อมูลต่างๆ ได้

driver.execute_script("document.body.style.zoom='100%'")

ใช้คำสั่งนี้เพื่อดึงข้อมูลออกมา

soup.find_all()

หลังจากนั้นเราจะเข้าไประบุข้อมูลในตัวสินค้าเช่น title ชื่อสินค้า

การทำงานของ BeautifulSoup
BeautifulSoup เราจะไม่ใช้การคลิกขวาและ cope Xpath เหมือนกับ selenium
แต่จะระบุรายละเอียดของแท็กที่เราต้องการ

อธิบายก่อนว่า โครงสร้างข้อมูลของเว็บไซต์นั้นประกอบด้วยอะไรบ้าง…

  • HTML : เป็นภาษาที่ใช้สร้างโครงสร้างของหน้าเว็บโดยใช้ตัวอักษรและแท็กตัวอย่างเช่นแท็ก <header> สำหรับส่วนหัวของหน้าเว็บ, แท็ก <p> สำหรับเนื้อหาข้อความ, และแท็ก <img> สำหรับแสดงรูปภาพบนหน้าเว็บ
  • CSS : เป็นภาษาที่ใช้สำหรับตกแต่งหน้าเว็บที่ถูกสร้างด้วย HTML เพื่อให้หน้าเว็บดูสวยงาม มีการจัดหน้า, สี, รูปแบบตัวอักษร, การเรียงลำดับ, และความสามารถในการปรับขนาด (responsive) เพื่อให้หน้าเว็บสามารถปรับตามขนาดหน้าจอของอุปกรณ์ที่ใช้ในการเข้าชม การใช้ CSS ทำให้เว็บไซต์มีความสวยงามและมีรูปแบบที่น่าสนใจมากยิ่งขึ้น
  • JS : เป็นภาษาสคริปต์ที่ใช้สำหรับเพิ่มความสามารถแบบโต้ตอบให้กับหน้าเว็บ HTML อย่างไดนามิก (dynamic) ซึ่งสามารถปรับปรุงและเปลี่ยนแปลงเนื้อหาบนหน้าเว็บได้โดยไม่ต้องโหลดหน้าเว็บใหม่ นอกจากนี้ยังสามารถใช้ JavaScript ในการทำฟอร์ม, ตรวจสอบข้อมูลทางเนื้อหา, การแสดงข้อความแจ้งเตือน, การแลกเปลี่ยนข้อมูลกับเว็บเซิร์ฟเวอร์, และอื่นๆ ที่เพิ่มความสามารถและประสิทธิภาพให้กับเว็บไซต์
  • Image : รูปภาพเป็นองค์ประกอบที่สำคัญในการตกแต่งหน้าเว็บ ซึ่งใช้สำหรับแสดงภาพหรือกราฟิกที่ต้องการเสริมสวยงามหรือสื่อความหมายในเนื้อหา รูปภาพสามารถเป็นในรูปแบบต่างๆ เช่น JPG และ PNG ซึ่งรองรับการแสดงผลบนเว็บไซต์ได้แบบเต็มหน้าจอหรือเล็กลงตามความเหมาะสม

ในภาษา css จะใช้จัดหน้าตาของเว็บ เราก็จะเห็นว่าถ้าหน้าตาของเว็บคล้ายๆกัน ตรงไหนที่มีตำแหน่งที่คล้ายๆกัน ก็จะรู้ได้ว่าใช้ภาษา css ซึ่งภาษา css จะใช้คำสั่ง class ในการจัดข้อมูล จากนั้นเราก็หาชื่อ class =’’ที่มีชื่อเหมือนๆ กันโดยการกด Ctrl+c และ Ctrl+f เพื่อหาคำที่เหมือนกันเราก็จะรู้ว่า class นั้นอยู่ในตำแหน่งไหนบ้าง

ในกรณีนี้ผมจะเลือกดึงชื่อสินค้าออกมา
กด F12 -> คลิกลูกศรซ้ายบนของแทบดังรูปเพื่อดู Elements ที่อยู่ในนั้น
และกด Ctrl+c และ Ctrl+f เพื่อหาคำที่เหมือนกันเราก็จะรู้ว่า class นั้นอยู่ในตำแหน่งไหนบ้าง และดับเบิ้ลคลิกตรง class เพื่อ copy ออกมาดังนี้

เมื่อ Ctrl+c และ Ctrl+f ก็จะพบว่ามี class ที่เหมือนกัน 60 class
soup.find_all('div', class_='ie3A+n bM+7UW Cve6sh')
# เราก็จะได้ข้อมูลที่เป็นชื่อสินค้าทั้งหมดออกมา

เช็คข้อมูลที่เราดึงมาว่าได้ข้อมูลมาครบหรือป่าวตัวคำสั่ง

len(soup.find_all('div', class_='ie3A+n bM+7UW Cve6sh'))
# output = 60 เนื่องจากข้อมูลใน page 1 ของหมวดรองเท้ามี 60 สินค้า

step 11: แปลงข้อมูลในอยู่ในรูปแบบ google sheet
หลังจากได้ข้อมูลที่เป็นชื่อสินค้าครบแล้ว เราก็ต้องแปลงข้อมูลในอยู่ในรูปแบบ ตาราง, google sheet ด้วยวิธีนี้

all_product = soup.find_all('div', class_='ie3A+n bM+7UW Cve6sh')

all_product_list = []
for product in all_product:
all_product_list.append(product.text)
all_product_list

# output แสดงชื่อของสินค้าออกมา

ต่อไปหาราคาของสินค้า ก็ทำเช่นเดิมคือ หาชื่อ class =’’ที่มีชื่อเหมือนๆ กันโดยการกด Ctrl+c และ Ctrl+f เพื่อหาคำเหมือนกันเราก็จะรู้ว่า class นั้นอยู่ในตำแหน่งไหนบ้าง และก็อปส่วนของ class มาวางตามตัวอย่าง

all_price = soup.find_all('div', class_='vioxXd rVLWG6')

all_price_list = []
for price in all_price:
all_price_list.append(price.text)
all_price_list

# output แสดงราคาของสินค้าออกมา

ต่อไปดึงข้อมูลของสินค้า ก็ทำเช่นเดิมคือ หาชื่อ class =’’ที่มีชื่อเหมือนๆ กันโดยการกด Ctrl+c และ Ctrl+f เพื่อหาคำเหมือนกันเราก็จะรู้ว่า class นั้นอยู่ในตำแหน่งไหนบ้าง และก็อปส่วนของ class มาวางตามตัวอย่าง

all_sales = soup.find_all('div', class_='ZnrnMl')

all_sales_list = []
for sales in all_sales:
all_sales_list.append(sales.text)
all_sales_list

# output แสดงจำนวนของสินค้าที่ขายได้ออกมา

ต่อไปดึงข้อมูลจังหวัดของร้านค้า ก็ทำเช่นเดิมคือ หาชื่อ class =’’ที่มีชื่อเหมือนๆ กันโดยการกด Ctrl+c และ Ctrl+f เพื่อหาคำเหมือนกันเราก็จะรู้ว่า class นั้นอยู่ในตำแหน่งไหนบ้าง และก็อปส่วนของ class มาวางตามตัวอย่าง

all_province = soup.find_all('div', class_='zGGwiV')

all_province_list = []
for province in all_province:
all_province_list.append(province.text)
all_province_list

# output แสดงจังหวัดของร้านค้าออกมา

step 11: แปลงข้อมูลทั้ง 4 ส่วนเข้าด้วยกันเพื่อโหลดไปยัง (Excel)

เอาข้อมูลที่เก็บไว้ใน all_product_list , all_price_list, all_sales_list , all_province_list เข้ามาอยู่ใน DataFrame เดียวกัน

import pandas as pd

shopee_data = pd.DataFrame([all_product_list , all_price_list, all_sales_list , all_province_list])

ใช้.transpose() เพื่อให้ข้อมูลดูได้ง่ายขึ้นเพราะเป็นแนวตั้ง

shopee_data.transpose()

เปลี่ยนชื่อคอลัมน์

shopee_data_new = shopee_data.transpose()
shopee_data_new.columns = ['Title', 'Price', 'Amount', 'Province']
shopee_data_new

หลังจากที่เราได้ตารางเรียบร้องแล้ว ขั้นตอนสุดท้าย save เป็น Excel ได้เลยครับ

shopee_data_new.to_excel(r'C:\Users\asus\Desktop\ดึงข้อมูล\shopee_รองเท้า.xlsx')

ไฟล์ Excel เข้ามาใน folder ที่เราต้องการเรียบร้อยครับ :)

ในบทความถัดไปผมจะสอนการ clean data เพื่อนำข้อมูลไปใช้จริงๆ เนื่องจากข้อมูลที่เราได้มายังเป็น raw data (ข้อมูลดิบ) อยู่

ขอบคุณทุกคนที่อ่านมาถึงตรงนี้ครับ See you agian
เนื้อหาในบทความมีความผิดพลาดประการใดขออภัยมา ณ ที่นี้ด้วยครับ

Ref : Ultimate Python

--

--

nattakit pinyorattanakit

AI Engineering and data science ———————————————————————— https://misternattakit.com