一日一技:使用大模型實現(xiàn)全自動爬蟲
在文章一日一技:圖文結合,大模型自動抓取列表頁中,我提到可以使用大模型實現(xiàn)一個全自動爬蟲。只需要輸入起始URL加上需求,就可以借助模擬瀏覽器自動完成所有的抓取任務。今天,借著智譜全模型家族正式上線 bigmodel.cn這個契機,我們就來實現(xiàn)全自動爬蟲。
在實現(xiàn)的過程中,我發(fā)現(xiàn)涉及到的知識點可能一篇文章講不完,因此拆分成了多篇文章。
爬蟲演示
今天是第一部分,我們暫時不依賴模擬瀏覽器,而是使用httpx(你也可以使用requests)實現(xiàn)全自動爬蟲,傳入我博客文章列表頁,爬蟲會自動抓取前三頁所有博客文章的標題、正文、作者、發(fā)布時間。
爬取結果如下圖所示:
圖片
運行過程如下圖所示:
圖片
爬蟲首先會進入起始列表頁,抓取上面的所有文章。然后進入列表頁第二頁,再抓取所有文章,最后進入第三頁,再抓取所有文章。整個過程都是全自動的。不需要寫任何XPath,也不需要告訴爬蟲哪里是翻頁按鈕,文章的標題在哪里,發(fā)布時間在哪里,正文在哪里。
模塊拆解
代碼我已經放到Github:AutoCrawler[1]。由于最近智譜[2]又免費送了1億的Token,并且超過以后,調用API費用1折起,所以還是使用他們最新的基座大模型GLM-4-Plus來實現(xiàn)這個全自動爬蟲。
代碼分為如下幾個主要文件:
- llm.py: 封裝智譜的大模型,以方便使用。代碼如下圖所示。大家可以根據這個輸入輸出修改成自己常用的大模型。我測試了國產的各家大模型,最后發(fā)現(xiàn)GLM-4-Plus在語言理解,網頁結構解析,指令遵循方面相對最好。
圖片
- utils.py: 常用工具函數(shù),清洗HTML,重試等等
- constants.py: 各種常量,包括各種Prompt
- parser.py: 核心解析邏輯,解析列表頁、詳情頁,識別翻頁按鈕
- main.py:調度邏輯。把各個模塊組合在一起
原理說明
字段解析與翻頁
其中,跟大模型相關的代碼在parser.py中。我們來看一下:
圖片
代碼邏輯很簡單,分為兩個主要的方法,data_extract用來從列表頁提取出詳情頁URL,從詳情頁提取出作者、標題、發(fā)布時間和正文。paging_extract用來提取分頁按鈕中,下一頁對應的鏈接。
這個提取的過程就交給智譜GLM-4-Plus來完成。對于字段提取,對應的System Prompt如下:
你將扮演一個HTML解析器的角色。我將會提供一段HTML代碼,這段代碼可能代表了一個博客網站的文章列表頁或者文章詳情頁。你需要首先判斷這段HTML是屬于哪種類型的頁面。如果是文章詳情頁,那么頁面中通常會包含文章標題、發(fā)布時間、作者以及內容等信息;而如果是列表頁,則會列出多篇文章的標題及其對應的詳情頁鏈接。
請根據以下規(guī)則進行處理:
1. 分析提供的HTML代碼,確定頁面類型(`list` 或 `detail`)。
2. 根據頁面類型,提取必要的信息:
- 如果是列表頁,請找到所有文章條目,并為每個條目提供標題和指向詳情頁的鏈接。
- 如果是詳情頁,請找到文章標題、作者、發(fā)布時間和內容的XPath。確保XPath直接指向包含這些信息的具體元素值,例如使用`@屬性`或者`text()`來獲取確切的文本內容。
3. 盡量使用具有特征性的屬性如`id`或`class`來構造XPath,以確保XPath簡潔且魯棒。
4. 對于標題、作者、發(fā)布時間等字段,如果它們不是直接在某個標簽內,而是嵌套在其他標簽中,XPath應包括這些結構,以保證準確性。
5. 按照指定格式輸出結果。
6. 只需要返回JSON,不要解釋,不要返回無關內容
**輸出格式:**
- 對于列表頁,返回如下JSON結構:
{
"page_type": "list",
"articles": [
{"title": "文章標題", "url": "文章詳情頁URL"},
{"title": "文章標題", "url": "文章詳情頁URL"},
{"title": "文章標題", "url": "文章詳情頁URL"},
// 更多文章...
]
}
- 對于詳情頁,返回如下JSON結構:
{
"page_type": "detail",
"fields": [
{"field_name": "title", "xpath": "XPath to the title"},
{"field_name": "author", "xpath": "XPath to the author"},
{"field_name": "publish_time", "xpath": "XPath to the publish time"},
{"field_name": "content", "xpath": "XPath to the content"}
]
}
現(xiàn)在,請接收以下HTML代碼并開始分析:
可能有同學會疑惑,為什么對于列表頁,是直接讓大模型提取出URL,但對于詳情頁,卻是生成XPath而不直接提取內容呢?原因很簡單,因為現(xiàn)在大模型的Output Token遠遠低于Input Token,并且Output Token更貴?,F(xiàn)在Input Token輕輕松松超過128K,但是Output Token大部分都在4096,只有少數(shù)在8192。對于長文章,把Output Token全部用完了可能都沒法輸出完整的正文。而且輸出的內容越多,費用就越高,速度就越慢。你以為我不想讓大模型直接輸出提取好的內容?
而由于列表頁的內容并不多,標題加上URL用不了多少字,所以就直接輸出了。
獲取翻頁鏈接的System Prompt,如下:
你將扮演一個HTML解析器的角色。我將會提供一段HTML代碼,這段代碼可能代表了一個博客網站的文章列表頁。你需要找到頁面上的翻頁鏈接,并提取出下一頁的URL
請根據以下規(guī)則進行處理:
1. 分析提供的HTML代碼,找到翻頁按鈕。
2. 翻頁按鈕上面的文本可能是『下一頁』、『next』、『>』、『Load more』等,也可能是一個數(shù)字,代表頁碼,也可能是paging標簽或者classname包含pagination的某個標簽。沒有固定的標準,你需要智能識別
3. 返回下一頁的URL,如果沒有下一頁,返回空字符串
4. 按照指定格式輸出結果。
5. 只需要返回JSON,不要解釋,不要返回無關內容
返回JSON格式:
{"page_type": "paging", "url": "下一頁的url"}
這就是常規(guī)的Prompt,沒什么好解釋的。
爬蟲流程調度
我們最后來看看main.py的代碼:
圖片
核心調度邏輯就這么幾行代碼。如果有同學經常刷算法題,應該會對這段代碼很熟悉。這里使用while循環(huán)來實現(xiàn)遞歸操作。
一開始,target里面只有我傳入的起始URL。然后進入while循環(huán),當target隊列為空時結束循環(huán)。在循環(huán)里面,首先解析當前列表頁,獲得當前頁面所有的文章詳情頁URL,全部放入隊列中。再獲得下一頁的URL,也放入隊列中。接下來循環(huán)開始進入第二項,也就是第一篇文章詳情URL,進入里面,獲取源代碼,使用大模型解析出XPath,然后調用self.extract_detail通過lxml執(zhí)行XPath從源代碼中提取出正文。接下來繼續(xù)第二篇文章……如此循環(huán)。
今天我們實現(xiàn)的是最簡單的情況。不考慮反爬蟲。不考慮列表頁滾動下拉的情況。在下一篇文章中,我們會把模擬瀏覽器引入進來。借助于智能全面提升的GLM-4-Plus和GLM-4V-Plus,讓爬蟲能夠自己控制模擬瀏覽器,讓它自動點擊頁面,繞過反爬蟲,自動滾動下拉。
參考資料
[1]AutoCrawler: https://github.com/kingname/AutoCrawler
[2]智譜: https://zhipuaishengchan.datasink.sensorsdata.cn/t/JX
[3] 視頻通話模型內測地址: https://bigmodel.cn/online-book/videocall