2012年3月6日 星期二

Web-Harvest 挖掘需要的數據


首先,在官方網站下載web-harvest,目前最新版本是1.0,下載頁面分三個下載包,分別是webharvest1-ex​​e.zip,webharvest1-bin.zip,webharvest1-project.zip,他們沒實質區別,第一個是包含了全部第三方包(一起打入了同一個jar文件直接可運行),第二個做為一個中間件出現,附帶了所有獨立的第三方jar包,第三個則是源碼,當然要最大的靈活性自然選擇下載源碼了:》

下載下來後再eclipse建立一個空項目,把所有解壓出來的文件夾仍進去,然後把src和config設為source folder (源碼目錄) 然後看到default包下面有個Test.java的文件,下面我們來看看這個文件:

        ScraperConfiguration config = new ScraperConfiguration("c:/temp/scrapertest/dddd.xml");
        Scraper scraper = new Scraper(config, "c:/temp/scrapertest/");
        scraper.setDebug(true);
        long startTime = System.currentTimeMillis();
        scraper.execute();
        System.out.println("time elapsed: " + (System.currentTimeMillis() - startTime));

除去log4j的註解外,剩下的就是這幾行代碼啦,我們看到運行挖掘任務只需要3行代碼,創建config,用config和挖取到數據存儲目錄做參數創建Scraper,然後執行就OK。

好了,先試試,它能不能工作,在剛才解壓出來的文件中,有一個examples文件夾下面有很多,配置文件可以先試試手,首先,看看圖片挖取的例子google_images.xml ,更改上面的兩行代碼

        ScraperConfiguration config = new ScraperConfiguration("E:/workspace/webharvest/examples/google_images.xml");

        Scraper scraper = new Scraper(config, " E:/workspace/webharvest/examples/");

然後運行這個Test在console窗口會看到抓取過程,完成後再E:\workspace\webharvest\examples\google_images目錄下就能看到剛才抓取到的所有圖片了,抓取非常簡單,到此為止,我們看看他的配置文件,google_images.xml到底有什麼魔法。

在google_images.xml中,這個配置文件中首先引用了一個functions.xml,在google_images.xml同級目錄下,我們先看看這個文件。這個文件中定義了一個function(函數)名字是download-multipage-list雖然不符合java函數定義規則,但是這裡只是一個函數名,函數return了一個循環出來的結果集,empty標記表示其中的執行結果不包含在返回結果集內,那麼主要返回的就是:
                <xpath expression="${itemXPath}">
                    <var name="content"/>
                </xpath>
這段了,這段代碼表示,用xpath方式(解析規則是expression表達式決定的)解析引用的content內容,做為一個行記錄(這個行記錄會被默認封裝成一個List(不是普通的list而是:org.webharvest.runtime.variables.ListVariable);

循環的主體主要實現讀取數頁(多少頁由$maxloops變量決定)的數據.


現在看看empty內部的功能:

首先
<var-def name="content">
    <html-to-xml>
        <http url="${pageUrl}"/>
    </html-to-xml>
</var-def>
是定義一個content變量,內容是訪問${pageUrl}頁面內容。

接著:
<var-def name="nextLinkUrl">
    <xpath expression="${nextXPath}">
        <var name="content"/>
    </xpath>
</var-def>

是用xpath表達式(${nextXPath})取content變量內部的值(也就是剛才${pageUrl}頁面解析)得到下一頁的URL地址。

<var-def name="pageUrl">
      <template>${sys.fullUrl(pageUrl.toString(), nextLinkUrl.toString())}</template>
</var-def>

對pageUrl重新賦值,將下一頁賦值給pageUrl下次循環讀下一頁數據解析。

好了這個函數簡單的說就是用來分頁取數據的。

回到google-images.xml文件我們繼續看:

      <!-​​- defines search keyword and start URL -->
      <var-def name="search" overwrite="false">platon</var-def>
      <var-def name="url">
            <xpath expression="//noscript//a/@href[1]">
                  <html-to-xml>
                   <http url="http://images.google.com/images?q=${search}&amp;hl=en&amp;btnG=Search+Images"/>
                  </html-to-xml>
            </xpath>
    </var-def>

很簡單,定義一個變量做搜索條件給url中,然後用html-to-xml標記把http標記訪問url的頁面html內容轉換為xml,最後用xpath一個表達式得到頁面真實的url(看來google確實比較麻煩,其他網站可以直接得到url的)。

      <!-​​- collects all image URLs -->
      <var-def name="imgLinks">
        <call name="d​​ownload-multipage-list">
            <call-param name="pageUrl"><var name="url"/></call-param>
            <call-param name="nextXPath">//td[.='Next']/a/@href</call-param>
            <call-param name="itemXPath">//img[contains(@src, 'images?q=tbn')]/@src</call-param>
            <call-param name="maxloops">5</call-param>
        </call>
      </var-def>
    這段的功能就是調用分頁函數,把itemXPath參數中的xpath表達式內容,限定解析的頁面內容封裝成一個list啦

首先定義了4個參數,然後調用functions定義的download-multipage-list函數,最後將返回值賦給imgLinks(這就完成了圖片url的抓取工作了)。

    <!-​​- download images and saves them to the files -->
    <loop item="link" index="i" filter="unique">
        <list>
            <var name="imgLinks"/>
        </list>
        <body>
            <file action="write" type="binary" path="google_images/${search}_${i}.gif">
                <http url="${sys.fullUrl(url, link)}"/>
            </file>
        </body>
    </loop>

雖然已經完成了抓取過程,但是圖片還沒有保存在本地呢,這裡我們就要循環調用file標籤,來把url中的圖片逐一保存在本地啦。
這裡很簡單,需要注意的就是loop循環,比較不同的是loop必須包含一個list和body,會把list逐一迭代出來,body代碼中有句sys.fullUrl函數,是用來處理抓到的相對地址修正為完整的http開頭的絕對地址,參數url是前面我們定義的,link是loop循環體變量在循環裡面定義的。

看完了這個我們做個我們看到只要用xpath表達式,對任何頁面的相對位置抓取都不是問題了。

Web-harvest已經解決了大部分問題,我們要做的就是寫配置文件了。

沒有留言:

張貼留言