最近在CSDN上遊盪,看到首頁有個WP專區,點開後是關於微軟的Windows Phone 7的各種開發資料。一時心血來潮,點開“四天玩轉Windows Phone 7開發視頻教程”的連結,點了下視頻,發現要安裝silverlight才能觀看。所以就想先把它們下載下來,但NND發現這些個東東是用silverlight架構播放的,居然無法下載。但咱是誰啊,苦X兼苦X的程式員啊,有啥子事情是咱做不來的,於是右鍵查看原始碼,可以看到
initParams:"SVP_{0}=c_69b409f9e1234b0abc8040841ecd7521,VideoUri=http://download.microsoft.com/download/7/1/0/710733A5-5BE6-436E-AC7D-A265170CBB4B/Series_Introduction_Day_1_Part_1_subtitle.wmv,ThumbUri=http://msdn.microsoft.com/zh-cn/windowsphone/hh395103.1_1b(l=zh-cn).jpg,Title=系列簡介,HideFullBrowser=true,EmbedEnabled=true,EmbedCssWidth=400,EmbedCssHeight=320,EmbedXapUri=http://msdn.microsoft.com/objectforward/default.aspx,Author=,Brand=,Locale=,StartMode=AutoLoad,Persistence=None,MSNVideoUUID=,PTID=,HeaderColor=#06a4de,HighlightColor=#06a4de,MoreLinkColor=#0066dd,LinkColor=#0066dd,LoadingColor=#06a4de,GetUri=http://msdn.microsoft.com/areas/sto/services/labrador.asmx,FontsToLoad=http://i3.msdn.microsoft.com/areas/sto/content/silverlight/Microsoft.Mtps.Silverlight.Fonts.SegoeUI.xap;segoeui.ttf 好啦,大家請看第二行的VideoUri=http://download.microsoft.com/download/7/1/0/710733A5-5BE6-436E-AC7D-A265170CBB4B/Series_Introduction_Day_1_Part_1_subtitle.wmv,發現了吧,以wmv結尾的,把地址複製下粘貼到瀏覽器或者迅雷,OK,直接下載。 但是網站上有七八十個視頻,總不能一個個點開然後查看原始碼找到以wmv結尾的URL複製到迅雷再下載吧。答案當然是NO,NO,NO,誰讓咱是偉大而苦X的程式員啊。大家應該知道搜尋引擎是怎麼檢索資訊的吧,沒錯就是網路爬蟲,它是一種按照一定的規則,自動的抓取全球資訊網資訊的程式或者指令碼。雖然網路上有很多前輩們寫的開源而強大的網路爬蟲,但本著學習的態度,還是自己動手寫吧。 我們就以這個地址為初始節點吧:http://msdn.microsoft.com/zh-cn/windowsphone/hh182984,裡面是所有的視頻地址,右鍵查看原始碼為了方便查看,我把其中不需要的元素刪除了。<a href="http://msdn.microsoft.com/windowsphone/hh768215">(1)從 XNA 到 SLXNA</a><a href="http://msdn.microsoft.com/windowsphone/hh768217">(2)將 FAS 添加到 XNA</a><a href="http://msdn.microsoft.com/windowsphone/hh768227">(3)將 FAS 添加到一個典型的Silverlight 應用程式中</a><a href="http://msdn.microsoft.com/windowsphone/hh768228">(4)添加次方塊</a><a href="http://msdn.microsoft.com/windowsphone/hh768230">(6)使用即時網路攝影機未經處理資料</a><a href="http://msdn.microsoft.com/windowsphone/hh768231">(7)對次方塊和深度 Toast 使用推播通知</a>
<a href="http://msdn.microsoft.com/windowsphone/hh968968">(8)使用代碼優先本機資料庫</a>
上面的地址就是我們需要的,但怎麼把它們全抓出來呢,首先就是將初始節點網頁內容全部下載。這裡為了方便,沒有將抓取到的網頁內容寫入檔案。
public static String getNetPage(String starturl){//starturl="http://msdn.microsoft.com/zh-cn/windowsphone/hh182984"StringBuilder page =new StringBuilder("");try {URL url=new URL(starturl);URLConnection connection=url.openConnection();InputStream in=connection.getInputStream();InputStreamReader reader=new InputStreamReader(in,"UTF-8");BufferedReader bufferedReader=new BufferedReader(reader);String line=null;while ((line=bufferedReader.readLine())!=null) {page.append(line).append("\n");}System.out.println(page);} catch (MalformedURLException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}return page.toString();} OK,網頁內容有了,下面就是怎麼將所需的地址取出來。這裡使用Regex,下面的Regex怎麼樣。
public static ArrayList<String> getUrlFromPage(String page){ArrayList<String> list=new ArrayList<String>();String regex="http://msdn.microsoft.com/windowsphone/hh[0-9]{6}";Pattern pattern=Pattern.compile(regex);Matcher matcher=pattern.matcher(page);while (matcher.find()) {String url=matcher.group(); System.out.println(url); list.add(url);}return list;} 細心的讀者可能會發現網頁裡許多不是視頻地址的地址也被我們抓取到了。<a href="http://msdn.microsoft.com/windowsphone/hh395103"><img align="top" alt="" src="http://i.msdn.microsoft.com/hh395033.1_1(zh-cn,MSDN.10).jpg" title="Windows Phone 視頻" /></a><a href="http://msdn.microsoft.com/windowsphone/hh398252"><img align="top" alt="" src="http://i.msdn.microsoft.com/hh395033.1_2(zh-cn,MSDN.10).jpg" title="Windows Phone 視頻" /></a><a href="http://msdn.microsoft.com/windowsphone/hh398439"><img align="top" alt="" src="http://i.msdn.microsoft.com/hh395033.1_3(zh-cn,MSDN.10).jpg" title="Windows Phone 視頻" /></a><<a href="http://msdn.microsoft.com/windowsphone/hh417688"><img align="top" alt="" src="http://i.msdn.microsoft.com/hh395033.1_4(zh-cn,MSDN.10).jpg" title="Windows Phone 視頻" />
這當然不是我們想要的結果。而且大家看到每個視頻地址後都有關於此視頻的標題,我們能不能將標題一塊抓取過來,將之與視頻地址對應。public static ArrayList<HashMap<String,String>> getUrlFromPage(String page){ArrayList<HashMap<String,String>> list=new ArrayList<HashMap<String,String>>();String regex="http://msdn.microsoft.com/windowsphone/hh[0-9]{6}\">[^x00-xff][0-9]+[^x00-xff][^6]*</a>";Pattern pattern=Pattern.compile(regex);Matcher matcher=pattern.matcher(page);while (matcher.find()) {String url=matcher.group(); System.out.println(url); HashMap<String,String> map=new HashMap<String,String>(); String[] s=url.split("\">"); map.put("index",s[1]); map.put("url",s[0]); list.add(map);}return list;} 下面是列印的結果。
http://msdn.microsoft.com/windowsphone/hh768215">(1)從 XNA 到 SLXNA</a>http://msdn.microsoft.com/windowsphone/hh768217">(2)將 FAS 添加到 XNA</a>http://msdn.microsoft.com/windowsphone/hh768227">(3)將 FAS 添加到一個典型的Silverlight 應用程式中</a>http://msdn.microsoft.com/windowsphone/hh768228">(4)添加次方塊</a>http://msdn.microsoft.com/windowsphone/hh768229">(5)添加背景代理程式</a>http://msdn.microsoft.com/windowsphone/hh768230">(6)使用即時網路攝影機未經處理資料</a>http://msdn.microsoft.com/windowsphone/hh768231">(7)對次方塊和深度 Toast 使用推播通知</a>http://msdn.microsoft.com/windowsphone/hh968968">(8)使用代碼優先本機資料庫</a>http://msdn.microsoft.com/windowsphone/hh968969">(9)後台音頻</a>http://msdn.microsoft.com/windowsphone/hh395103">(1)系列簡介</a>http://msdn.microsoft.com/windowsphone/hh398252">(2)安裝 Visual Studio 2010 Express for Windows Phone</a>http://msdn.microsoft.com/windowsphone/hh398439">(3)編寫您的第一個 Windows Phone 7 應用程式</a>http://msdn.microsoft.com/windowsphone/hh417688">(4)Windows Phone 7 模擬器概述</a>http://msdn.microsoft.com/windowsphone/hh417718">(5)詳解您編寫的第一個應用程式</a>http://msdn.microsoft.com/windowsphone/hh417729">(6)管理專案檔並理解編譯和部署</a>http://msdn.microsoft.com/windowsphone/hh417730">(7)Visual Studio 2010 Express for Windows Phone IDE 概述</a>http://msdn.microsoft.com/windowsphone/hh417732">(8)使用項目</a>http://msdn.microsoft.com/windowsphone/hh417735">(9)聲明變數和賦值</a>http://msdn.microsoft.com/windowsphone/hh417890">(10)從文字框中接受輸入和賦值</a>http://msdn.microsoft.com/windowsphone/hh417892">(11)if 判斷語句</a>http://msdn.microsoft.com/windowsphone/hh417893">(12)運算子、運算式和語句</a>http://msdn.microsoft.com/windowsphone/hh417894">(13)switch 判斷語句</a>http://msdn.microsoft.com/windowsphone/hh417895">(14)for iteration 語句</a>http://msdn.microsoft.com/windowsphone/hh417896">(15)建立和調用簡單的 Helper 方法</a>http://msdn.microsoft.com/windowsphone/hh417897">(16)家庭作業</a>http://msdn.microsoft.com/windowsphone/hh417898">(17)家庭作業解決方案</a>http://msdn.microsoft.com/windowsphone/hh417899">(1)處理字串</a>http://msdn.microsoft.com/windowsphone/hh417901">(2)使用 DateTime</a>http://msdn.microsoft.com/windowsphone/hh417902">(3)理解和建立類</a>http://msdn.microsoft.com/windowsphone/hh417903">(4)使用 .NET Framework 類庫中的類</a>http://msdn.microsoft.com/windowsphone/hh417904">(5)理解命名空間</a>http://msdn.microsoft.com/windowsphone/hh417905">(6)使用集合</a>http://msdn.microsoft.com/windowsphone/hh417906">(7)對象和集合初始設定式</a>http://msdn.microsoft.com/windowsphone/hh417908">(8)在 XAML 設計器和代碼視窗中工作</a>http://msdn.microsoft.com/windowsphone/hh417909">(9)理解 XAML 文法</a>http://msdn.microsoft.com/windowsphone/hh417910">(10)Silverlight 布局控制項</a>http://msdn.microsoft.com/windowsphone/hh417911">(11)處理 Silverlight 事件</a>http://msdn.microsoft.com/windowsphone/hh417912">(12)Silverlight 輸入控制項</a>http://msdn.microsoft.com/windowsphone/hh417913">(13)家庭作業</a>http://msdn.microsoft.com/windowsphone/hh417914">(14)家庭作業解決方案 - 第1 部分</a>http://msdn.microsoft.com/windowsphone/hh417916">(15)家庭作業解決方案 - 第2 部分</a>http://msdn.microsoft.com/windowsphone/hh417917">(1)使用影像控制</a>http://msdn.microsoft.com/windowsphone/hh417918">(2)處理資源和樣式</a>http://msdn.microsoft.com/windowsphone/hh417923">(3)在 XAML 頁面之間瀏覽和傳遞資料</a>http://msdn.microsoft.com/windowsphone/hh417924">(4)使用應用程式欄</a>http://msdn.microsoft.com/windowsphone/hh417925">(5)利用 Canvas 作為對話方塊</a>http://msdn.microsoft.com/windowsphone/hh417926">(6)理解隔離儲存區 (Isolated Storage)</a>http://msdn.microsoft.com/windowsphone/hh417927">(7)隔離儲存區 (Isolated Storage)、ListBox 和資料範本</a>http://msdn.microsoft.com/windowsphone/hh417928">(8)邏輯刪除和任務切換</a>http://msdn.microsoft.com/windowsphone/hh418008">(9)添加不同的輸入範圍</a>http://msdn.microsoft.com/windowsphone/hh418009">(10)GPS、位置 API 和調用 Web 服務</a>http://msdn.microsoft.com/windowsphone/hh418010">(11)映像背景、方向更改和控制項可見度</a>http://msdn.microsoft.com/windowsphone/hh418011">(12)家庭作業</a>http://msdn.microsoft.com/windowsphone/hh418012">(13)家庭作業解決方案</a>http://msdn.microsoft.com/windowsphone/hh418013">(1)簡介</a>http://msdn.microsoft.com/windowsphone/hh418014">(2)開始活動</a>http://msdn.microsoft.com/windowsphone/hh418015">(3)MainPage 初始設定</a>http://msdn.microsoft.com/windowsphone/hh418016">(4)建立注釋命名規範</a>http://msdn.microsoft.com/windowsphone/hh418017">(5)將 Note Class 綁定到 ListBox DataTemplate</a>http://msdn.microsoft.com/windowsphone/hh418018">(6)添加註釋頁面初始設定</a>http://msdn.microsoft.com/windowsphone/hh418019">(7)調用 TerraService Web 服務</a>http://msdn.microsoft.com/windowsphone/hh418020">(8)儲存新注釋</a>http://msdn.microsoft.com/windowsphone/hh418021">(9)ViewEdit 頁面初始設定</a>http://msdn.microsoft.com/windowsphone/hh418022">(10)在 MainPage 與 ViewEdit 頁面之間導航</a>http://msdn.microsoft.com/windowsphone/hh418023">(11)在 ViewEdit 頁面上切換到Edit 模式並儲存更改</a>http://msdn.microsoft.com/windowsphone/hh418024">(12)ViewEdit 頁面的刪除注釋功能</a>http://msdn.microsoft.com/windowsphone/hh418025">(13)在 MainPage 上添加協助螢幕</a>http://msdn.microsoft.com/windowsphone/hh418026">(14)儲存應用程式狀態第 1 部分- MainPage</a>http://msdn.microsoft.com/windowsphone/hh418027">(15)儲存應用程式狀態第 2 部分 - Add 頁面</a>http://msdn.microsoft.com/windowsphone/hh418028">(16)儲存應用程式狀態第 3 部分 - ViewEdit 頁面</a>http://msdn.microsoft.com/windowsphone/hh418029">(17)調試空白檔案名稱問題</a>http://msdn.microsoft.com/windowsphone/hh418030">(18)代碼清理、異常處理和市場準備</a>http://msdn.microsoft.com/windowsphone/hh418031">(19)相關內容</a>
但這還不是我們期望的結果,沒關係,接著來public static String getWMVFromURL(String page){String suburl = null;String regex="http://download.microsoft.com/download[^\\u4e00-\\u9fa5]+\\.(wmv)";Pattern pattern=Pattern.compile(regex);Matcher matcher=pattern.matcher(page);while (matcher.find()) {suburl=matcher.group();}return suburl;} 下面是主函數public static void main(String[] args){String url="http://msdn.microsoft.com/zh-cn/windowsphone/hh182984";String page=getNetPage(url);ArrayList<HashMap<String,String>> list;list=getUrlFromPage(page);for (int i = 0; i < list.size(); i++) {String suburl=list.get(i).get("url");String subpage=getNetPage(suburl);String wmvurl=getWMVFromURL(subpage);System.out.println("wmvurl="+i+"="+wmvurl);}} 大家可以對此最佳化一下,可以使用多線程。 另外需要說明的是如果只是使用我上面的方法是不能正確抓取到視頻地址的,需要加上諸如User-Agent:使用者瀏覽器與版本資訊、Referer:請求URL的源地址或Cookie:用於辨別使用者身份,儲存在使用者的資料等資訊,這是為了防止網路爬蟲可能頻繁訪問網站影響網站效能。而之所以寫這篇博文,只是提供一種如何抓取網頁URL的思想。 文章中如有錯誤或不當之處,還請指正。若是大牛看到,就當是一笑話了。