我們在 Day9 的時候有用到一個工具叫做 gpt-crawler,有了它就可以很輕鬆地爬取網頁的內容,不過他的格式是 JSON 格式。雖然 JSON 格式對 LLM 來說已經是相對好懂的格式了,不過 LLM 最熟悉的其實是 Markdown 格式的資料,而 Firecrawl 和 Jina 的 Reader API 可以把爬下來的網站自動轉換成 Markdown 使用,來一探究竟吧!
最重要的是,在 Dify 中也支援這兩種方法來建立知識庫!(LangChain, LlamaIndex 也可以)
Firecrawl 是一款由 Mendable.ai 公司和 Firecrawl 社群共同開發的強大網站爬蟲和資料搜集工具。它的主要功能是將整個網站轉換為適合大型語言模型使用的標記語言或結構化資料。
雖然 Firecrawl 是開源的,你可以自己把 Firecrawl 架成一個 Baas (Backend an a service),不過他的免費額度也夠我們個人使用了 (可以爬 500 page)
在 Firecrawl 中主要可以分為兩種爬蟲的方式
在官網 Playground 輸入要爬取的網址,以及一些設定,可以直接拿到 Python / Node / cURL 程式碼
也能看到自己的 API Key
來測試一下吧!一樣用成大住宿服務組的網站來測試,這邊我們把 limit 設定成 10
觀察這些公告網站底下的文章,會發現它們的 url 不是以子網頁的方式呈現,而是以 /p/406-xxx
的方式,像是 https://housing-osa.ncku.edu.tw/p/406-1052-273737,r407.php?Lang=zh-tw
和 https://housing-osa.ncku.edu.tw/p/406-1052-273384,r407.php?Lang=zh-tw ,如果我只想爬取公告的話就比較麻煩
安裝 Python 套件
pip install firecrawl-py python-dotenv
將 API key 寫入 .env
檔案
FIRECRAWL_API_KEY=fc-xxx
產生 Python 程式碼
# Install with pip install firecrawl-py
from firecrawl import FirecrawlApp
from rich import print
from dotenv import load_dotenv
import os
load_dotenv() # 載入環境變數
app = FirecrawlApp(api_key=os.getenv('FIRECRAWL_API_KEY'))
crawl_result = app.crawl_url('https://housing-osa.ncku.edu.tw', params={
'limit': 10,
'scrapeOptions': {
'formats': [ 'markdown' ],
}
}, wait_until_done=False)
print(crawl_result)
job_id = crawl_result['jobId']
status = app.check_crawl_status(job_id)
print(status)
若你將 wait_until_done 設定成 True,則這個程式執行時,會等到完全爬蟲完畢才結束;如果是 False,記得要把 job id 存起來,方便之後檢索。
執行結果,把 job id 存起來
$ python main.py
{'jobId': '331ced2f-31e1-450a-b8b4-74f483f64920'}
{'status': 'active', 'current': 0, 'total': 1, 'data': None, 'partial_data': []}
這時候我們可以用以下程式碼來檢查爬蟲狀態
# Install with pip install firecrawl-py
from firecrawl import FirecrawlApp
from rich import print
from dotenv import load_dotenv
import json, os
load_dotenv()
app = FirecrawlApp(api_key=os.getenv('FIRECRAWL_API_KEY'))
crawl_status = app.check_crawl_status("這邊填入 job id")
print(crawl_status)
# 將資料存入 json 檔案中
with open('result.json', 'w') as f:
json.dump(crawl_status, f, ensure_ascii=False)
格式如下 (因為資料太大ㄌ,所以有些我直接以 xxx 替代,略過了很多東東,不過我們要關注的只有 markdown 和 metadata 中的 title)
{
"current": 43,
"data": [
{
"content":"xxx太大了",
"linksOnPage": [
"https://xxx.xxx",
"url2",
"更多 url"
],
"markdown": "我們要拿的內容",
"metadata": {
"title": "NCKU, Housing Service Division ",
"sourceURL": "https://housing-osa.ncku.edu.tw",
"robots": "index,follow",
"pageStatusCode": 200,
"description": "Brief description"
}
}
],
"partial_data": [],
"status": "completed",
"total": 43
}
再寫一個 Python 腳本,取出 Markdown 檔案,並以 title 作為檔案名稱
import json
from rich import print
import os
with open('result.json', 'r') as f:
data = json.load(f)
print(len(data['data']))
# mkdir data
os.makedirs('data', exist_ok=True)
counter = 0
for item in data['data']:
if item is None:
continue
try:
title = item['metadata']['title']
except Exception as e:
print(e)
print(item)
counter += 1
title = f'{counter}.md'
content = item['content']
with open(f'data/{title}.md', 'w', encoding='utf-8') as f:
f.write(content)
觀察一下檔案們,會發現有些檔案是 pdf 檔案 (像是一些法規) 他也轉換成 markdown 的格式了,超讚!
完整程式碼可以參考 Github 連結
在設定的資料喇元輸入你的 API key
建立知識庫的時候,填入網址,剩下的嵌入方法、怎麼切 document 都跟之前一樣
跑完之後可以選擇要加入知識庫的 page
超炫砲的官網,Jina 不只有爬蟲工具 (Reader API),還有 rerank、嵌入模型、Prompt Perfect 服務等等,很全面的一家公司。
請看下圖 (來源)
只要把你想爬的網址加上 https://r.jina.ai/
就可以使用了 wow (!)
到瀏覽器輸入 https://r.jina.ai/https://housing-osa.ncku.edu.tw/index.php?Lang=zh-tw
試試看,這也太方便了吧...超適合那種只需要爬少少網站的人
不得不說,Jina 官網的 demo 真的是帥
使用上直接用 Python 的 request 就好 (真的是太簡單了)
import requests
response = requests.get('https://r.jina.ai/https://example.com')
print(response.text) # 這個就是 LLM 友善的 Markdonw 文本了
目前 Reader API 是免費的,不需要 API Key,就好像網頁的「閱讀模式」一樣,不過這個是給 LLM 專屬的閱讀模式。
今天介紹的爬蟲工具都是「基於傳統方式的爬蟲」,只不過爬出來的內容經過工具整理後,變成 LLM 看得懂的內容,類似的工具還有 Crawl4AI。
明天來介紹「使用 LLM + Agent 的爬蟲」,這就不是要讓 LLM 讀懂了,而是透過 LLM 的力量,自動適應網站結構變化,減少開發者維護的工作量。過去從純用 Python request 到使用 Beautiful Soup 這類自動解析 html 標籤的工具出現,到現在有 LLM 幫你解析,你要做的就是下好 Propmt,真慶幸自己活在 2024 啊...