ดึงข้อมูลจากเว็บไซต์ IMDb ด้วย R

Web Scraping คือการดึงข้อมูลที่เราต้องการจากเว็บไซต์บนอินเตอร์เน็ต (fetch & extract) ซึ่งเป็นอีกหนึ่ง skill ที่พวกเรา data analyst ควรฝึกไว้ เพราะ free dataset ที่ใหญ่ที่สุดในโลกมีพร้อมให้เราใช้งานบนอินเตอร์เน็ต ส่วนใหญ่อยู่ในรูปแบบของ text/ natural language บนเว็บไซต์อย่าง wikipedia, encyclopedia, imdb เป็นต้น

tutorial วันนี้เราจะสอนเขียน R ง่ายๆ เพื่อทำ web scraping ดึงข้อมูลจากเว็บไซต์ online database – ภาพยนต์ ซีรี่ รายการทีวีที่ใหญ่ที่สุดในโลก – เรียกสั้นๆว่า IMDb โดย package หลักที่เราใช้คือ rvest ของ Hadley Wickham ลองอ่านบทความแนะนำของการใช้งานเบื้องต้นได้ที่นี่

Getting Started

Wickham แนะนำให้เราใช้ Google Chrome ในการตรวจสอบ html/ css ของหน้าเว็บที่เราต้องการ ด้วยการติดตั้ง Extension เสริมที่ชื่อว่า SelectorGadget กดที่ลิ้งนี้เพื่อ install (ฟรี)

พอติดตั้งเสร็จแล้ว จะมีไอคอน SelectorGadget ตามรูปด้านบน โผล่ขึ้นมาบน Google Chrome (ด้านขวาบนของหน้าจอ ใกล้ๆปุ่ม option) เดี๋ยวเราจะใช้ปุ่มนี้เยอะมาก ในการเลือก content ที่เราต้องการจากหน้าเว็บไซต์ต่างๆ

Top 50 Movies

โจทย์ของเราวันนี้คือดึงรายชื่อหนังที่ได้ rating สูงที่สุด 50 เรื่องแรกบน IMDb รวมถึงปีที่เข้าฉาย และคะแนน rating เฉลี่ย จาก website นี้

หน้าเว็บไซต์ IMDb ที่เราต้องการ scrape

เปิดโปรแกรม RStudio ขึ้นมา ติดตั้ง package rvest และดึงข้อมูลจากเว็บไซต์ไปเก็บไว้ใน object imdb ด้วยฟังชั่น read_html()

# install package
install.packages("rvest")
library(rvest)
# website url
url <- "https://www.imdb.com/search/title?genres=drama&groups=top_250&sort=user_rating,desc"
# fetching information (parse html page)
imdb <- read_html(url)
view raw .r hosted with ❤ by GitHub

Pick The Elements

ถัดมาเป็นขั้นตอนที่สำคัญมาก! คลิกที่ไอคอน SelecterGadget แล้วเอาเม้าส์ไปคลิก element ที่เราต้องการบนเว็บไซต์ เช่น ชื่อเรื่อง The Shawshank Redemption

วิธีการใช้งาน SelectorGadget คือใช้เม้าส์คลิกหนึ่งครั้งที่ element ที่เราต้องการจะ extract จากหน้าเว็บนั้นๆ จุดที่เราคลิกจะเป็นสีเขียว / สีเหลืองคือ element อื่นๆที่เหมือนกับสีเขียวที่เราต้องการดึงออกมาพร้อมกัน / สีแดงคือ element ที่เราไม่ต้องการ

ลองดูตัวอย่างสีในรูปด้านล่าง เราใช้ SelectorGadget เลือกเฉพาะชื่อหนังในหน้าเว็บนี้ (มีทั้งหมด 50 เรื่องใน page นี้)

พอเราเลือก element ที่เราต้องการได้แล้ว สังเกตที่ box ด้านล่างขวาของ Google Chrome จะมี text ขึ้นมาว่า .lister-item-header a ให้เรา copy text นี้ แล้วกลับไปที่ RStudio พิมพ์โค้ดตามนี้ แล้วกดรัน ก็จะได้รายชื่อหนังทั้ง 50 เรื่องออกมา ง่ายอะไรเบอร์นี้ !!

# use SelectorGadget to select element we want from the page
imdb %>%
html_nodes(".lister-item-header a") %>%
html_text()
view raw .r hosted with ❤ by GitHub

ฟังชั่น html_nodes() กับ html_text() ใช้ในการเลือก element ที่เราต้องการ และเปลี่ยนให้กลายเป็น text/ character ให้เราจัดการง่ายๆ

