Web Scraping Part 3
May 14, 2020
Last updated
Was this helpful?
May 14, 2020
Last updated
Was this helpful?
มาต่อกันกับ series Python Web Scraping part 3 นะครับ หลังจากที่ใน เราได้เรียนรู้วิธีการแกะ XPath ของแต่ละ element ออกมาจาก web browser แบบง่าย ๆ กันแล้ว แต่ทีนี้ในกรณีที่ข้อมูลที่เราสนใจมีหลายตำแหน่งมาก เราคงไม่อยากเสียเวลานั่ง extract แต่ละ element ด้วยมือทั้งหมดใช่ไหมครับ (เพราะถ้าจะทำด้วยมือทั้งหมด ก็ก๊อปตัวข้อมูลมาตรง ๆ เลยสะดีกว่า 555)
ท่านที่พอจะมีประสบการณ์การทำเว็บมาบ้าง พอเห็น XPath สัก 1 หรือ 2 อัน ก็อาจจะเดาได้แล้ว ว่า XPath ที่เหมาะสม ที่น่าจะครอบคลุมทุก ๆ element นั้น ควรจะเป็นอะไร แต่ถึงจะเดาไม่ออกก็ไม่เป็นไรครับ เพราะอย่างบาง website ที่ซับซ้อนขึ้นหน่อย ต่อให้มีประสบการณ์ก็คงเดาไม่ออกในทีแรกเช่นกัน
สำหรับในบทความนี้ก็จะสอนวิธีหนึ่งที่สามารถทำได้ เพื่อหา XPath ที่ "น่าจะ" ครอบคลุมข้อมูลทั้งหมดที่เราต้องการมานะครับ ซึ่งเป็นวิธีที่ผู้เขียนเองก็ใช้งานอยู่จริงในการ scrape website ในหลาย ๆ ครั้งครับ (ที่บอกว่า "น่าจะ" เนี่ย เพราะว่าในความเป็นจริงไม่มีใครรู้หรอกครับ ว่า website เป้าหมายนี้ ถูกเขียน หรือถูกสร้างมาอย่างไร แต่ด้วยวิธีดังกล่าว+หลักของสถิติ เราก็จะมั่นใจได้ในระดับหนึ่งว่า XPath ของเรามัน "น่าจะ" ดีเพียงพอครับ)
วิธีหนึ่งที่ผมทำก็คือ sample XPath ออกมาดู เอามา สำรวจ เพิ่มอีกเยอะ ๆ ก็จะช่วยให้เห็นภาพมากขึ้นครับ จากนั้นเราก็จะใช้ syntax ของ XPath ในการ select และระบุ condition เพื่อให้ครอบคลุมกรณีที่เรา sample ออกมา ให้มากที่สุดครับ
ทบทวนสักเล็กน้อย ใน part นี้เราก็ยังอยู่กับเว็บ Wikipedia กันเหมือนเดิมนะครับ โดยเป้าหมายคือ หา XPath สำหรับ extract รายชื่อเทศบาลตำบลทั้งหมด ซึ่งใน เราใช้ Chrome Inspector ในการแกะ XPath ของ "Element" หนึ่ง ๆ มาได้แบบง่าย ๆ แล้วนะครับ ในตอนนี้เรากำลังจะหา XPath ที่สามารถ extract ข้อมูลทั้งหมดได้ (คือครอบคลุมทุก element ไม่ใช่แค่ 1 element)
อย่างในเว็บเป้าหมาย ถ้าลอง scroll เลื่อนขึ้นลงดู จะเห็นว่ามันมีหลายตาราง เพราะฉะนั้น เพื่อให้เราได้เห็นรูปแบบที่หลากหลาย แล้วก็ครอบคลุมข้อมูลทั้งหมดมากที่สุด ก็ควรจะหยิบ sample ออกมาจากหลาย ๆ ที่ กระจาย ๆ กันหน่อยนั่นเองครับ เช่น เอามาจากตาราง 1 บ้าง จากตาราง 8 บ้าง จากตารางสุดท้ายบ้าง หรือจากหัวตารางบ้าง จากท้ายตารางบ้าง ปน ๆ กันไป โดยหลักสถิติแล้วยิ่งเราสุ่มมามากเท่าไหร่ เราก็จะยิ่งมั่นใจได้ว่าเราได้เห็น pattern ที่เป็นไปได้ทั้งหมดแล้วมากขึ้นนั่นเองครับ (จะเรียกว่าหลักสถิติหรือดวงก็ได้นะครับ 555)
สำหรับท่านที่ยังไม่เข้าใจว่าจะเอา sample XPath ตรงนี้มาได้อย่างไร กรุณาอ่าน ด่วน ๆ เลยครับ! หรือถ้ามีข้อสงสัย สามารถคอมเม้นถามด้านล่าง หรือในเพจ ได้เลยนะครับ
ด้านล่างนี้เป็นตัวอย่างที่ผม sample ออกมา
จะเห็นว่า XPath จริง ๆ ของข้อมูลเรา มันไม่ได้ตรงไปตรงมาเสมอไปนะครับ อย่างเช่นตัวเลขของ table และ tr ใน XPath ของแต่ละ sample นั้น ก็อาจจะไม่ได้สัมพันธ์กับเลขตารางหรือเลขบรรทัดของข้อมูลเสมอไป หรือบางทีก็มี element b บ้าง บางทีก็ไม่มี ซึ่งในเหตุการณ์เช่นนี้สามารถพบเจอได้จริง ในเว็บทั่ว ๆ ไปนะครับ โดยอาจเกิดจาก developer ที่เขียนโค้ดไม่สัมพันธ์กันเอง หรืออย่างในกรณีของ Wikipedia นี้ คืออาจเกิดจาก user ซึ่งเป็นผู้เขียนบทความได้ใช้โครงสร้างของข้อมูลที่แตกต่างกันนั่นเองครับ
ในขั้นตอนนี้ เราจะทำการวิเคราะห์ XPath ที่เรา sample ออกมา แล้วก็ตั้งข้อสังเกตุถึง จุดที่เหมือน และ จุดที่แตกต่าง สำหรับแต่ละตัวอย่างนะครับ ซึ่งอาจจะต้องใช้ความรู้ HTML เล็กน้อยนะครับ แต่จะพยายามอธิบายให้เข้าใจง่ายที่สุดนะครับ
เมื่อเรา sample ออกมาดูเยอะ ๆ แล้วก็จะเห็นครับว่ามันมีส่วนที่เหมือนกันอยู่ คือ ขึ้นต้นด้วย element <table>
ซึ่ง <table>
ก็หมายถึงตัวตารางแต่ละตารางนั่นเองครับ
และจะสังเกตุได้จาก XPath ที่ได้มา ว่าข้อมูลที่เราต้องการ
1. จะเริ่มต้นที่ ตารางที่ 3 (เพราะในตารางที่ 1 บรรทัดที่ 1 ใช้ table[3]
)
2. แล้วตามด้วย <tbody>
3. ตามด้วย <tr>
คือแต่ละ row ของ table นั้น ๆ
4. จากนั้นก็ <td>
คือแต่ละ column ของ row นั้น ๆ ซึ่งอาจจะเป็น column ที่ 2 หรือ column ที่ 3 ก็ได้ (เช่น sample (4)
และ (5)
)
5. แล้วก็อาจจะมี หรือไม่มี <b>
ก็ได้ (กรณีที่ไม่มี <b>
ดู sample ที่ (8)
)
6. ตามด้วย <a>
คือข้อความที่เป็น link
7. แล้วก็อาจจะมี หรือไม่มี <b>
ก็ได้
นี่ก็เป็นข้อสังเกตุทั้งหมดที่เราได้จาก sample ของเรานะครับ
ต่อไป จากข้อสังเกตุทั้ง 7 ข้อ ด้านบน เราก็ได้ทราบแล้วว่า elements ที่เราต้องการ จะมี XPath ลักษณะอย่างไร ทีนี้เรานำข้อสังเกตุทั้งหมดมารวมกัน เพื่อสร้าง XPath ขึ้นมา 1 อัน ที่สามารถครอบคลุม cases ที่กล่าวมาได้ทั้งหมด! โดยใช้การเขียน condition มาเพื่อช่วยเลือก elements ที่ต้องการนะครับ อันดับแรกก็เริ่มจาก XPath ที่ทุก sample มีร่วมกันก่อน ก็คือ
ทีนี้ ก็จะเริ่มใส่ condition ตามข้อสังเกตุของเราข้างต้นแล้วนะครับ
1. เราต้องการเลือกตารางตั้งแต่ตารางที่ 3 ขึ้นไปเท่านั้น วิธีการคือให้ใส่ condition เข้าไป ว่า position ของ <table>
เนี่ย ต้องมากกว่าหรือเท่ากับ 3 ครับ ซึ่งเขียนเป็น condition ได้ว่า position() >= 3
ก็จะได้ XPath เป็น
2. ตามด้วย <tbody>
และ <tr>
ก็เติมเข้าไปตรง ๆ ได้เลยครับ
3. ตามด้วย <td>
แต่เราจะเอาเฉพาะ column ที่ 2 หรือ 3 เท่านั้น วิธีหนึ่งที่ทำได้ก็คือ ใส่ condition ว่า position ของ <td>
เนี่ย ต้อง >= 2 และ <= 3 ซึ่งเขียน condition ออกมาได้ว่า 2 <= position() and position() <= 3
จึงได้ XPath เป็น
4. อย่างที่สังเกตุว่าบาง sample ก็มี <b>
ขึ้นก่อนแล้วตามด้วย <a>
(/b/a/
)
หรือบาง sample ก็เป็น <a>
ขึ้นก่อน แล้วตามด้วย <b>
(/a/b/
)
แล้วยังมี <b>
แล้ว <a>
แล้ว <b>
อีก (/b/a/b/
)
โชคดีที่ใน XPath เราสามารถละได้ โดยการเขียนเป็น //a//
จะหมายถึงว่าจะมี element อะไรขึ้นก่อน <a>
ก็ได้ (กี่ elements ก็ได้ หรือจะไม่มีก็ได้) แล้วตามด้วย elements อะไรก็ได้ (กี่ elements ก็ได้ หรือจะไม่มีก็ได้) แล้วตัว engine ก็จะหาทุก ๆ elements ที่เป็นไปได้มาให้เองครับ
note: ซึ่งการละใน XPath นี้ ต้องระวังในการใช้สักเล็กน้อยนะครับ อย่าง //a//
อาจหมายถึง /b/a
ก็ได้ หรือ /b/a/b
ก็ได้ หรืออาจหมายถึง /b/div/a/div/b/a/b/div
ก็ได้ คือในส่วนที่ละ จะแทนเป็นอะไรก็ได้นั่นเองครับ
5. สุดท้ายตามด้วย text()
คือต้องการเอาเฉพาะข้อความที่อยู่ใน element นั้นออกมา
ได้ XPath สุดท้ายเป็น
ซึ่งเป็น XPath ที่เรามั่นใจว่าและครอบคลุมทุกกรณีที่เรา sample ออกมา และ(หวังว่า)จะครอบคลุมข้อมูลที่เราต้องการจริง ๆ ทั้งหมด
สำหรับการสร้าง XPath นั้น วิธีการที่นำเสนอไปก็เป็นหนึ่งในวิธีที่สามารถทำได้ง่าย ๆ ซึ่งเราจะสามารถมั่นใจได้ในระดับหนึ่งว่า XPath ที่ได้มานั้น ครอบคลุมข้อมูลส่วนใหญ่ โดยทำการ sample ออกมาให้มากขึ้น และ sample ในหลาย ๆ จุดที่แตกต่างกัน กระจาย ๆ กันไป แต่อาจจะต้องอาศัยความรู้ในเรื่อง syntax และคำสั่งของ XPath สักเล็กน้อยสำหรับการเขียน condition เพื่อ select element ต่าง ๆ นะครับ
และถ้ามีเรื่องไหนที่สนใจเพิ่มเติมสามารถ comment เอาไว้ได้นะครับ
และเป็น XPath ที่เราก็ได้นำไปใช้จริงแล้วในการ extract รายชื่อเทศบาลตำบล ใน นั่นเองครับ
ซึ่งจริง ๆ แล้ว ผู้เขียนเองก็ไม่ได้จำคำสั่งของ XPath ได้ทั้งหมดจริง ๆ หรอกครับ เมื่อจำเป็นต้องใช้ที ก็ search หาจาก internet เอา โดยผู้เขียนพบว่า เว็บ w3school ได้ทำรายการของคำสั่งต่าง ๆ พร้อมคำอธิบายเอาไว้ได้ดีและครบถ้วนแล้ว ทุก ๆ ท่านสามารถนำไปใช้เพื่ออ้างอิงขณะที่เขียนได้เลยครับ
FB Page:
Reference :