# Web Scraping for beginner

## **Web Scraping ฉบับคนไม่รู้ด้านนี้เลยก็สามารถทำได้** by Botnoi student

ในบทความนี้ผมจะพูดถึงการทำ Web Scraping ซึ่งเป็นวิธีการดึงข้อมูลจาก web page ต่างๆ เพื่อนำไปใช้ประโยชน์ตามที่เราต้องการ โดยจะใช้ Library BeautifulSoup ใน Python ครับ

บทความที่ผมจะมาแชร์ในวันนี้เป็นบางส่วนใน Botnoi data science classroom เป็นคลาสที่เปิดสอนสำหรับคนที่สนใจด้าน Data Science ครับ ซึ่ง web scraping เกี่ยวข้องกับด้านงานด้าน data ได้อย่างไร และจำเป็นมากแค่ไหนที่จะต้องรู้ ?

ดังที่ทราบกันว่าแหล่งข้อมูล (Data source) ที่ใหญ่ที่สุดคือ internet นั้นเองแล้วเราจะเข้าถึงข้อมูลที่มีอยู่ในนั้นได้อย่างไรล่ะ ก็โดย web scraping นั้นไง ซึ่งจะทำการสกัดและดึงข้อมูลจากแหล่งข้อมูล (ในที่นี้คือเว็บไซต์) เพื่อนำข้อมูลออกมาใช้ ดังเช่นว่า data scientist สามาถสร้าง model เพื่อเทรนหุ้น จากการดึงข้อมูลข่าวจากเว็บข่าวทั่วไป หรือ data analyst ทำการดึงข้อมูลร้านอาหารที่เปิดใหม่ล่าสุดในเขตกรุงเทพและปริมณฑลใน Wongnai มาทำการวิเคราะห์เพื่อจะใช้ประโยชน์ในด้านธุรกิจเป็นการต่อไป ขึ้นอยู่กับว่าเราจะนำข้อมูลที่ได้มานั้นไปใช้อย่างไร ซึ่งการดึงข้อมูลนั้นไม่ยากเลยครับ เรามาลอง scrape website เพื่อดึงข้อมูลออกมาใช้กันในบทความนี้ครับSyncsort:&#x20;

