ทำ web scraping บน Python ด้วยไลบรารี่ Scrapy บน Google Colab
สวัสดีครับท่านผู้อ่านทุกคน วันนี้ผมจะมาเล่าเรื่องการทำ web scraping ด้วย library ที่ชื่อ Scrapy ครับ ก่อนอื่นจะขอแนะนำคร่าวๆก่อนนะครับว่า web scraping คืออะไร และมีความสำคัญอย่างไรในการทำ data science
Web scraping คือการใช้ script (หรือใช้ computer นั้นเอง) ในการดึงข้อมูลบนอินเตอร์เน็ตที่ต้องการมาเก็บไว้ ไม่ว่าจะเป็นข้อความ ตัวเลข รูปภาพ หรือเสียงก็สามารถทำได้ ซึ่งส่วนมากมักจะทำจะทำในกรณีที่ต้องการข้อมูลในปริมาณมาก และ การค่อยๆ ใช้คนในการดึงข้อมูลเหล่านั้น ไม่ใช่ทางเลือกที่ดีนั่นเอง เพราะคนไม่สามารถที่จะดึงข้อมูลเหล่านั้นได้อย่างมีประสิทธิภาพเท่าการใช้ script ทำให้เสียเวลามาก (ลองจินตนาการว่าเราต้องการรูปแมวในปริมาณมหาศาล การค้นหา google ว่า แมว แล้วค่อยๆ save รูปทีละรูป จะเสียเวลาขนาดไหน)
ในการทำ data science หรือ สร้างโมเดล machine learning นั้น สิ่งแรกๆที่เราต้องทำเลยก็คือการได้มาซึ่งข้อมูล และบ่อยครั้งที่เราไม่มีข้อมูลเหล่านั้นอยู่ในมือ การทำ web scraping จึงมาอุดช่องว่างในจุดนี้
ในปัจจุบัน เครื่องมือที่เป็นที่นิยมสำหรับทำ web scraping บน python มี อยู่หลักๆ 3 ตัว ได้แก่ BeautifulSoup, Selenium, Scrapy ซึ่ง 2 ตัวแรกจะมีข้อดีตรงที่ใช้งานง่ายกว่า แต่ข้อเสียคือ ช้ากว่า และไม่เหมาะแก่การใช้เป็นกิจจลักษณะเท่าตัว Scrapy
เกริ่นกันมาพอสมควรแล้ว ทีนี้เราจะมาเริ่มกันเลยครับ โดย environment ที่ผมจะทำก็คือ Google Colab ซึ่งขอบอกก่อนว่าไม่เหมาะนักกับการใช้ Scrapy แต่เนื่องจากเป็น environment ที่ใครก็สามารถนำไปลองทำได้โดยไม่ต้อง ติดตั้งอะไรบนเครื่องเพิ่มเติม ผมจึงเลือกที่จะใช้ environment ตัวนี้ครับ
สิ่งที่เราจะทำวันนี้คือการดึงข้อมูลวัตถุดิบจากเว็บไซต์ https://www.yummly.com/recipes ซึ่งเป็นเว็บไซต์รวบรวมเมนูอาหาร วัตถุดิบ และวิธีทำ ในครั้งนี้ เราจะทำการดึงชื่ออาหาร และวัตถุดิบของอาหารนั้นๆครับ
ก่อนอื่นก็ต้องสร้างไฟล์ .py ขึ้นมาก่อน ซึ่งใน colab ไม่เหมาะนักกับการสร้างไฟล์ดังกล่าว ผมจึง มีการเพิ่ม magic command %%writefile crawler.py
ไว้บนสุดทุกครั้ง เพื่อเป็นการ save บล็อคดังกล่าวเป็นไฟล์ชื่อ crawler.py นั่นเอง
หลังจากที่เรารันโค้ดชุดนี้แล้ว เราจะได้ไฟล์ชื่อ crawler.py
ขึ้นมาจากคำสั่ง %%writefile crawler.py
ด้านบน
หลังจากนั้นเราก็รัน command ด้านล่างนี้ (หากไม่ได้รันบน Google Colab ให้นำเครื่องหมาย !
ออก และนำไปรันใน Terminal)
!scrapy runspider crawler.py
จะเห็นได้ว่าเกิด error ขึ้น เนื่องจากเรายังไม่ได้สร้างฟังค์ชั่น parse
นั้นเอง ดังนั้นเราจะมาสร้างฟังค์ชั่น parse กันก่อนครับ
การที่เราจะสามารถได้มาซึ่งรายการวัตถุดิบมานั้น เราต้องหาลิ้งค์ในการเข้าไปดูอาหารแต่ละเมนู ซึ่งเราสามารถ inspect ดูเพื่อที่จะทราบได้ จากรูป เราจะเห็นได้ว่า class ที่จะนำไปสู่ลิ้งค์ของอาหารแต่ละชนิดชื่อ link-overlay
และ href
คือสิ่งที่นำไปสู่สู่ลิ้งค์ของอาหาร เราจึงสามารถเขียน selector (พูดง่ายๆคือ ตัวเลือกสำหรับการเลือกลิ้งค์ประเภทนี้) ดังนี้
หลังจากเราสร้างฟังค์ชั่นสำหรับ parse ลิ้งค์ของอาหารแต่ละเมนูแล้ว เราจะมาสร้างตัว parse รายชื่อวัตถุดิบของอาหารแต่ละประเภทกัน ซึ่งก่อนอื่นเราจะทำการสำรวจก่อนเหมือนที่เราทำก่อนหน้านี้
จะเห็นได้ว่าวัตถุดิบที่เราต้องการนั้น อยู่ใน class ingrediant
ซึ่งเราสามารถทำการดึง text ดังกล่าวออกมาดังนี้
โดยรวมแล้ว class RecipeSpider
ของเราจะมีหน้าตาดังนี้
เมื่อทำการรันดูจะเห็นว่าสามารถดึงชื่ออาหารและวัตถุดิบออกมาได้ดีตามที่ตั้งใจไว้
อย่างไรก็ตามเมื่อลองสังเกตุดูจะพบว่าเราสามารถดึงมาได้แค่ 36 เมนูเท่านั้น
ที่เป็นเช่นนี้เพราะหน้าเว็บไซต์นี้ เป็นแบบ infinite scrolling นั่นเอง (ต้องเลื่อนลงไปจนสุดล่างจอก่อน ถึงจะโหลดเมนูอาหารเพิ่มมาให้ดู) ถ้าเป็นแบบนี้ เราก็ไม่สามารถดึงข้อมูลในปริมาณมากๆได้
วิธีแก้ของเราก็คือ การไปหาว่า มีการเคลื่อนไหว network อย่างไรเมื่อเรา scroll ไปถึงจุดล่างสุดของหน้า
เราจะได้ url ที่เกิดขึ้นตอน scroll ไปที่ท้ายสุดของเพจ
https://mapi.yummly.com/mapi/v19/content/search?solr.seo_boost=new&start=36&maxResult=36&fetchUserCollections=false&allowedContent=single_recipe&allowedContent=suggested_search&allowedContent=related_search&allowedContent=article&allowedContent=video&allowedContent=generic_cta&guided-search=true&solr.view_type=search_internal
จะเห็นได้ว่ามีจุดหนึ่งใน url ที่เขียนว่า maxResult=36
อยู่ทำให้เรารู้ได้ว่าเราสามารถเปลี่ยนตัวเลข max result ได้ตามที่เราต้องการ แต่เราต้องมีการแก้ไขโค้ดเล็กน้อย เพราะเมื่อเราเข้าไปในลิ้งค์ดังกล่าว ข้อมูลถูกเก็บในรูปแบบไฟล์ json เราจะอ่านจากไฟล์ json แทน
สุดท้าย เราทำการแก้ฟังค์ชั่น parse
เล็กน้อยเพื่อให้ได้ไฟล์สามารถเก็บข้อมูลเป็นไฟล์ csv ออกมา
เราจะได้ ข้อมูลที่มีหน้าตาดังรูป
ทุกท่านสามารถไปลองเล่นและศึกษาการทำ Web scraping ที่ได้ทำในบทความนี้ด้วยลิ้งค์ Google Colab นี้ครับ
ก็จบไปแล้วครับสำหรับการทำ web scraping ด้วย Scrapy หวังว่าท่านผู้อ่านทุกคนจะได้ความรู้ไม่มากก็น้อยจากบทความนี้นะครับ แล้วพบกันใหม่ในบทความหน้าครับผม :)
Reference
บทความนี้ผมได้ทำตามตัวอย่างจาก https://medium.com/analytics-vidhya/web-crawling-with-scrapy-f4d93c1bfcc7 และทำการ implement ลงใน Google Colab และเพิ่มเติมด้วยการดึงข้อมูลลงไฟล์ csv