欧拉七桥问题
歐拉七橋問題
把一塊連通的陸地作為一個(gè)頂點(diǎn),每一座橋當(dāng)成圖的一條邊,那么就把哥尼斯堡的七座橋抽象成圖中所示
對(duì)于圖中的每一個(gè)頂點(diǎn),將與之相連的邊的數(shù)量定義為它的度(Degree)
定理:如果一個(gè)圖能夠從一個(gè)頂點(diǎn)出發(fā), 每條邊不重復(fù)地遍歷一遍回到這個(gè)頂點(diǎn),那么每一頂點(diǎn)的度必須為偶數(shù)。
證明:假如能夠遍歷圖的每條邊各一次, 那么對(duì)于每個(gè)頂點(diǎn),需要從
某條邊進(jìn)人頂點(diǎn),同時(shí)從另一條邊離開這個(gè)頂點(diǎn)。進(jìn)人和離開頂點(diǎn)的次
數(shù)是相同的,因此每個(gè)頂點(diǎn)有多少條進(jìn)入的邊,就有多少條出去的邊。
也就是說,每個(gè)頂點(diǎn)相連的邊的數(shù)量是成對(duì)出現(xiàn)的,即每個(gè)頂點(diǎn)的度都
是偶數(shù)。
在圖9.5中,有多個(gè)頂點(diǎn)的度為奇數(shù),因此,這個(gè)圖無法從一個(gè)頂點(diǎn)出發(fā),
遍歷每條邊各一次然后回到這個(gè)頂點(diǎn)。
構(gòu)建網(wǎng)絡(luò)爬蟲的工程要點(diǎn)
“如何構(gòu)建一個(gè)網(wǎng)絡(luò)爬蟲”Google常用的一道面試題。
網(wǎng)絡(luò)爬蟲在工程實(shí)現(xiàn)上要考慮的細(xì)節(jié)非常多,其中大的方面有這樣幾點(diǎn)。
首先,用BFS?還是DFS?
雖然從理論上講,這兩個(gè)算法(在不考慮時(shí)間因素的前提下)都能夠在大致相同的時(shí)間里“爬下”整個(gè)“靜態(tài)”互聯(lián)網(wǎng)上的內(nèi)容,但是工程上的兩個(gè)假設(shè)——不考慮時(shí)間因素,互聯(lián)網(wǎng)靜態(tài)不變,都是現(xiàn)實(shí)中做不到的。搜索引擎的網(wǎng)絡(luò)
爬蟲問題更應(yīng)該定義成“如何在有限時(shí)間里最多地爬下最重要的網(wǎng)頁”。顯然各個(gè)網(wǎng)站最重要的網(wǎng)頁應(yīng)該是它的首頁。在最極端的情況下,如果爬蟲非常小,只能下載非常有限的網(wǎng)頁,那么應(yīng)該下載的是所有網(wǎng)站的首頁,如果把爬蟲再擴(kuò)大些,應(yīng)該爬下從首頁直接鏈接的網(wǎng)頁(就如同和北京直接相連的城市),因?yàn)檫@些網(wǎng)頁是網(wǎng)站設(shè)計(jì)者自認(rèn)為相當(dāng)重要的網(wǎng)頁。在這個(gè)前提下,顯然BFS明顯優(yōu)于DFS。事實(shí)上在搜索引擎的爬蟲,雖然不是簡單地采用BFS,但是先爬哪個(gè)網(wǎng)頁,后爬哪個(gè)網(wǎng)頁的調(diào)度程序,原理上基本上是BFS。
那么是否DFS就不使用了呢?也不是這樣的。這跟爬蟲的分布式結(jié)構(gòu)以及網(wǎng)絡(luò)通信的握手成本有關(guān)。所謂“握手”就是指下載服務(wù)器和網(wǎng)站的服務(wù)器建立通信的過程。這個(gè)過程需要額外的時(shí)間(Overhead Time )如果握手的次數(shù)太多,下載的效率就降低了。實(shí)際的網(wǎng)絡(luò)爬蟲都是由成百上千甚至成干上萬臺(tái)服務(wù)器組成的分布式系統(tǒng)。對(duì)于某個(gè)網(wǎng)站,一般是由特定的一 一臺(tái)或者幾臺(tái)服務(wù)器專門下載。 這些服務(wù)器下載完網(wǎng)站,然后再進(jìn)人下一個(gè)網(wǎng)站,而不是每個(gè)網(wǎng)站先輪流下載5%,然后回過頭來下載第二批,這樣可以避免握手的次數(shù)太多。要是下載完第個(gè)網(wǎng)站再下載第二個(gè),那么這又有點(diǎn)像DFS,雖然下載同一個(gè)網(wǎng)站(或者子網(wǎng)站)時(shí),還是需要用BFS的。
總結(jié)起來,網(wǎng)絡(luò)爬蟲對(duì)網(wǎng)頁通歷的次序不是簡單的BFS或者DFS有一個(gè)相對(duì)復(fù)雜的下載優(yōu)先級(jí)排序的方法。管理這個(gè)優(yōu)先級(jí)排用序的子系統(tǒng)般稱為調(diào)度系統(tǒng) (Scheduler),由它來決定當(dāng)一個(gè)網(wǎng)頁下載完成后,接下來下載哪個(gè)當(dāng)然在調(diào)用系統(tǒng)里需要存儲(chǔ)那些已經(jīng)發(fā)現(xiàn)但是尚未下載的網(wǎng)頁的URL,它們一般存在一個(gè)優(yōu)先級(jí)隊(duì)列 ( Priorty Queue)里。而用這種方式遍歷整個(gè)互聯(lián)網(wǎng),在工程上和BFS更相似。因此,在爬蟲中,BFS的成分多一些。
第二,頁面的分析和URL的提取。
在上一部分中提到,當(dāng)一個(gè)網(wǎng)頁下載完成后,需要從這個(gè)網(wǎng)頁中提取其中的URL。把它們加入到下載的隊(duì)列中。這個(gè)工作在互聯(lián)網(wǎng)的早期不難,因?yàn)槟菚r(shí)的網(wǎng)頁都是直接用HTML語言書寫的。那些URL都以文本的形式放在網(wǎng)頁中,前后都有明顯的標(biāo)識(shí),很容易提取出來。但是現(xiàn)在很多URL的提取就不那么直接了,因?yàn)楹芏嗑W(wǎng)頁如今是用一些腳本語言(比如JavaScript) 生成的。打開網(wǎng)頁的源代碼,URL不是直接可見的文本,而是運(yùn)行這一段腳本后才能得到的結(jié)果。因此,網(wǎng)絡(luò)爬蟲的頁面分析就變得復(fù)雜很多,它要模擬瀏覽器運(yùn)行一個(gè)網(wǎng)頁,才能得到里面隱含的URL。有些網(wǎng)頁的腳本寫得非常不規(guī)范,以至于解析起來非常困難。可是,這些網(wǎng)頁還是可以在瀏覽器中打開,說明瀏覽器可以解析。因此,需要做瀏覽器內(nèi)核的工程師來寫網(wǎng)絡(luò)爬蟲中的解析程序,可惜出色的瀏覽器內(nèi)核工程師在全世界數(shù)量并不多。因此,若你發(fā)現(xiàn)些網(wǎng)頁明明存在,但搜索引擎就是沒有收錄,一個(gè)可能的原因是網(wǎng)絡(luò)爬蟲中的解析程序沒能成功解析網(wǎng)頁中不規(guī)范的腳本程序。
第三,記錄哪些網(wǎng)頁已經(jīng)下載過的小本本——URL表。
在互聯(lián)網(wǎng)上,一個(gè)網(wǎng)頁可能被多個(gè)網(wǎng)頁中的超鏈接所指向,即在互聯(lián)網(wǎng)這張大圖上,有很多弧(鏈接)可以走到這個(gè)節(jié)點(diǎn)(網(wǎng)頁)。這樣在遍歷互聯(lián)網(wǎng)這張圖時(shí),這個(gè)網(wǎng)頁可能被多次訪問到。為了防止一個(gè)網(wǎng)頁被下載多次,我們可以用個(gè)哈希表記錄哪些網(wǎng)頁已經(jīng)下載過。再遇到這我們就可以跳過它。采用哈希表的好處是,判斷一個(gè)網(wǎng)頁的URL是否在表中,平均只需一次(或者略多的)查找。當(dāng)然。如果遇到還未下載的網(wǎng)頁。除了下載該網(wǎng)頁,還要適時(shí)將這個(gè)網(wǎng)頁的URL存入哈希表中,這個(gè)操作對(duì)哈希表來講也非常簡單。在一臺(tái)下載服務(wù)器上建立和維護(hù)一張哈希表并不是難事。但是如果同時(shí)有上千臺(tái)服務(wù)器一起下載網(wǎng)頁。維護(hù)一張統(tǒng)一的哈希表就不那么簡單了。 首先,這張哈希表會(huì)大到一臺(tái)服務(wù)器存儲(chǔ)不下。其次,由于每個(gè)下載服務(wù)器在開始下載前和完成下載后都要訪問和維護(hù)這張表,以免不同的服務(wù)器做重復(fù)的工作,這
個(gè)存儲(chǔ)哈希表的服務(wù)器的通信就成了整個(gè)爬蟲系統(tǒng)的瓶頸。
這里有各種解決辦法,沒有絕對(duì)正確的,但是卻也有好壞之分。好的方法都采用了這樣兩個(gè)技術(shù): 首先明確每臺(tái)下載服務(wù)器的分工,也就是說在調(diào)度時(shí)一看到某個(gè)URL就知道要交給哪臺(tái)服務(wù)器去下載,以免很多服務(wù)器都要重重復(fù)判斷某個(gè)URL是否需要下載。然后,在明確分工的基礎(chǔ)上,判斷URL是否下載就可以批處理了,比如每次向哈希表(一組獨(dú)立的服務(wù)器)發(fā)送一大批詢問, 或者每次更新一批哈希表的內(nèi)容。 這樣通信的次數(shù)就大大減少了。
轉(zhuǎn)載于:《數(shù)學(xué)之美》
總結(jié)
- 上一篇: QuickCHM V2.6注册码
- 下一篇: 高斯定理在神经网络上的投影