![ETL (Extract, Transform and Load)](https://miro.medium.com/max/581/1*nuy29WAjBsVNv5Lloj1xVQ.jpeg)

ก่อนอื่นเรามาทำความเข้าใจกับคำว่า web scraping กันก่อน web scraping นั้นเป็นการดึงข้อมูลจากหน้าเว็บ (web page) โดยวิเคราะห์จากลักษณะของภาษา HTML (Hyper Text Markup Language) ที่ใช้ในการแสดงผลบนอินเตอร์เน็ตในลักษณะของข้อความ รูปภาพ ต่างๆ โดยการจะดึงข้อมูลออกมาขั้นต้น เราควรที่จะเข้าใจข้อมูลพื้นฐานของ web ก่อน เพื่อทำให้รู้ว่าถ้าจะเราสนใจข้อมูลตรงนี้ในเว็บ เราต้องดูตรงจุดไหน จะได้ดึงข้อมูลนั้นออกมาครบถ้วนและถูกต้องครับ

เรามาทำความเข้าใจภาษา HTML เบื้องต้นกันก่อนแบบไม่ต้องเขียนกันครับ

![ภาพตัวอย่างหน้า HTML Page](https://miro.medium.com/max/1800/1*9lncWQIguXf7yy7QTrwhHQ.png)

โดยแต่ละส่วนประกอบหลักๆ จะมีชื่อเรียกดังนี้

![](https://miro.medium.com/max/1418/1*cCph4eWbpf7RzCjncI7ylA.jpeg)

**Tag name** ใช้ในการระบุรูปแบบคำสั่ง หรือการลงรหัสคำสั่ง ภายในเครื่องหมาย less-than bracket ( < ) และ greater-than bracket ( > ) โดยที่ Tag HTML แบ่งได้ 2 ลักษณะ คือ

* **Tag เดี่ยว** เป็น Tag ที่ไม่ต้องมีการปิดรหัส เช่น \<meta>, \<link> เป็นต้น
* **Tag เปิด/ปิด** รูปแบบของ tag นี้จะเป็นแบบ \<title> …. \</title> โดยที่ \<title> เราเรียกว่า tag เปิด และ \</title> เราเรียกว่า tag ปิด

**ซึ่งเราจะใช้ tag เพื่อระบุตำแหน่งของข้อมูลที่ต้องการในการดึงข้อมูลออกมาครับ**

**Attribute** คือ เป็นตัวบอกรายละเอียดของ tag นั้นเช่น \<meta http-equiv=”Content type”> เป็นการบอกว่า meta นี้บรรจุ http อยู่ใน tag (http-equiv)

**Value** คือ ค่าของ Tag นั้น อย่างเช่น \<meta http-equiv=”Content type”> มี Value คือ “Content-Type”

**Nefted-element** คือ Tag ย่อยที่ถูกบรรจุอยู่ อย่างในภาพ Tag ใหญ่ คือ \<head>……\</head> โดยมี Nefted-element คือ \<meta> ,\<title>…\</title> และ \<link>

> ถ้าสงสัยตรงไหนสามารถศึกษาเพิ่มเติมได้จากลิงค์นี้เลยครับ [https://www.hellomyweb.com/course/html/structure\_of\_html/](https://www.hellomyweb.com/course/html/structure_of_html/)

**Web-scraping ethics**

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

โดยเราสามารถตรวจสอบข้อมูลที่เว็บนั้นสงวนไว้ ด้วยการเติม /robots.txt หลังที่อยู่เว็บไซต์ (address) นั้นเช่น [https://www.wongnai.com/robots.txt](https://www.wongnai.com/robots.txt)อย่างจากภาพเป็นเว็บไซต์ Wongnai จากในเว็บแสดงถึง เราห้าม (Disallow) ดึงข้อมูล Users ออกมา

![](https://miro.medium.com/max/626/1*dJBP0AaZAhul0-Yzib_5bQ.png)

![หรืออย่าง Lazada ได้ห้ามเราดึงข้อมูลหลายอย่าง เช่น cart (สินค้าในรถเข็น) หรือ shop microsoft](https://miro.medium.com/max/705/1*MiRzG6U_8MDEbxiIAyWVsA.png)

**Introduce Developer-Tools**

หลังจากได้ตรวจเช็คแล้วเรามาทำความรู้จักกับ d**ev-tools** กันครับ โดย d**ev-tools** สามารถทำให้เราดูว่ามีอะไรบ้างอยุ่ในเว็บนั้นและคัดกรองว่าจะนำอะไรมาใช้ได้บ้างและต้องทำอย่างไรถึงจะนำออกมาใช้ได้ โดยวิธีใช้เครื่องมือนี้ไม่จำเป็นต้องติดตั้งโปรแกรม เพราะมีอยู่ใน Browser ที่ทุกท่านใช้อยุ่แล้ว อย่างผมใช้ Opera หรือ Chrome สามารถทำได้โดยกด Ctrl + Shift + I หรือ กด F12 หรือ Right click แล้วเลือก Inspect หรือจะกดที่มุมซ้ายบนได้เลยครับ

![](https://miro.medium.com/max/1800/1*LOfXYlO2pq5bPObAdNBReg.png)

![หน้าตาของ Developer tool](https://miro.medium.com/max/1800/1*VHrFI7Kjx2N82hFKqzOwMg.png)

**How to select element in HTML document : CSS Selector**

เราจะมาเริ่มแตะ coding กันเลยนะครับ ภาษาที่เราจะใช้คือ Python โดยมี Library อยู่ที่เราใช้ในการ scrape web คือ BeautifulSoup , Selenium และ Scrapy ซึ่งจะมีข้อดีและข้อเสียที่แตกต่างกัน แต่ในบทความนี้ผมจะพูดถึงเฉพาะ BeautifulSoup เพราะค่อนข้างง่ายและเหมาะกับผู้เริ่มต้นครับ เรามาเริ่มต้น scraping ผ่าน library BeautifulSoup กันเลย

> Scrapy vs Selenium vs BeautifulSoup:
>
> [https://towardsdatascience.com/scrapy-vs-selenium-vs-beautiful-soup-for-web-scraping-24008b6c87b8](https://towardsdatascience.com/scrapy-vs-selenium-vs-beautiful-soup-for-web-scraping-24008b6c87b8)

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

```python
import bs4 ##ถ้ายังไม่มีก็สามารถลงได้โดย pip install bs4 
```

และเราก็ดึง Library request มาใช้ในการดึงเว็บที่เราสนใจ โดย requests จะใช้สำหรับการสร้างการเชื่อมต่อกับ HTTP หรือตัวหน้าเว็บเรานั้นเอง

```python
import requests ##มี s ลงท้ายด้วย 
## ถ้ายังไม่มีก็สามารถลงได้โดย pip install requests
```

ทีนี้เราก็สามารถดึงข้อมูลจากเว็บที่เราสนใจได้แล้ว โดยใช้ requests.get(‘web link’)

```python
r = requests.get(‘https://www.wongnai.com/restaurants/sushimasa’)
```

![หน้าเว็บไซต์ที่เราสนใจ (ยิ่งทำไปเรื่อยๆยิ่งหิวเลยครับ 5555)](https://miro.medium.com/max/1800/1*UbOyZAGF2kZ8aHpllNXuNg.png)

เรามาเช็คข้อมูลทั้งหมดที่มีอยู่ในหน้าเว็บนั้น

```python
r.text
```

![](https://miro.medium.com/max/1772/1*F2RWUihZpr6LPCFsnje5Iw.png)

นี่คือสิ่งที่เราได้จากการ request ซึ่งก็คือ Source code ของเว็บเพจนั้นแหละครับ แต่มันจะแสดงผลโดยการนำมาต่อกันทั้งหมดเลย ซึ่งจะทำให้ดูยากมากๆ แต่มีคำสั่งมาช่วยทำให้ดูง่ายขึ้น

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

```python
html_page = bs4.BeautifulSoup(r.text, ‘html.parser’)
print(html_page)
```

![](https://miro.medium.com/max/1799/1*FPp3BV8oxayE6mI3_zygpw.png)

```python
type(html_page)
```

![โดย type ของข้อมูลที่เราดึงมา จะเป็น bs4.BeautifulSoup](https://miro.medium.com/max/1242/1*YvqsmqrnSACQzAnspWbzjw.png)

โดยเราสามารถทำให้ source ดูได้ง่ายขึ้นไปอีกด้วย .prettify()

```python
print(html_page.prettify())
```

จะเห็นได้ว่า การใช้คำสั่ง prettify() ทำให้ Source code ที่เราได้มาจะถูกจัดการให้อยู่ในรูปแบบที่ดูง่ายขึ้นมากๆ ซึ่งจะอยู่ในรูปแบบที่คล้ายกับการกด F12 ดูใน web page เลยครับ

![](https://miro.medium.com/max/1800/1*qpuO9iYcMMDqi4fLif2nsQ.png)

เรามาเริ่มดึงข้อมูลกัน โดยจะใช้ CSS Selector ในการดึงข้อมูลออกมานะครับ

> _CSS Selector reference:_
>
> [https://www.w3schools.com/cssref/css\_selectors.as](https://www.w3schools.com/cssref/css_selectors.asp)

อย่างเช่นผมอยากจะดึง ประเภทราคาของร้านค้านี้ออกมา เราต้องเริ่มด้วยการไปดูก่อนว่าประเภทราคานั้นอยู่ส่วนไหนของเว็บนั้น และถูกบรรจุอยู่ในคลาสอะไร มาเริ่มกันเลยดีกว่าก่อนจะงง \*\***อย่าลืม ethics ด้วยนะครับ** อย่างใน Wongnai not allow เฉพาะ users ดังนั้นเราสามารถดึงข้อมูลในส่วนของประเภทราคาของร้านได้ครับ

ก่อนอื่นเลยเราต้องเข้า dev-tools ก่อนแล้วทำการเลือก (ด้วยการนำ cursor เมาส์ไปคลิ้กตรงส่วนที่เราสนใจในหน้าเว็บนั้นได้เลย) ซึ่ง dev-tools จะระบุที่อยู่ของ tag ที่บรรจุข้อมูลนั้นมาให้เลย![](https://miro.medium.com/max/317/1*5hh6D0zdlzdtm_A5DjmIXA.png)

![กลับไปที่ web browser ของเรา จากนั้นคลิกที่ select element (วงกลมสีแดง) แล้วคลิกตรงช่วงราคา (ข้อมูลที่เราสนใจ)](https://miro.medium.com/max/1868/1*Y9UstIjMyJTPVaoI44uEkg.jpeg)

ตรง span.sc-1ascgl-3.cbakhs คือ tag ของช่วงราคา ดังที่กล่าวไว้ข้างต้นว่า Tag name จะใช้ในการระบุรูปแบบคำสั่ง หรือการลงรหัสคำสั่ง โดยตรงนี้แหละครับที่จะใช้ css selectors ดึงออกมาเป็นข้อมูลที่เราต้องการ เรามา coding กันต่อครับ

```python
selector = 'span._2qDKIyMmA-jMRyfxACZWt6'
price = html_page.select_one(selector)
price
```



![ถ้า tag ที่เราได้มาเว้นด้วย spacebar เราจะแทนด้วย . ลงไปแทนนะครับ เช่น span. sc-1u6e7er-1 cvVMHV จะต้องใช้เป็น span. sc-1u6e7er-1.cvVMHV](https://miro.medium.com/max/1283/1*WaukGvmV3nnCZFNhO3BAfg.jpeg)

มาอีก fuction นึง .select\_one(selector) เป็นการระบุว่า tag span ใน class \_2qDKIyMmA-jMRyfxACZWt6 จะเลือกออกมากี่ตัว โดยจะมีอยู่ 2 แบบคือ เลือกตัวเดียว(ตัวแรกที่พบ) .select\_one() หรือจะดึงออกมาทุกตัวเลย .select()![](https://miro.medium.com/max/60/1*MUEt8EvNH32pXYx5WlynRg.png?q=20)จากการ select จะได้เป็นอะไรยืดยาว แต่เราพอได้ข้อมูลที่เราสนใจคร่าวๆแล้วนั่นคือ >฿\<! — →฿\<! — →฿<

![](https://miro.medium.com/max/1121/1*MUEt8EvNH32pXYx5WlynRg.png)

โดยใน BeautifulSoup นั้นได้มี function ที่จะสกัดข้อมูลที่เราต้องการได้ทันที

```python
price.text
```

![และ type ที่ได้จากการดึงข้อมูลออกมาจะเป็น bs4.element.Tag](https://miro.medium.com/max/1108/1*Jt9_FqHJyPrgAc8NtEmlVg.png)

![](https://miro.medium.com/max/1099/1*GleP6myo_iESVJkxgmwjLg.png)

แต่ถ้าเราใส่ข้อมูลผิดจะแสดงผลว่า None จากภาพด้านบนผมจงใจจะลบ 6 ใน class ออก พอมันหา ‘span.\_2qDKIyMmA-jMRyfxACZWt’ ในเว็บแต่หาไม่เจอในเว็บเพราะข้อมูลที่เราใส่ผิด ได้ผลที่ออกมาเป็น None

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

![](https://miro.medium.com/max/478/1*WCC5UHEvlEDqm6KlGJNyzg.png)

![tag ของภาพที่ผู้ใช้มารีวิว](https://miro.medium.com/max/1800/1*iE0XRpbccRnhQgzWllo8_w.png)

```
picture_selector = 'img.ogo0re-0.llQZZn.w0wgso-15.hgqWqI'
pic = html_page.select(picture_selector)
pic
```

![จากที่ดึงมาจะมี 9 ดังปรากฏในหน้าเว็บนั้นนะครับ](https://miro.medium.com/max/1342/1*eMvEW06bvp1hqEtpGpgMJA.png)

จากที่ดึงมาจะมี 9 img tag ดังปรากฏภาพ 9 ภาพในหน้าเว็บนั้น แล้วเราจะใช้เครื่องมือของ BeautifulSoup ในการสกัดเอาลิงค์ออกมานะครับ

```python
for image in pic:print(image[‘src’]) #src = source
```

![เรียบร้อยครับ ได้ลิงค์ของแต่ละภาพมาแล้ว](https://miro.medium.com/max/1298/1*qdcjmsJknqV6SATregfvrQ.png)

เป็นไงบ้างครับ พอจะทำตามกันได้ไหมครับ ซึ่งเจ้า Web-scraping ที่ได้เรียนจาก data science school by Botnoi จะอยู่ในขอบเขต data extraction เป็นการดึงข้อมูลหรือรวบรวมข้อมูลจากที่ต่างๆก่อนที่จะนำมาใช้ในการต่อไป ซึ่งการที่เราเข้าใจในด้านนี้ได้มากขึ้น จะช่วยทำให้เวลาเราดึงข้อมูลออกมาข้อมูลที่ได้จะมีความ clean มากขึ้นและตรงกับความต้องการมากขึ้นครับ หวังว่าทุกคนจะเข้าใจนะครับไว้ถ้ายังไงในบทความต่อไปผมได้ตั้งโปรเจ็คไว้กับ [Tamagotchi](https://medium.com/u/6d07e17204b8?source=post_page-----ba7febad3527----------------------) โดยจะดึงข้อมูลช่วงราคาและตำแหน่งที่ตั้งของร้านอาหารในเขตกรุงเทพและปริมณฑลเพื่อจะนำมา visualize หาความหนาแน่นของร้านในช่วงราคาต่างๆ ฝากติดตามกันด้วยนะครับ

ขอบคุณพี่ก็อต [Tamagotchi](https://medium.com/u/6d07e17204b8?source=post_page-----ba7febad3527----------------------) และพี่วิน [Dr. Winn Voravuthikunchai](https://medium.com/u/f9725b09d0e5?source=post_page-----ba7febad3527----------------------) สำหรับคำแนะนำด้วยครับ

Reference : [https://medium.com/botnoi-classroom](https://medium.com/botnoi-classroom/web-scraping-%E0%B8%89%E0%B8%9A%E0%B8%B1%E0%B8%9A%E0%B8%84%E0%B8%99%E0%B9%84%E0%B8%A1%E0%B9%88%E0%B8%A3%E0%B8%B9%E0%B9%89%E0%B8%94%E0%B9%89%E0%B8%B2%E0%B8%99%E0%B8%99%E0%B8%B5%E0%B9%89%E0%B9%80%E0%B8%A5%E0%B8%A2%E0%B8%81%E0%B9%87%E0%B8%AA%E0%B8%B2%E0%B8%A1%E0%B8%B2%E0%B8%A3%E0%B8%96%E0%B8%97%E0%B8%B3%E0%B9%84%E0%B8%94%E0%B9%89-by-botnoi-student-ba7febad3527)
