#46 - วิธีติดตั้ง SearXNG และวิธีใช้ Search API สำหรับการค้นหาข้อมูล
SearXNG [1] เป็นเว็บ Search Engine ที่รวบรวมผลการค้นหาจากเว็บต่าง ๆ รวมอยู่ประมาณ 250 บริการ โดยผู้ใช้จะไม่ถูกติดตาม และรองรับการใช้งานผ่าน Tor สำหรับการใช้งานเว็บไซต์โดยไม่ระบุตัวตน
ผู้ใช้สามารถใช้งานเว็บไซต์ที่ใช้ SearXNG ได้โดยดูรายการในหน้าเว็บ searx.space หรือสามารถติดตั้งบนคอมพิวเตอร์ตัวเองได้เลยถ้าเราไม่ต้องการเข้าไปใช้งานเว็บไซต์ของคนอื่น
การติดตั้ง
การติดตั้ง [2] มีอยู่หลายวิธี แต่วิธีที่ทำได้ง่ายที่สุดคือการใช้งานผ่าน Container บน Docker (หรือ Podman ก็ได้) โดยกรณีที่เราใช้งานผ่าน Docker เราจำเป็นต้องเพิ่มผู้ใช้ของเราเข้าไปในกลุ่ม docker เสียก่อนโดยพิมพ์คำสั่ง
$ sudo usermod -aG docker $USER
โดยตัวแปร $USER เป็นตัวแปรที่มีหน้าที่บอกชื่อผู้ใช้ที่เราล็อคอินบน macOS หรือ Linux
ในตัวอย่างนี้เราจะใช้งานผ่าน Docker โดยใช้งาน Docker Compose ครับ ขั้นตอนแรกเราจำเป็นต้องดาวน์โหลดไฟล์ docker-compose.yml เสียก่อนโดยพิมพ์คำสั่ง
$ mkdir -p <โฟลเดอร์ที่เก็บการตั้งค่าและเก็บ Environment Variable>
$ cd <โฟลเดอร์ที่เก็บการตั้งค่าและเก็บ Environment Variable>
$ curl -fsSL \
-O https://raw.githubusercontent.com/searxng/searxng/master/container/docker-compose.yml \
-O https://raw.githubusercontent.com/searxng/searxng/master/container/.env.example
หลังจากนั้นเราก๊อบปี้ไฟล์ .env.example โดยให้เปลี่ยนชื่อเป็น .env แทน จากนั้นเราสามารถตั้่งค่าในไฟล์ .env ได้ตามใจชอบผ่านการพิมพ์คำสั่งตามด้านล่างนี้
$ cp .env.example .env
$ vim .env (หรือจะใช้ nano หรือโปรแกรมแก้ไขข้อความตัวอื่นก็ได้)
ในไฟล์ .env เราสามารถตั้งค่า
- SEARXNG_VERSION สำหรับการกำหนด version ของ SearXNG โดยค่าเริ่มต้นเป็น latest
- SEARXNG_HOST สำหรับการตั้งค่า Host ของ SearXNG โดยค่าเริ่มต้นเป็น [::] ที่สามารถเข้าถึงจากคอมพิวเตอร์ไหนก็ได้
- SEARXNG_PORT สำหรับการตั้งค่า Port ของ SearXNG โดยค่าเริ่มต้นเป็น 8080
เมื่อเราตั้งค่า (หรือไม่ตั้งค่า) เรียบร้อยแล้ว เราจะให้ตัว Container SearXNG สร้างไฟล์การตั้งค่าไว้ที่ตำแหน่ง ./core-config/settings.yml ด้วยการพิมพ์คำสั่ง
$ docker compose up -d
$ docker compose down
หลังจากนั้นผู้ใช้สามารถตั้งค่าเพิ่มเติมได้ใน settings.yml ครับ
เมื่อตั้งค่าเรียบร้อยแล้ว เราสามารถเปิดใช้งาน SearXNG ได้โดยการพิมพ์คำสั่ง
$ docker compose up -d
เมื่อเริ่มต้น Container แล้วเราเข้ามายังหน้าเว็บไซต์ SearXNG ที่เราเปิดช้ได้โดยการพิมพ์ http://localhost:8080 (หรือพอร์ตอื่นตามที่เราตั้งค่าไว้) แล้วตัวเว็บเบราวเซอร์จะปรากฏหน้าจอตามด้านล่างนี้

