多線程異步非阻塞C語言爬蟲


最近用C寫了個爬蟲,純屬練習,離實用還相差甚遠。

下載源碼:ISeeSpider

bloom.h實現布隆過濾器算法。對一條url拆分為domain和path兩部分,bloomDomain函數判斷domain是否出現過,bloomPath函數判斷path是否出現過。如果domain未出現過,則要先進行DNS解析(解析之后把domain和ip對存入map),再下載網頁;如果domain出現過,則不需要再進行DNS解析,此時如果path也出現過,則該url直接忽略;如果是新的url,需要放入queue。

建立好socket connection后向連接寫入http request,然后把sockfd放入epoll中,同時sockfd設為非阻塞式的。當sockfd准備就緒后,就說明可以從sockfd中讀取http response數據(即下載網頁)了。對於每一個下載網頁的任務創建一個分離的子線程去完成。

下載網頁時,一邊下載,一邊抽取超鏈接放入待爬取的url queue。此時對於每一個下載需要單獨創建一個buffer,比如我把buffer的大小設為1K,則每次從sockfd中read時,最多讀取1K的數據。從buffer中提取出所有超鏈接,然后整個buffer左移,把包含所有超鏈接的最短子串移出去。實際上還可以繼續左移,直到一個空格移到buffer的首位置為止,記下此時buffer中還有多少數據(記為left_size)。則下次從sockfd中read時,需要讀取的數據量為1k - left_size。

每次從buffer中讀取了一些url,去除已下載過的url,再去除已存在於map<domain,ip>中的,剩下的需要進行一次DNS異步解析(使用libevent)。libevent是非線程安全的,即event_base不被多個線程share,所以我每次調用libevent時在一個線程中完成event_base和創建和釋放,即一次完整DNS異步解析是在一個線程中就完成的。

每個線程完成下載網頁的工作后,從url_queue中讀出1個或2個url(epoll中的sockfd比較少時就2個,否則就1個),建立sockte connect,發出http request,然后把sockfd加入到主線程的epoll中去,最后子線程退出。

下面給個程序運行時的截圖:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM