เสิร์ชเอนจิน 80 บรรทัดที่สร้างด้วย Python
- เมื่อเดือนกันยายนที่ผ่านมา ผู้เขียนได้เข้าร่วมงานที่ Wallapop ในตำแหน่งนักวิทยาศาสตร์ข้อมูลด้านการค้นหา และทำงานกับเสิร์ชเอนจินโอเพนซอร์สชื่อ Solr
- เพื่อทำความเข้าใจหลักการพื้นฐานของเสิร์ชเอนจิน ผู้เขียนจึงตัดสินใจสร้างเสิร์ชเอนจินขึ้นมาเองตั้งแต่ต้นด้วย Python
- เป้าหมายคือการแก้ปัญหา "วิกฤตการค้นพบเว็บไซต์ขนาดเล็ก" เพื่อทำให้เว็บไซต์เล็ก ๆ ที่ค้นหาไม่เจอผ่านเสิร์ชเอนจินอย่าง Google กลับมายิ่งใหญ่อีกครั้ง
- บทความนี้อธิบายขั้นตอนการสร้างเสิร์ชเอนจินด้วย Python และสามารถดูโค้ดทั้งหมดที่เขียนไว้ได้ในรีโพซิทอรี GitHub ของ microsearch
- เสิร์ชเอนจินที่ทำขึ้นนี้ไม่ใช่เสิร์ชเอนจินที่พร้อมใช้งานในงานจริง แต่เป็นตัวอย่างแบบของเล่นที่ใช้งานได้ ซึ่งแสดงให้เห็นว่าเสิร์ชเอนจินทำงานภายในอย่างไร
microsearch
- สำรวจองค์ประกอบของ microsearch และดูว่าแต่ละส่วนถูกสร้างขึ้นอย่างไร: (1) crawler, (2) inverted index, (3) ranking, (4) interface
Crawler
- ขั้นตอนแรกของการสร้างเสิร์ชเอนจินคือการเตรียมข้อมูลสำหรับใช้ค้นหา
- ผู้เขียนสร้างเสิร์ชเอนจินจากข้อมูลของบล็อกที่ติดตามอยู่ โดยตั้งใจจะทำ "Google เวอร์ชันท้องถิ่น"
- การ crawl ครอบคลุมกระบวนการดาวน์โหลดและจัดระเบียบโพสต์ทั้งหมดจากรายการบล็อกที่กำหนด
- เพื่อให้เร็วขึ้น ผู้เขียนใช้ไลบรารี
asyncio ของ Python ทำให้เวลาการ crawl ลดลงจาก 20 นาทีเหลือ 20 วินาที
- ใช้ RSS feed จำนวน 642 รายการ โดยในจำนวนนี้ราว 100 รายการเป็นบล็อกที่อ่านเป็นประจำ และอีก 500 รายการนำมาจากโปรเจกต์บล็อก surprisetalk
Inverted index
- Inverted index คือโครงสร้างข้อมูลที่แมปคีย์เวิร์ดเข้ากับเอกสาร ทำให้ค้นหาเอกสารที่มีคำใดคำหนึ่งปรากฏอยู่ได้ง่าย
- เมื่อผู้ใช้ค้นหาคิวรี ระบบจะใช้ inverted index เพื่อดึงเอกสารทั้งหมดที่ตรงกับคีย์เวิร์ดในคิวรี
- ตรรกะของ inverted index ถูกนิยามไว้ในคลาสชื่อ
SearchEngine และทำการติดตั้งโดยการกำหนดค่าเริ่มต้นให้พจนานุกรมสองชุด
Ranking
- เมื่อมีชุดเอกสารที่ตรงกับคิวรีแล้ว ก็จำเป็นต้องมีวิธีจัดเรียงลำดับเอกสารเหล่านั้น
- วิธีจัดอันดับที่มีชื่อเสียงที่สุดคือ PageRank ของ Google แต่ก็ยังมีตัวเลือกอื่น เช่น BM25 ที่จัดอันดับเอกสารตามเนื้อหา
- ผู้เขียนเติมส่วนที่ขาดหายไปของคลาส
SearchEngine รวมถึงวิธีคำนวณคะแนน BM25
Interface
- หลังจากสร้างเสิร์ชเอนจินแล้ว ผู้เขียนต้องการเปิดให้ใช้งานในรูปแบบใดรูปแบบหนึ่ง
- จึงสร้างแอป FastAPI เพื่อเปิด endpoint สำหรับเสิร์ชเอนจิน และเรนเดอร์หน้าเว็บอย่างง่ายสำหรับทำการค้นหา
- เพื่อให้อ่านผลลัพธ์ได้ง่าย จึงตัดสินใจเลือกแสดงเฉพาะ URL อันดับต้น ๆ จำนวน N รายการ
ฟีเจอร์ที่ยังขาด
- หากผู้อ่านคุ้นเคยกับเสิร์ชเอนจินอยู่แล้ว ก็น่าจะสังเกตได้ว่ามีฟีเจอร์อีกมากที่ยังไม่ได้ถูกนำมาใช้
- ที่ยังขาดอยู่ได้แก่ query operator, การทำดัชนีแบบ n-gram, การขยายคิวรีหรือเอกสาร และความสามารถในการ crawl กับ indexing ไปพร้อมกัน
บทสรุป
- จากโปรเจกต์นี้ ผู้เขียนเข้าใจการทำงานภายในของ Solr ดีขึ้น และได้เรียนรู้ถึงความน่าทึ่งของการเขียนโค้ดแบบ asynchronous
- ขั้นตอนถัดไปในการสร้างเสิร์ชเอนจินส่วนตัวคือการเพิ่มความสามารถด้าน semantic search ให้กับเสิร์ชเอนจิน
ความเห็นของ GN⁺
- ประเด็นสำคัญที่สุดของบทความนี้คือ บุคคลทั่วไปสามารถสร้างเสิร์ชเอนจินขึ้นมาเองได้เพื่อปรับปรุงการค้นพบเว็บไซต์ขนาดเล็ก
- ประสบการณ์ในการใช้ Python และไลบรารีโอเพนซอร์สเพื่อทำให้การสร้างเสิร์ชเอนจินที่มีฟังก์ชันซับซ้อนกลายเป็นเรื่องเรียบง่าย อาจเป็นแรงบันดาลใจให้วิศวกรซอฟต์แวร์ระดับเริ่มต้นได้เช่นกัน
- บทความนี้มอบทั้งมุมมองเชิงเทคนิคและโอกาสในการเรียนรู้เชิงปฏิบัติ ด้วยการแสดงให้เห็นประสิทธิภาพของ asynchronous programming และความสำคัญของโครงสร้างข้อมูลผ่านตัวอย่างจริง
1 ความคิดเห็น
ความเห็นจาก Hacker News
การพัฒนาเสิร์ชเอนจิน BM25 ด้วย Pandas
รีวิวโค้ด: คลาส
SearchEnginek1และbและในโค้ดก็ไม่มีคอมเมนต์เลย_documentsใช้ URL เป็นคีย์ และใช้เนื้อหาของ URL นั้นเป็นค่าความซับซ้อนของเสิร์ชเอนจิน
ความเห็นเรื่องจำนวนบรรทัดของโค้ด
มุกเกี่ยวกับสำนวนในโค้ด
chunk for chunk in chunks if chunkในโค้ด ก็ทำให้นึกถึงมุกเกี่ยวกับคนตัดไม้ตัวอย่างโค้ด recommendation engine
การเปรียบเทียบประสิทธิภาพของไลบรารี parsing
lxml.htmlและlxml.html.cleanอาจเร็วกว่าBeautifulSoupมากคำแนะนำเรื่องการใช้คีย์เวิร์ด
ความเห็นต่อโปรเจกต์เชิงการศึกษา
ข้อสงสัยเกี่ยวกับการใช้ Python กับการประมวลผลข้อมูลขนาดใหญ่