ผู้ใช้สามารถค้นหาข้อมูลได้ตามที่ต้องการโดยพิมพ์ที่กล่องข้อความตรงกลางหน้าเว็บ หรือสามารถตั้งค่าได้โดยการกดที่ Preferences ที่มุมบนขวาครับ
ต่อมาเรามาพูดถึงเรื่องหลักเลยคือ Search API
Search API
Search API [3] เป็น API ที่อนุญาตให้เราใช้งานการค้นหาผ่าน SearXNG ได้จากโปรแกรมภายนอกครับ โดยตัวระบบจะรองรับการใช้งานแบบ GET หรือ POST อย่างไรก็ดี เราจำเป็นต้องตั้งค่าในไฟล์ settings.yml ตรงส่วน search ตรงหัวข้อ format เสียก่อนเพื่อให้ตัวโปรแกรมรองรับการคืนค่าจาก API แบบ JSON, CSV หรือ CSS
search:
# Filter results. 0: None, 1: Moderate, 2: Strict
safe_search: 0
# Existing autocomplete backends: "360search", "baidu", "bing", "brave", "dbpedia", "duckduckgo", "google",
# "yandex", "mwmbl", "naver", "seznam", "sogou", "startpage", "swisscows", "quark", "qwant", "wikipedia" -
# leave blank to turn it off by default.
autocomplete: ""
.
.
.
# remove format to deny access, use lower case.
# formats: [html, csv, json, rss]
formats:
- html
ในตัวอย่างเราต้องการให้ SearXNG คืนค่า API แบบ JSON เราสามารถแก้ไขได้ตามด้านล่างนี้
# remove format to deny access, use lower case.
# formats: [html, csv, json, rss]
formats:
- html
- json
เมื่อเราแก้ไขแล้ว ให้บันทึก แต่ถ้าบันทึกไม่ได้ก็น่าจะติดเรื่อง Permission ให้เราพิมพ์ sudo vim settings.yml (หรือจะใช้โปรแกรมแก้ไขข้อความตัวอื่น ๆ ก็ได้)
แก้ไขเสร็จแล้วให้เราปิดและเปิด SearXNG ใหม่เสียก่อนโดยการพิมพ์
$ docker compose down
$ docker compose up -d
ต่อมาเรามารู้เกี่ยวกับ Search API ของ SearXNG โดยเราสามารถใช้งานตัว API ได้ 3 วิธีตามตัวอย่างด้านล่างนี้ (ที่ใช้ curl) โดยวิธีแรกเป็น GET ส่วนสองวิธีหลังเป็น POST
$ curl 'http://< ตำแหน่ง SearXNG >/search?q=searxng&format=json'
$ curl -X POST 'http://< ตำแหน่ง SearXNG >/search' -d 'q=searxng&format=csv'
$ curl -L -X POST -d 'q=searxng&format=json' 'http://< ตำแหน่ง SearXNG >/'
โดยตำแหน่ง Sear XNG ก็เป็น http://localhost:8080 (หรือจะเป็นตำแหน่งที่อยู่อื่น พอร์ตอื่นก็ขึ้นกับการตั้งค่าของแต่ละคน)
ต่อมานอกจากรู้วิธีการเรียกใช้ Search API แล้ว เราจำเป็นต้องรู้พารามิเตอร์ที่เกี่ยวข้องเสียก่อน ได้แก่
- q (จำเป็น) เป็นข้อความ Search Query ที่เราต้องการให้ค้นหาข้อมูล โดยตัว SearXNG รองรับการพิมพ์คำสั่งเพิ่มเติมที่ขึ้นกับบริการค้นหานั้น ๆ ได้แก่ site:github.com SearXNG เป็นคำสั่งที่ใช้กับเว็บ Google อย่างไรก็ตาม ถ้าเราพิมพ์คำสั่งตามที่กล่าวไว้แล้วตัวเว็บค้นหาเว็บนั้น ๆ ไม่อรงรับ เราก็อาจจะได้ผลไม่ตรงตามที่ต้องการ ผู้ใช้สามารถดูข้อมูลเพิ่มเติมได้ใน Search Syntax
- categories (ไม่จำเป็น) เป็นหมวดหมู่ของ Search Engine ที่เราต้องการให้ค้นหา โดยเราสามารถกำหนดได้หลายประเภทโดยการแบ่งด้วย commma (,) โดยเราจะแบ่งเป็น general, images, videos, news, news, map, music เป็นต้น ผู้ใช้สามารถดูได้ในหน้า Configured Engines
- engines (ไม่จำเป็น) เป็นการระบุ Search Engine ที่เราต้องการใช้ โดยสามารถกำหนดได้หลายเว็บโดยการแบ่งด้วย commma (,)
- languages (ไม่จำเป็น) เป็นการกำหนดภาษาที่เราต้องการ
- pageno (ไม่จำเป็น) เป็นการกำหนดตำแหน่งหน้าที่เราต้องการค้นหา
- format (ไม่จำเป็น) เป็นการกำหนดลักษณะข้อมูลที่ต้องการให้เว็บคืนค่ากลับมา โดยเราสามารถกำหนดเป็น json, csv, rss แต่ในบทความนี้เรากำหนดเป็น JSON เราจำเป็นต้องพิมพ์ json
- autocomplete (ไม่จำเป็น) เป็นการกำหนด Search Engine ที่เราต้องการให้ Complete คำที่เราพิมพ์เข้าไปในระบบ ได้แก่ google, dbpedia, duckduckgo, mwmbl, startpage, wikipedia, swisscows, qwant
- safesearch (ไม่เป็น) เป็นการกำหนดให้สามารถค้นหาข้อมูลได้แบบปลอดภัย แต่ฟีเจอร์นี้ขึ้นกับ Search Engine โดยบางเว็บรองรับ บางเว็บก็ไม่รองรับ โดยเราสามารถตั้งค่า 0, 1, 2 ที่เป็น None, Moderate, Strict
- enabled_plugins (ไม่เป็น) เป็นการเปิดใช้งาน Plugin ของเว็บ SearXNG ที่เราใช้อยู่ โดย SearXNG ที่หลาย Plugin ให้เลือกใช้ ได้แก่ Hash_plugin, Self_Information, Tracker_URL_remover, Ahmia_blacklist, Hostnames_plugin, Open_Access_DOI_rewrite, Vim-like_hotkeys, Tor_check_plugin
- disabled_plugins (ไม่เป็น) เป็นการปิดใช้งาน Plugin ของ SearXNG ที่เราไม่ต้องการใช้
ส่วนข้อมูลอื่นสามารถดูได้ในหน้า Search API
เมื่อทราบข้อมูลแล้ว ต่อมาเราจะมาเขียนโค้ดด้วย Python แต่ก่อนอื่นเราจำเป็นต้องติดตั้งแพคเกจอย่าง requests เสียก่อนเพื่อให้เราสามารถ request ตัว API ผ่าน GET หรือ POST ด้วยการพิมพ์
$ pip install requests
เมื่อติดตั้งเสร็จแล้ว เรามาเขียนโค้ดกัน ตัวอย่างนี้เราจะเลือกการเรียกใช้ API แบบ POST ตามตัวอย่างที่ 2 ที่เขียน curl -X POST 'http://< ตำแหน่ง SearXNG >/search' -d 'q=searxng&format=csv' ด้วยการกำหนดพารามิเตอร์เพิ่มเติมนอกจาก q ที่สองพารามิเตอร์ ได้แก่
- format เป็น json
- pageno เป็นหน้าแรก โดยกำหนดเป็น 1
ในขั้นตอนแรก เรียกใช้ไลบรารี requests และ json (สำหรับการแปลง JSON เป็นตัวแปรแบบ dict) เสียก่อน
import requests
import json
ต่อมาเราจะเรียกใช้ API โดยผ่านการเช็ค error ด้วย try except ครับ
ส่วนแรกเป็นการ request แบบ POST
try:
result = requests.post("http://localhost:8080/search", data = {
"q" : "Bangkok", # <- หรือจะใช้คีย์เวิร์ดอื่น ๆ หรือกำหนดเป็นตัวแปรที่เก็บข้อมูลจากการ input ก็ได้
"format" : "json",
"pageno" : "1" # <- กำหนดหน้าได้ตามที่ต้องการ
})
ต่อมาเป็นการกำหนดให้ตัวโปรแกรม raise ให้เกิด Error กรณีที่เราโหลดไม่สำเร็จ (หรือ HTTP status ไม่เท่ากับ 200)
result.raise_for_status()
จากนั้นรับค่าที่ได้จากตัว SearXNG ด้วยการดูข้อมูลในตัวแปร request ด้วย property อย่าง text
text = result.text
เมื่อได่้ข้อมูลจากหน้าเว็บ SearXNG แล้ว ตัวแปรที่ได้จะเป็ย JSON ที่มีโครงสร้างบางส่วนตามด้านล่างนี้
{"query": "Bangkok", "number_of_results": 0, "results": [{"url": "xxxx", "title": "xxxx", "content": "xxxx", "thumbnail": "data:image/jpeg;base64,/xxxx", "engine": "<ชื่อ Search Engine>", "template": "default.html", "parsed_url": ["ที่อยู่หน้าเว็บที่แบ่งเป็น array"], "img_src": "", "priority": "", "engines": ["array ของ search engine"], "positions": ["ตำแหน่งของผลลัพธ์ตามแต่ละ search engines ที่เรียงตามลำดับ], "score": < score ของผลลัพธ์>, "category": "general", "publishedDate": null}, {"url": ...
ให้เราถอด decode ข้อความ JSON แล้ววนลูปเข้าไปในตัวแปรตรงส่วนที่เป็น dictionary key อย่าง results โดยในตัวอย่างนี้จะเป็นการวนลูปเพื่อแสดงหัวข้อและที่อยู่เว็บไซต์ของหน้านั้น ๆ
result_dict = json.loads(text)['results']
for result_each in result_dict:
title = result_each['title']
url = result_each['url']
print(f"{title} -> {url}")
จากนั้นเราเขียนโค้ดเพื่อจับ Error จากการ requests เมื่อได้ HTTP status ไม่เท่ากับ 200 และเมื่อเกิด Error อื่น
except requests.RequestException as e:
console.print(f"Sending request for a search API is not success. => {e}")
except Exception as e:
console.print("Cannot request a search API")
console.print(e)
เมื่อเขียนโค้ดเสร็จแล้วก็จะมีหน้าตาประมาณนี้ครับ
import requests
import json
try:
result = requests.post("http://localhost:8080/search", data = {
"q": "Bangkok",
"format": "json",
"pageno": "1"
})
result.raise_for_status()
text = result.text
result_dict = json.loads(text)['results']
for result_each in result_dict:
title = result_each['title']
url = result_each['url']
print(f"{title} -> {url}")
except requests.RequestException as e:
print(f"Sending request for a search API is not success. => {e}")
except Exception as e:
print("Cannot request a search API")
print(e)
แค่นี้ก็ใช้งานได้แล้ว โดยผลลัพธ์จะแสดงประมาณตามด้านล่างนี้ (ผลลัพธ์อาจจะแตกต่างไปในแต่ละคน)

ที่มา
Kittisak Chotikkakamthorn
จบทั้งแพทย์ + วิศวะร่วมกับผ่านการฝึกงานทางด้าน AI ที่มหาวิทยาลัยที่ไต้หวันที่พัฒนาเทคนิค Machine Learning ที่เป็น state-of-the-art (SOTA) สำหรบัการแก้ปัญหาทางการแพทย์ ปัจจุบันเขียนบล็อกโดยสนใจเกี่ยวกับทางด้าน Coding, AI, Data รวมถึงเขียนเป็นไดอารี่เป็นหลัก
ผู้อ่านสามารถส่งอีเมลมาทาง contact[at]nickuntitled.com