前幾天的博文《關於一道.NET程序員面試題的遐想》得到了很多高手的指教,使我學到了很多,在這里再次向園子里的高手們表示感謝。
開篇,還是從一道面試題開始談起:
面試題:抓取招聘信息。
如下圖:
這是從智聯招聘網站上截取的一份招聘信息頁面,要求用正則表達式抓取出當前頁面下的所有職位名稱。
想必,接觸過正則表達式的程序員做出這道題來都不算困難。只要根據頁面的一些規律性的代碼就可以寫出相應的正則表達式。
下面附上html代碼頁面(部分截圖):(圖2)
解題思路:
要想從頁面中匹配出相應的正則表達式,就要找出一定的規律來,如下圖:
可見,職位信息都是包含在一個<a></a>超鏈接中,雖然超鏈接地址不同但他們的class="jobLink"屬性都是相同的,這樣,規律就出來了,只要我把其中的 class="jobLink"匹配上,再從中提取組,那么這個職位信息也就提取出來了。
我的提取職位信息的正則表達式如下:
<a href=(.+?)class=\"jobLink\">(.+?)</a>
測試如下圖:
做到這里,又突然勾起了我的興趣。既然職位信息這么好抓取,那我何不把公司信息及其他的信息都給抓取下了呢?或者說,何不把職位信息和公司信息一一對應的給他抓取下來?畢竟是剛開始學正則表達式,就當練習了,多多練習才能總結出經驗和規律來嘛!
再次觀察html代碼:
可見,對應於職位信息的class="companyLink"這個屬性都是一致的。根據這一點,正則表達式也就好寫了:
<a href=(.+?)class=\"companyLink\">(.+?)</a>
測試如下圖:
接下來就是怎么將這兩個正則表達式給合並了:
再次觀察圖2,再這兩個<a></a>之間只是隔了一些<td></td>表格標簽,所以開始我想到的方法就是用 .+? 來進行匹配即可。但是無論我怎么測試,都出不來想要的效果。
以下是我測試時失敗的正則表達式:
1. <a href=(.+?)class=\"jobLink\">(.+?)</a>(.+?)<a href=(.+?)class=\"companyLink\">(.+?)</a>
2. <a href=(.+?)class=\"jobLink\">(.+?)</a></td>(.+?)<td id=\"dvCompNM\"><a href=(.+?)class=\"companyLink\">(.+?)</a>
3. <a href=(.+?)class=\"jobLink\">(.+?)</a></td><td></td><td id=\"dvCompNM\"><a href=(.+?)class=\"companyLink\">(.+?)</a>
第三種方法我干脆直接都把這些<td>標簽給寫上了,但仍出不來想要實現的效果。
最后只得向敬愛的曉虎哥求助了。
曉虎哥說:在<a>標簽和<td>標簽之間的這些空白符(如圖2)也算是字符串,必須把他們也要匹配出來。
虎哥的一句話讓我頓悟啊,之前我一直覺得這些只是空白嗎,根本不顯示的,又不像換行符雖不顯示出來但查看源碼還有個<br>標簽呢,但是空白符也是占着一定的位置的。
所以,修改后的正則表達式為:
<a href=(.+?)class=\"jobLink\">(.+?)</a></td>\s*?<td></td>\s*?<td id=\"dvCompNM\"><a href=(.+?)class=\"companyLink\">(.+?)</a>
下圖是我自己寫的程序的抓取結果截圖:
總結一下吧:
有些細微的地方很容易被忽略掉,但關鍵時刻也是這些最容易被忽視的地方決定着整件事情是成功還是失敗。畢竟細節決定成敗嘛!
空白符,我記住你了。
后天曉虎哥就要去往別的城市工作了,這段時間里非常感謝他教會我的解題方法和技巧,在這里祝他一路順風吧!
初學正則表達式,希望可以幫到一些朋友們!
再向大家推薦一個學習正則表達式的網站,http://deerchao.net/tutorials/regex/regex.htm
同時也歡迎大家多多指教!