【正文】
ore being fetched URLs int pending = 0。 pthread_attr_destroy(amp。pAttr)。 該函數(shù)用來設定線程 id 為 tid 的線程是可脫離的,確切地說,當 tid 終止時,所有相關資源自動釋放,主線程并不用等待它結束。 參數(shù): tid 為線程 id。ev)。 = EPOLLIN | EPOLLOUT | EPOLLET。使用非阻塞 I/O 模型的好處在于可以進一步提高進程中讀寫的并發(fā)性,進而提高程序運行效率。 int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout); 該函數(shù)用于輪詢 I/O 事件的發(fā)生。在使用完 epoll 后,必須調用 close()關閉。 opts |= O_NONBLOCK。 參數(shù): hostname 為用戶指定的域名。常見的用戶代理 (User Agent)有 Mozilla/,廣東石油化工學院本科畢業(yè) (設計 )論文 : Linux 平臺下 C/C++網(wǎng)絡爬蟲的設計與實現(xiàn) 20 Opera/ 等。 string request = GET /+ () + HTTP/\r\nHost: + () + \r\nUserAgent: + Uagent + \r\nAccept: + Accept + \r\nConnection: + Conn + \r\n\r\n。 } ( 3) write(), read() 函數(shù) 本文使用這兩個函數(shù)來讀寫套接字操作, read 函數(shù)從參數(shù) fd 讀取內容放到參數(shù) buf第四章 網(wǎng)絡爬蟲模 型的設計與實現(xiàn) 19 中;相反, write 函數(shù)把參數(shù) buf 的內容寫入到參數(shù) fd 中。server_addr, sizeof(server_addr))。 protocol 指明某個協(xié)議類型,常設為 0。 客 戶 端服 務 器S o c k e C o n n e c t ( 阻 塞 )( 主 動 打 開 )S Y N JS Y N K , A C K J + 1S o c k e t , b i n d , l i s t en( 被 動 打 開 )A c c e p t ( 阻 塞 )A C K K + 1C o n n e c t 返回A c c e p t 返 回R e a d ( 阻 塞 )C l o s e( 主 動 關 閉 )F I N M( 被 動 關 閉 )R e a d 返 回 0C l o s eA C K M + 1F I N NA C K N + 1 圖 41 TCP 三次握手與兩次半關閉過程 在了解各個 Socket 函數(shù)之前,首先來看一個經(jīng)典的流程圖,幾乎每次網(wǎng)絡通信都需要走 以下流程,它詳細地顯示了 TCP 客戶端和 TCP 服務器之間的 Socket 通信流程: 第四章 網(wǎng)絡爬蟲模 型的設計與實現(xiàn) 17 S o c k e t ( )T C P 客 戶 端C o n n e c t ( )W r i t e ( )R e a d ( )C l o s e ( )S o c k e t ( )L i s t e n ( )B i n d ( )A c c e p t ( )R e a d ( )W r i t e ( )R e a d ( )C l o s e ( )T C P 服 務 器一 直 阻 塞 到 客 戶連 接 到 達處 理 請 求連 接 建 立( T C P 三 路 握 手 )數(shù) 據(jù) ( 請 求 )數(shù) 據(jù) ( 應 答 )文 件 結 束 通 知眾 所 周 知 的 端 口 圖 42 基于 TCP 客戶 /服務器程序的套接字函數(shù)及通信流程 在程序中,每一個 URL 對應的網(wǎng)頁,在客戶端都需要完成 Socket(), Connect(),Write(), Read(), Close()這一過程。 第一行代碼使用 O_CREAT | O_EXCL | O_RDWR 模式打開,當該文件已經(jīng)存在時返回 1,錯誤代碼存放在 error 中,錯誤代號為 EEXIST。 if(fd 0) { perror(file open error)。那么接下來要做的事就是把它保存到磁盤里,在這一步需要用到文件操作(摘自 )。 ( 3) URL 判重 抓取網(wǎng)頁時有一個非常棘手的問題,那就是重復抓取問題。第一種: URL 用雙引號引起來;第二種:以單引號引起來;第三種: URL 沒有被引起來。 ( 4)若 URL 沒有主機屬性,則默認 Host 成員的值為初始 URL 的主機名。 string Fname。 file) { File = file。 網(wǎng)絡爬蟲的具體設計 URL 類設計及標準化 URL URL 的一般形式是 : URL 的訪問方式 ://主機 :端口 /路徑 。 本網(wǎng)絡爬蟲最終將設 計成一個能夠自動讀寫配置文件并且在后臺自動執(zhí)行的網(wǎng)絡第三章 網(wǎng)絡爬蟲模型的分析和概要設計 爬蟲程序。如果新結點是目標結點,則搜索成功,程序結束;若新結點不是目標結點,則回到第( 1)步,再從隊列頭取出結點進行擴展。 結點的擴展規(guī)則也就是如何從現(xiàn)有的結點生成新結點。不同的問題需要用不同的數(shù)據(jù)結構描述。如圖 所示。當然,它并不僅僅為程序員而生。通常來講,一個 Linux 發(fā)布版包括 Linux 內核,將整個軟件安裝到計算機上的一套安裝工具,各種 GNU 軟件,其他的一些自由軟件,在一些特定的 Linux 發(fā)布版中也有一些專有軟件。這些方法的缺點在于,隨著抓取網(wǎng)頁的增多 ,大量的無關網(wǎng)頁將被下載并過濾,算法的效率將變低。 網(wǎng)頁搜索策略介紹 網(wǎng)頁的抓取策略可以分為深度優(yōu)先、廣度優(yōu)先和最佳優(yōu)先三種。 ( 6)總結和展望。并以此引出網(wǎng)絡爬蟲系統(tǒng)的相關知識介紹。不同的搜索引擎,會根據(jù)對搜索結果的不同需求,選擇最合適的爬行策略來搜集互聯(lián)網(wǎng)上的信息。 搜索引擎的發(fā)展面臨著兩大難題:一是如何跟上 Inter 的發(fā)展速度,二是如何為用戶提供更精確的查詢結果。 ( 2)客戶端:很適合部署定題爬蟲,或者叫聚焦爬蟲。目前,互聯(lián)網(wǎng)上有名有姓的搜索引擎已達數(shù)百家,其檢索的信息量也與從前不可同日而語。 隨著互 聯(lián)網(wǎng)的迅速發(fā)展,使得檢索所有新出現(xiàn)的網(wǎng)頁變得越來越困難,因此,在Matthew Gray 的 Wanderer 基礎上,一些編程者將傳統(tǒng)的 ―蜘蛛 ‖程序工作原理作了些改進。由于 Archie 深受用戶歡迎,受其啟發(fā),美國內華達 System Computing Services 大學于 1993 年開發(fā)了另一個與之非常相似的搜索工具,不過此時的搜索工具除了索引文件外,已能檢索網(wǎng)頁。另外一些不常使用的名字還有螞蟻,自動索引,模擬程序或者蠕蟲。 把互聯(lián)網(wǎng)比喻成一個蜘蛛網(wǎng),那么 Spider 就是在網(wǎng)上爬來爬去的蜘蛛。網(wǎng)絡蜘蛛是通過網(wǎng)頁的鏈接地址來尋找 網(wǎng)頁,從網(wǎng)站某一個頁面(通常是首頁)開始,讀取網(wǎng)頁的內容,找到在網(wǎng)頁中的其它鏈接地址,然后通過這些鏈接地址尋找下一個網(wǎng)頁,這樣一直循環(huán)下去,直到把這個網(wǎng)站所有的網(wǎng)頁都抓取完為止。 網(wǎng)絡檢索功能起于互聯(lián)網(wǎng)內容爆炸性發(fā)展所帶來的對內容檢索的需求。 當時, ―機器人 ‖一詞在編程者中十分流行。其設想是,既然所有網(wǎng)頁都可能有連向其他網(wǎng)站的鏈接,那么從跟蹤一個網(wǎng)站的鏈接開始,就有可能檢索整個互聯(lián)網(wǎng)。比如最近風頭正勁的 Google,其數(shù)據(jù)庫中存放的網(wǎng)頁已達 30 億之巨。做一個與 Google,百度等競爭的綜合搜索引擎成功的機會微乎其微,而垂直搜索或者比價服務或者推薦引擎,機會要多得多,這類爬蟲不是什么頁面都取的,而是只取關心的頁面,而且只取頁面上關心的內容,例如提取黃頁信息,商品價格信息,還有提取競爭對手 廣告信息的。所以,傳統(tǒng)的引擎不能適應信息 技術的高速發(fā)展,新一代智能搜索引擎作為一種高效搜索引擎技術的在當今的網(wǎng)絡信息時代日益引起業(yè) 界人士的關注。高效,優(yōu)秀的爬蟲程序可以使人們在互聯(lián)網(wǎng)上尋找到更及時,更準確的信息。 ( 3)網(wǎng)絡爬蟲的模型分析 。 第二章 相關技術和工具綜述 5 第二章 相關技術和工具綜述 網(wǎng)絡爬蟲的定義 定義 1:網(wǎng)絡爬蟲是一個自動提取網(wǎng)頁的程序,它為搜索引擎從 Web 上下載網(wǎng)頁,是搜索引擎的重要組成部分。深度優(yōu)先在很多情況下會導致爬蟲的陷入( trapped)問題,目前常見的是廣度優(yōu)先和最佳優(yōu)先方法。 廣東石油化工學院本科畢業(yè) (設計 )論文 : Linux 平臺下 C/C++網(wǎng)絡爬蟲的設計與實現(xiàn) 6 相關工具介紹 操作系統(tǒng) 本網(wǎng)絡爬蟲程序開發(fā)環(huán)境為 Linux CentOS 操作系統(tǒng),并且目標是在 Linux 下運行,而在其他平臺上會出現(xiàn)各種無法正常運行的問題,所以在此有必要介紹一下該程序的運行環(huán)境, Linux 操作系統(tǒng)。發(fā)布版為許多不同的目的而制作,包括對不同計算機硬件結構的支持,對一個具體區(qū) 域或語言的本地化,實時應用,和嵌入式系統(tǒng)。面對各種文本編輯,無論是撰寫 還是編輯配置文件, Vim 都臻于完美。 Q U E U E _ U R LP u s hQ U E U E _ U R L 為 空 / 其它 終 止 條 件P o p退 出Y e s抓 取 指 定 網(wǎng) 頁N o網(wǎng) 頁 分 析提 取 U R LA n a l y z eY e sS t o r e初 始 U R L存 儲 H t m l符 合 條 件 ( 不 重 復/ 包 含 關 鍵 字 )丟 棄N o 圖 31 網(wǎng)絡爬蟲的基本框架圖 首先建立 URL 任務列表隊列,即開始要爬取的 URL。 ( 2)確定結點的擴展規(guī)則 根據(jù)問題所給定的條件,從一個結點出發(fā),可以生成一個或多個新的結點,這個過程通常稱為擴展。對不同的問題,結點的擴展規(guī)則也不相同,需要按照問題的要求確定。 最終可能產(chǎn)生兩種結果:找到目標結點,或擴展完所有結點而沒有找到目標結點。網(wǎng)絡爬蟲工作流程圖如圖 34 所示。為了方便處理,設計了一個名叫 URL 的類,它包含 Host(主機名), Port(端口), File(文件路徑),F(xiàn)name(給這張網(wǎng)頁取的名字)。 } 第四章 網(wǎng)絡爬蟲模 型的設計與實現(xiàn) 13 string GetFile() { return File。 }。 爬取網(wǎng)頁 在分析網(wǎng)頁之前,首先網(wǎng)頁需要被抓取下來,分析一下數(shù)據(jù)從服務器保存到本地的過程。在此使用了一個標記變量( flag)來區(qū)分以上三種情況。大家知道,一個網(wǎng)站中的鏈 接非常多,抽象出來就是一個巨大的蜘蛛網(wǎng),類似與圖論中的無向圖。 chdir(Pages)。 goto NEXT。 廣東石油化工學院本科畢業(yè) (設計 )論文 : Linux 平臺下 C/C++網(wǎng)絡爬蟲的設計與實現(xiàn) 16 代碼中使用 stat 函數(shù)來讀取參數(shù)為文件名的文件信息,其中我們需要的就是 st_size這個成員的內容,它以字節(jié)形式記錄了文件的大小。要注意的是,如果不及時關閉 Socket 文件描述符,有時會出現(xiàn) ―open too many files‖的系統(tǒng)錯誤,這是由于系統(tǒng)對用戶同時打開多個文件的限制(這里的文件不僅僅指通常意義上的文件, Linux 會把任何東西都當做文 件,包括目錄、各類描述符等)。 例(摘自 ): if((sockfd = socket(PF_INET, SOCK_STREAM, 0)) == 1) { return 1。 = AF_INET。 include ssize_t read(int fd, void * buf , size_t count)。 int d, total = (), send = 0。其中需要注意格式的要求,比如空格,回車換行等,最后四個字符(兩個回車,兩個換行)表示命令的結束。 返回: 成功返回非空指針,反之則為 NULL。 // set nonblocking if (ftl(sockfd, F_SETFL, opts) 0) return 1。 int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)。 返回: 返回需要處理的事件數(shù)目,如返回 0 表示超時。 程序框架如下(摘自 ,參考 blogs): epfd = epoll_create(50)。 廣東石油化工學院本科畢業(yè) (設計 )論文 : Linux 平臺下 C/C++網(wǎng)絡爬蟲的設計與實現(xiàn) 22 if(epoll_ctl(epfd, EPOLL_CTL_ADD, sockfd, amp。 perror(epoll_ctl_del)。 attr 為線程屬性。在本程序中,并沒有調用此函數(shù),而是在線程屬性的設置中把線程設定為可脫離的。 pthread_attr_set