ตอนนี้เราดึงรายชื่อหนังทั้ง 50 เรื่องออกมาได้แล้ว

Released Year & Rating

ลองใช้ SelectorGadget ดึงข้อมูลปีที่หนังเรื่องนั้นๆเข้าฉาย และคะแนน rating บ้าง แล้วก็ copy text ที่ได้ไปใส่ฟังชั่น html_nodes() เหมือนเดิม ลองดูตัวอย่างโค้ดด้านล่าง

ใช้ SelectorGadget เลือกปีที่หนังเข้าฉาย
# select year
imdb %>%
html_nodes(".text-muted.unbold") %>%
html_text()
# select rating
imdb %>%
html_nodes(".ratings-imdb-rating strong") %>%
html_text()
view raw .r hosted with ❤ by GitHub

กดรันโค้ดจะได้ output ด้านล่างเป็นอันเสร็จเรียบร้อย ปล. สังเกตว่า output ที่ได้จะออกมาเป็น text/ character ทั้งหมดเลย (อยู่ในเครื่องหมาย “_”) เพราะเราใช้ฟังชั่น html_text() อ่ะเนอะ

ดึงปีที่เข้าฉาย และคะแนน rating ของหนังทั้ง 50 เรื่อง

Create DataFrame

เราสามารถเขียนโค้ดเพื่อดึงข้อมูลจาก IMDb (หรือเว็บไซต์อื่นๆ) แล้วสร้างเป็น dataframe / csv file ง่ายๆ ด้วยโค้ดนี้

# select movie name
imdb %>%
html_nodes(".lister-item-header a") %>%
html_text() -> movie_names
# select year
imdb %>%
html_nodes(".text-muted.unbold") %>%
html_text() %>%
# extract numeric year
stringr::str_extract('[0-9]+') %>%
as.integer() -> years
# select rating
imdb %>%
html_nodes(".ratings-imdb-rating strong") %>%
html_text() %>%
as.numeric() -> ratings
# create dataframe
imdb_data <- data.frame(movie_names, years, ratings)
# export csv file
write.csv(imdb_data, "imdb_data.csv")
view raw .r hosted with ❤ by GitHub

หน้าตาของ data frame ที่ได้จากโค้ดนี้

Good Summary

จบแล้วกับ tutorial วันนี้ สรุปขั้นตอนการดึงข้อมูลจากเว็บไซต์ต่างๆด้วย rvest

  • ดึงข้อมูล html จากเว็บไซต์นั้นมาก่อนด้วย read_html()
  • ใช้ SelectorGadget เลือก element ที่เราต้องการ extract
  • copy text ที่ได้ไปใส่ฟังชั่น html_nodes() และดึงออกมาด้วย html_text()
  • ใช้เทคนิคการ clean data อื่นๆใน R เพื่อปรับหน้าตาข้อมูลให้อยู่ในแบบที่เราต้องการ เช่น ดึงเฉพาะตัวเลขออกมาจากวงเล็บ อย่างที่เราทำในตัวอย่างวันนี้

ถ้าอยากจะทำ web scraping เก่งๆ ด้วยความที่ข้อมูลส่วนใหญ่บนอินเตอร์เน็ตจะเป็นแบบ text based ซะเยอะ ความรู้เรื่อง regular expression จะมีประโยชน์มาก อีกอย่างที่เราควรรู้คือเรื่อง html และ css ที่ developer ใช้ในการเขียนเว็บ ลองศึกษาเพิ่มเติมได้ใน references ด้านล่าง 😛

Good References

4 thoughts on “ดึงข้อมูลจากเว็บไซต์ IMDb ด้วย R

  1. R_programming ที่สอนฟรี ทำอย่างไร จะสามารถเรียน EP7 เป็นต้นไปได้คะ

  2. พี่ทอย ช่วยอธิบายบรรทัดนี้หน่อยได้ไหมครับ
    # extract numeric year
    stringr::str_extract(‘[0-9]+’) %>%
    as.integer() -> years

    1. package stringr ใช้วิเคราะห์ข้อมูลพวก text ครับ [0-9]+ เรียกว่า regular expression ในตัวอย่างนี้แปลว่า จงดึงข้อมูลที่เป็นตัวเลข 0-9 ออกมาจาก text นั้นๆ (e.g. ปี)

      ลองเสิร์ชหาบทความ regular expression ในบล๊อกเราได้เลยครับ 🙂

Leave a Reply