網路爬蟲技術學習概覽初步《一》
1、爬蟲技術概述
網路爬蟲(Web crawler),是一種按照一定的規則,自動地抓取全球資訊網資訊的程式或者指令碼,它們被廣泛用於網際網路搜尋引擎或其他類似網站,可以自動採集所有其能夠訪問到的頁面內容,以獲取或更新這些網站的內容和檢索方式。從功能上來講,爬蟲一般分為資料採集,處理,儲存三個部分。傳統爬蟲從一個或若干初始網頁的URL開始,獲得初始網頁上的URL,在抓取網頁的過程中,不斷從當前頁面上抽取新的URL放入佇列,直到滿足系統的一定停止條件。聚焦爬蟲的工作流程較為複雜,需要根據一定的網頁分析演算法過濾與主題無關的連結,保留有用的連結並將其放入等待抓取的URL佇列。然後,它將根據一定的搜尋策略從佇列中選擇下一步要抓取的網頁URL,並重覆上述過程,直到達到系統的某一條件時停止。另外,所有被爬蟲抓取的網頁將會被系統存貯,進行一定的分析、過濾,並建立索引,以便之後的查詢和檢索;對於聚焦爬蟲來說,這一過程所得到的分析結果還可能對以後的抓取過程給出反饋和指導。
相對於通用網路爬蟲,聚焦爬蟲還需要解決三個主要問題:
(1) 對抓取目標的描述或定義;
(2) 對網頁或資料的分析與過濾;
(3) 對URL的搜尋策略。
2、爬蟲原理
2.1 網路爬蟲原理
Web網路爬蟲系統的功能是下載網頁資料,為搜尋引擎系統提供資料來源。很多大型的網路搜尋引擎系統都被稱為基於 Web資料採集的搜尋引擎系統,比如 Google、Baidu。由此可見Web 網路爬蟲系統在搜尋引擎中的重要性。網頁中除了包含供使用者閱讀的文字資訊外,還包含一些超連結資訊。Web網路爬蟲系統正是通過網頁中的超連線資訊不斷獲得網路上的其它網頁。正是因為這種採集過程像一個爬蟲或者蜘蛛在網路上漫遊,所以它才被稱為網路爬蟲系統或者網路蜘蛛系統,在英文中稱為Spider或者Crawler。
2.2 網路爬蟲系統的工作原理
在網路爬蟲的系統框架中,主過程由控制器,解析器,資源庫三部分組成。控制器的主要工作是負責給多執行緒中的各個爬蟲執行緒分配工作任務。解析器的主要工作是下載網頁,進行頁面的處理,主要是將一些JS指令碼標籤、CSS程式碼內容、空格字元、HTML標籤等內容處理掉,爬蟲的基本工作是由解析器完成。資源庫是用來存放下載到的網頁資源,一般都採用大型的資料庫儲存,如Oracle資料庫,並對其建立索引。
控制器
控制器是網路爬蟲的中央控制器,它主要是負責根據系統傳過來的URL連結,分配一執行緒,然後啟動執行緒呼叫爬蟲爬取網頁的過程。
解析器
解析器是負責網路爬蟲的主要部分,其負責的工作主要有:下載網頁的功能,對網頁的文字進行處理,如過濾功能,抽取特殊HTML標籤的功能,分析資料功能。
資源庫
主要是用來儲存網頁中下載下來的資料記錄的容器,並提供生成索引的目標源。中大型的資料庫產品有:Oracle、Sql Server等。
Web網路爬蟲系統一般會選擇一些比較重要的、出度(網頁中鏈出超連結數)較大的網站的URL作為種子URL集合。網路爬蟲系統以這些種子集合作為初始URL,開始資料的抓取。因為網頁中含有連結資訊,通過已有網頁的 URL會得到一些新的 URL,可以把網頁之間的指向結構視為一個森林,每個種子URL對應的網頁是森林中的一棵樹的根節點。這樣,Web網路爬蟲系統就可以根據廣度優先演算法或者深度優先演算法遍歷所有的網頁。由於深度優先搜尋演算法可能會使爬蟲系統陷入一個網站內部,不利於搜尋比較靠近網站首頁的網頁資訊,因此一般採用廣度優先搜尋演算法採集網頁。Web網路爬蟲系統首先將種子URL放入下載佇列,然後簡單地從隊首取出一個URL下載其對應的網頁。得到網頁的內容將其儲存後,再經過解析網頁中的連結資訊可以得到一些新的URL,將這些URL加入下載佇列。然後再取出一個URL,對其對應的網頁進行下載,然後再解析,如此反覆進行,直到遍歷了整個網路或者滿足某種條件後才會停止下來。
網路爬蟲的基本工作流程如下:
1.首先選取一部分精心挑選的種子URL;
2.將這些URL放入待抓取URL佇列;
3.從待抓取URL佇列中取出待抓取在URL,解析DNS,並且得到主機的ip,並將URL對應的網頁下載下來,儲存進已下載網頁庫中。此外,將這些URL放進已抓取URL佇列。
4.分析已抓取URL佇列中的URL,分析其中的其他URL,並且將URL放入待抓取URL佇列,從而進入下一個迴圈。
2.3 抓取策略
在爬蟲系統中,待抓取URL佇列是很重要的一部分。待抓取URL佇列中的URL以什麼樣的順序排列也是一個很重要的問題,因為這涉及到先抓取那個頁面,後抓取哪個頁面。而決定這些URL排列順序的方法,叫做抓取策略。下面重點介紹幾種常見的抓取策略:
2.3.1深度優先遍歷策略
深度優先遍歷策略是指網路爬蟲會從起始頁開始,一個連結一個連結跟蹤下去,處理完這條線路之後再轉入下一個起始頁,繼續跟蹤連結。我們以下面的圖為例:
遍歷的路徑:A-F-G E-H-I B C D
2.3.2寬度優先遍歷策略
寬度優先遍歷策略的基本思路是,將新下載網頁中發現的連結直接插入待抓取URL佇列的末尾。也就是指網路爬蟲會先抓取起始網頁中連結的所有網頁,然後再選擇其中的一個連結網頁,繼續抓取在此網頁中連結的所有網頁。還是以上面的圖為例:
遍歷路徑:A-B-C-D-E-F G H I
2.3.3反向連結數策略
反向連結數是指一個網頁被其他網頁連結指向的數量。反向連結數表示的是一個網頁的內容受到其他人的推薦的程度。因此,很多時候搜尋引擎的抓取系統會使用這個指標來評價網頁的重要程度,從而決定不同網頁的抓取先後順序。
在真實的網路環境中,由於廣告連結、作弊連結的存在,反向連結數不能完全等他我那個也的重要程度。因此,搜尋引擎往往考慮一些可靠的反向連結數。
2.3.4Partial PageRank策略
Partial PageRank演算法借鑑了PageRank演算法的思想:對於已經下載的網頁,連同待抓取URL佇列中的URL,形成網頁集合,計算每個頁面的PageRank值,計算完之後,將待抓取URL佇列中的URL按照PageRank值的大小排列,並按照該順序抓取頁面。
如果每次抓取一個頁面,就重新計算PageRank值,一種折中方案是:每抓取K個頁面後,重新計算一次PageRank值。但是這種情況還會有一個問題:對於已經下載下來的頁面中分析出的連結,也就是我們之前提到的未知網頁那一部分,暫時是沒有PageRank值的。為了解決這個問題,會給這些頁面一個臨時的PageRank值:將這個網頁所有入鏈傳遞進來的PageRank值進行彙總,這樣就形成了該未知頁面的PageRank值,從而參與排序。下面舉例說明:
2.3.5OPIC策略策略
該演算法實際上也是對頁面進行一個重要性打分。在演算法開始前,給所有頁面一個相同的初始現金(cash)。當下載了某個頁面P之後,將P的現金分攤給所有從P中分析出的連結,並且將P的現金清空。對於待抓取URL佇列中的所有頁面按照現金數進行排序。
2.3.6大站優先策略
對於待抓取URL佇列中的所有網頁,根據所屬的網站進行分類。對於待下載頁面數多的網站,優先下載。這個策略也因此叫做大站優先策略。
3、爬蟲分類
開發網路爬蟲應該選擇Nutch、Crawler4j、WebMagic、scrapy、WebCollector還是其他的?上面說的爬蟲,基本可以分3類:
(1)分散式爬蟲:Nutch
(2)JAVA爬蟲:Crawler4j、WebMagic、WebCollector
(3)非JAVA爬蟲:scrapy(基於Python語言開發)
3.1 分散式爬蟲
爬蟲使用分散式,主要是解決兩個問題:
1)海量URL管理
2)網速
現在比較流行的分散式爬蟲,是Apache的Nutch。但是對於大多數使用者來說,Nutch是這幾類爬蟲裡,最不好的選擇,理由如下:
1)Nutch是為搜尋引擎設計的爬蟲,大多數使用者是需要一個做精準資料爬取(精抽取)的爬蟲。Nutch執行的一套流程裡,有三分之二是為了搜尋引擎而設計的。對精抽取沒有太大的意義。也就是說,用Nutch做資料抽取,會浪費很多的時間在不必要的計算上。而且如果你試圖通過對Nutch進行二次開發,來使得它適用於精抽取的業務,基本上就要破壞Nutch的框架,把Nutch改的面目全非,有修改Nutch的能力,真的不如自己重新寫一個分散式爬蟲框架了。
2)Nutch依賴hadoop執行,hadoop本身會消耗很多的時間。如果叢集機器數量較少,爬取速度反而不如單機爬蟲快。
3)Nutch雖然有一套外掛機制,而且作為亮點宣傳。可以看到一些開源的Nutch外掛,提供精抽取的功能。但是開發過Nutch外掛的人都知道,Nutch的外掛系統有多蹩腳。利用反射的機制來載入和呼叫外掛,使得程式的編寫和除錯都變得異常困難,更別說在上面開發一套複雜的精抽取系統了。而且Nutch並沒有為精抽取提供相應的外掛掛載點。Nutch的外掛有隻有五六個掛載點,而這五六個掛載點都是為了搜尋引擎服務的,並沒有為精抽取提供掛載點。大多數Nutch的精抽取外掛,都是掛載在“頁面解析”(parser)這個掛載點的,這個掛載點其實是為了解析連結(為後續爬取提供URL),以及為搜尋引擎提供一些易抽取的網頁資訊(網頁的meta資訊、text文字)。
4)用Nutch進行爬蟲的二次開發,爬蟲的編寫和除錯所需的時間,往往是單機爬蟲所需的十倍時間不止。瞭解Nutch原始碼的學習成本很高,何況是要讓一個團隊的人都讀懂Nutch原始碼。除錯過程中會出現除程式本身之外的各種問題(hadoop的問題、hbase的問題)。
5)很多人說Nutch2有gora,可以持久化資料到avro檔案、hbase、mysql等。很多人其實理解錯了,這裡說的持久化資料,是指將URL資訊(URL管理所需要的資料)存放到avro、hbase、mysql。並不是你要抽取的結構化資料。其實對大多數人來說,URL資訊存在哪裡無所謂。
6)Nutch2的版本目前並不適合開發。官方現在穩定的Nutch版本是nutch2.2.1,但是這個版本綁定了gora-0.3。如果想用hbase配合nutch(大多數人用nutch2就是為了用hbase),只能使用0.90版本左右的hbase,相應的就要將hadoop版本降到hadoop 0.2左右。而且nutch2的官方教程比較有誤導作用,Nutch2的教程有兩個,分別是Nutch1.x和Nutch2.x,這個Nutch2.x官網上寫的是可以支援到hbase 0.94。但是實際上,這個Nutch2.x的意思是Nutch2.3之前、Nutch2.2.1之後的一個版本,這個版本在官方的SVN中不斷更新。而且非常不穩定(一直在修改)。
所以,如果你不是要做搜尋引擎,儘量不要選擇Nutch作為爬蟲。有些團隊就喜歡跟風,非要選擇Nutch來開發精抽取的爬蟲,其實是衝著Nutch的名氣(Nutch作者是Doug Cutting),當然最後的結果往往是專案延期完成。
如果你是要做搜尋引擎,Nutch1.x是一個非常好的選擇。Nutch1.x和solr或者es配合,就可以構成一套非常強大的搜尋引擎了。如果非要用Nutch2的話,建議等到Nutch2.3釋出再看。目前的Nutch2是一個非常不穩定的版本。
分散式爬蟲平臺架構圖
3.2 JAVA爬蟲
這裡把JAVA爬蟲單獨分為一類,是因為JAVA在網路爬蟲這塊的生態圈是非常完善的。相關的資料也是最全的。這裡可能有爭議,我只是隨便談談。
其實開源網路爬蟲(框架)的開發非常簡單,難問題和複雜的問題都被以前的人解決了(比如DOM樹解析和定位、字符集檢測、海量URL去重),可以說是毫無技術含量。包括Nutch,其實Nutch的技術難點是開發hadoop,本身程式碼非常簡單。網路爬蟲從某種意義來說,類似遍歷本機的檔案,查詢檔案中的資訊。沒有任何難度可言。之所以選擇開源爬蟲框架,就是為了省事。比如爬蟲的URL管理、執行緒池之類的模組,誰都能做,但是要做穩定也是需要一段時間的除錯和修改的。
對於爬蟲的功能來說。使用者比較關心的問題往往是:
1)爬蟲支援多執行緒麼、爬蟲能用代理麼、爬蟲會爬取重複資料麼、爬蟲能爬取JS生成的資訊麼?
不支援多執行緒、不支援代理、不能過濾重複URL的,那都不叫開源爬蟲,那叫迴圈執行http請求。
能不能爬js生成的資訊和爬蟲本身沒有太大關係。爬蟲主要是負責遍歷網站和下載頁面。爬js生成的資訊和網頁資訊抽取模組有關,往往需要通過模擬瀏覽器(htmlunit,selenium)來完成。這些模擬瀏覽器,往往需要耗費很多的時間來處理一個頁面。所以一種策略就是,使用這些爬蟲來遍歷網站,遇到需要解析的頁面,就將網頁的相關資訊提交給模擬瀏覽器,來完成JS生成資訊的抽取。
2)爬蟲可以爬取ajax資訊麼?
網頁上有一些非同步載入的資料,爬取這些資料有兩種方法:使用模擬瀏覽器(問題1中描述過了),或者分析ajax的http請求,自己生成ajax請求的url,獲取返回的資料。如果是自己生成ajax請求,使用開源爬蟲的意義在哪裡?其實是要用開源爬蟲的執行緒池和URL管理功能(比如斷點爬取)。
如果我已經可以生成我所需要的ajax請求(列表),如何用這些爬蟲來對這些請求進行爬取?
爬蟲往往都是設計成廣度遍歷或者深度遍歷的模式,去遍歷靜態或者動態頁面。爬取ajax資訊屬於deep web(深網)的範疇,雖然大多數爬蟲都不直接支援。但是也可以通過一些方法來完成。比如WebCollector使用廣度遍歷來遍歷網站。爬蟲的第一輪爬取就是爬取種子集合(seeds)中的所有url。簡單來說,就是將生成的ajax請求作為種子,放入爬蟲。用爬蟲對這些種子,進行深度為1的廣度遍歷(預設就是廣度遍歷)。
3)爬蟲怎麼爬取要登陸的網站?
這些開源爬蟲都支援在爬取時指定cookies,模擬登陸主要是靠cookies。至於cookies怎麼獲取,不是爬蟲管的事情。你可以手動獲取、用http請求模擬登陸或者用模擬瀏覽器自動登陸獲取cookie。
4)爬蟲怎麼抽取網頁的資訊?
開源爬蟲一般都會整合網頁抽取工具。主要支援兩種規範:CSS SELECTOR和XPATH。至於哪個好,這裡不評價。
5)爬蟲怎麼儲存網頁的資訊?
有一些爬蟲,自帶一個模組負責持久化。比如webmagic,有一個模組叫pipeline。通過簡單地配置,可以將爬蟲抽取到的資訊,持久化到檔案、資料庫等。還有一些爬蟲,並沒有直接給使用者提供資料持久化的模組。比如crawler4j和webcollector。讓使用者自己在網頁處理模組中新增提交資料庫的操作。至於使用pipeline這種模組好不好,就和操作資料庫使用ORM好不好這個問題類似,取決於你的業務。
6)爬蟲被網站封了怎麼辦?
爬蟲被網站封了,一般用多代理(隨機代理)就可以解決。但是這些開源爬蟲一般沒有直接支援隨機代理的切換。所以使用者往往都需要自己將獲取的代理,放到一個全域性陣列中,自己寫一個代理隨機獲取(從陣列中)的程式碼。
7)網頁可以呼叫爬蟲麼?
爬蟲的呼叫是在Web的服務端呼叫的,平時怎麼用就怎麼用,這些爬蟲都可以使用。
8)爬蟲速度怎麼樣?
單機開源爬蟲的速度,基本都可以講本機的網速用到極限。爬蟲的速度慢,往往是因為使用者把執行緒數開少了、網速慢,或者在資料持久化時,和資料庫的互動速度慢。而這些東西,往往都是使用者的機器和二次開發的程式碼決定的。這些開源爬蟲的速度,都很可以。
9)明明程式碼寫對了,爬不到資料,是不是爬蟲有問題,換個爬蟲能解決麼?
如果程式碼寫對了,又爬不到資料,換其他爬蟲也是一樣爬不到。遇到這種情況,要麼是網站把你封了,要麼是你爬的資料是javascript生成的。爬不到資料通過換爬蟲是不能解決的。
10)哪個爬蟲可以判斷網站是否爬完、那個爬蟲可以根據主題進行爬取?
爬蟲無法判斷網站是否爬完,只能儘可能覆蓋。
至於根據主題爬取,爬蟲之後把內容爬下來才知道是什麼主題。所以一般都是整個爬下來,然後再去篩選內容。如果嫌爬的太泛,可以通過限制URL正則等方式,來縮小一下範圍。
11)哪個爬蟲的設計模式和構架比較好?
設計模式純屬扯淡。說軟體設計模式好的,都是軟體開發完,然後總結出幾個設計模式。設計模式對軟體開發沒有指導性作用。用設計模式來設計爬蟲,只會使得爬蟲的設計更加臃腫。
至於構架,開源爬蟲目前主要是細節的資料結構的設計,比如爬取執行緒池、任務佇列,這些大家都能控制好。爬蟲的業務太簡單,談不上什麼構架。
所以對於JAVA開源爬蟲,我覺得,隨便找一個用的順手的就可以。如果業務複雜,拿哪個爬蟲來,都是要經過複雜的二次開發,才可以滿足需求。
3.3 非JAVA爬蟲
在非JAVA語言編寫的爬蟲中,有很多優秀的爬蟲。這裡單獨提取出來作為一類,並不是針對爬蟲本身的質量進行討論,而是針對larbin、scrapy這類爬蟲,對開發成本的影響。
先說python爬蟲,python可以用30行程式碼,完成JAVA 50行程式碼乾的任務。python寫程式碼的確快,但是在除錯程式碼的階段,python程式碼的除錯往往會耗費遠遠多於編碼階段省下的時間。使用python開發,要保證程式的正確性和穩定性,就需要寫更多的測試模組。當然如果爬取規模不大、爬取業務不復雜,使用scrapy這種爬蟲也是蠻不錯的,可以輕鬆完成爬取任務。
上圖是Scrapy的架構圖,綠線是資料流向,首先從初始URL 開始,Scheduler 會將其交給 Downloader 進行下載,下載之後會交給 Spider 進行分析,需要儲存的資料則會被送到Item Pipeline,那是對資料進行後期處理。另外,在資料流動的通道里還可以安裝各種中介軟體,進行必要的處理。 因此在開發爬蟲的時候,最好也先規劃好各種模組。我的做法是單獨規劃下載模組,爬行模組,排程模組,資料儲存模組。
對於C++爬蟲來說,學習成本會比較大。而且不能只計算一個人的學習成本,如果軟體需要團隊開發或者交接,那就是很多人的學習成本了。軟體的除錯也不是那麼容易。
還有一些ruby、php的爬蟲,這裡不多評價。的確有一些非常小型的資料採集任務,用ruby或者php很方便。但是選擇這些語言的開源爬蟲,一方面要調研一下相關的生態圈,還有就是,這些開源爬蟲可能會出一些你搜不到的BUG(用的人少、資料也少)
4、反爬蟲技術
因為搜尋引擎的流行,網路爬蟲已經成了很普及網路技術,除了專門做搜尋的Google,Yahoo,微軟,百度以外,幾乎每個大型入口網站都有自己的搜尋引擎,大大小小叫得出來名字得就幾十種,還有各種不知名的幾千幾萬種,對於一個內容型驅動的網站來說,受到網路爬蟲的光顧是不可避免的。
一些智慧的搜尋引擎爬蟲的爬取頻率比較合理,對網站資源消耗比較少,但是很多糟糕的網路爬蟲,對網頁爬取能力很差,經常併發幾十上百個請求迴圈重複抓取,這種爬蟲對中小型網站往往是毀滅性打擊,特別是一些缺乏爬蟲編寫經驗的程式設計師寫出來的爬蟲破壞力極強,造成的網站訪問壓力會非常大,會導致網站訪問速度緩慢,甚至無法訪問。
一般網站從三個方面反爬蟲:使用者請求的Headers,使用者行為,網站目錄和資料載入方式。前兩種比較容易遇到,大多數網站都從這些角度來反爬蟲。第三種一些應用ajax的網站會採用,這樣增大了爬取的難度。
4.1 通過Headers反爬蟲
從使用者請求的Headers反爬蟲是最常見的反爬蟲策略。很多網站都會對Headers的User-Agent進行檢測,還有一部分網站會對Referer進行檢測(一些資源網站的防盜鏈就是檢測Referer)。如果遇到了這類反爬蟲機制,可以直接在爬蟲中新增Headers,將瀏覽器的User-Agent複製到爬蟲的Headers中;或者將Referer值修改為目標網站域名[評論:往往容易被忽略,通過對請求的抓包分析,確定referer,在程式中模擬訪問請求頭中新增]。對於檢測Headers的反爬蟲,在爬蟲中修改或者新增Headers就能很好的繞過。
4.2 基於使用者行為反爬蟲
還有一部分網站是通過檢測使用者行為,例如同一IP短時間內多次訪問同一頁面,或者同一賬戶短時間內多次進行相同操作。[這種防爬,需要有足夠多的ip來應對]
大多數網站都是前一種情況,對於這種情況,使用IP代理就可以解決。可以專門寫一個爬蟲,爬取網上公開的代理ip,檢測後全部儲存起來。這樣的代理ip爬蟲經常會用到,最好自己準備一個。有了大量代理ip後可以每請求幾次更換一個ip,這在requests或者urllib2中很容易做到,這樣就能很容易的繞過第一種反爬蟲。[評論:動態撥號也是一種解決方案]
對於第二種情況,可以在每次請求後隨機間隔幾秒再進行下一次請求。有些有邏輯漏洞的網站,可以通過請求幾次,退出登入,重新登入,繼續請求來繞過同一賬號短時間內不能多次進行相同請求的限制。[評論:對於賬戶做防爬限制,一般難以應對,隨機幾秒請求也往往可能被封,如果能有多個賬戶,切換使用,效果更佳]
4.3動態頁面的反爬蟲
上述的幾種情況大多都是出現在靜態頁面,還有一部分網站,我們需要爬取的資料是通過ajax請求得到,或者通過Java生成的。首先用Firebug或者HttpFox對網路請求進行分析[評論:感覺google的、IE的網路請求分析使用也挺好]。如果能夠找到ajax請求,也能分析出具體的引數和響應的具體含義,我們就能採用上面的方法,直接利用requests或者urllib2模擬ajax請求,對響應的json進行分析得到需要的資料。
能夠直接模擬ajax請求獲取資料固然是極好的,但是有些網站把ajax請求的所有引數全部加密了。我們根本沒辦法構造自己所需要的資料的請求。我這幾天爬的那個網站就是這樣,除了加密ajax引數,它還把一些基本的功能都封裝了,全部都是在呼叫自己的介面,而介面引數都是加密的。遇到這樣的網站,我們就不能用上面的方法了,我用的是selenium+phantomJS框架,呼叫瀏覽器核心,並利用phantomJS執行js來模擬人為操作以及觸發頁面中的js指令碼。從填寫表單到點選按鈕再到滾動頁面,全部都可以模擬,不考慮具體的請求和響應過程,只是完完整整的把人瀏覽頁面獲取資料的過程模擬一遍。[評論:支援phantomJS]
用這套框架幾乎能繞過大多數的反爬蟲,因為它不是在偽裝成瀏覽器來獲取資料(上述的通過新增 Headers一定程度上就是為了偽裝成瀏覽器),它本身就是瀏覽器,phantomJS就是一個沒有介面的瀏覽器,只是操控這個瀏覽器的不是人。利用 selenium+phantomJS能幹很多事情,例如識別點觸式(12306)或者滑動式的驗證碼,對頁面表單進行暴力破解等等。它在自動化滲透中還 會大展身手,以後還會提到這個。