1. 程式人生 > >前程無憂爬蟲原始碼及分析(一)

前程無憂爬蟲原始碼及分析(一)

一、網頁分析

    1.1 關鍵字頁面(url入口)

        首先在前程無憂網站上檢索關鍵詞"大資料":

        跳轉到如下url: https://search.51job.com/list/000000,000000,0000,00,9,99,%25E5%25A4%25A7%25E6%2595%25B0%25E6%258D%25AE,2,1.html?lang=c&stype=&postchannel=0000&workyear=99&cotype=99&degreefrom=99&jobterm=99&companysize=99&providesalary=99&lonlat=0%2C0&radius=-1&ord_field=0&confirmdate=9&fromType=&dibiaoid=0&address=&line=&specialarea=00&from=&welfare=

        在這個url中,'%25E5%25A4%25A7%25E6%2595%25B0%25E6%258D%25AE'很明顯為某種編碼格式,我們知道'大資料'的UTF-8為'E5A4A7 E695B0 E68DAE',加上'%'變為16進位制編碼,即'%E5%A4%A7%E6%95%B0%E6%8D%AE',這'25'又是什麼鬼?百度得到到關鍵詞'二次編碼',%25的url編碼即為符號'%',所以'%25E5'即為'%E5'。不過我好奇的是,既然'%'已經是URI中的特殊轉義字元,為啥還要多此一舉地進行二次編碼呢。再查,發現'%'在URI中可能會引起程式解析的歧義,百分號本身就用作對不安全字元進行編碼時使用的特殊字元,因此本身需要編碼

        做一個實驗,我們將該url擷取下來,用'銷售'中文的utf-8編碼代替其中的編碼,看看發生了什麼。

        再回過頭去看在網站入口搜尋框進去的'大資料'頁面:

        這是二次編碼過的,再在url裡改成中文名:

        好吧,二次編碼與否並不影響效果。

        接下來來比較不同頁數URL之間的聯絡。提取'大資料'關鍵詞前三頁url:

        將前兩頁進行對比:

        只有一個符號不同,再比較二、三頁:

        也是一個數字的差異,改數字即為頁碼。所以對於頁數url我們可以得出如下結論:

'https://search.51job.com/list/000000,000000,0000,00,9,99,關鍵詞 ,2,頁數.html?lang=c&stype=1&postchannel=0000&workyear=99&cotype=99&degreefrom=99&jobterm=99&companysize=99&lonlat=0%2C0&radius=-1&ord_field=0&confirmdate=9&fromType=&dibiaoid=0&address=&line=&specialarea=00&from=&welfare='

        因此入口url模組程式碼如下:

  1. if __name__ == '__main__':  
  2.     key = '銷售'  
  3.     urls = ['https://search.51job.com/list/000000,000000,0000,00,9,99,'+ key + ',2,{}.html?lang=c&stype=1&postchannel=0000&workyear=99&cotype=99°reefrom=99&jobterm=99&companysize=99&lonlat=0%2C0&radius=-1&ord_field=0&confirmdate=9&fromType=&dibiaoid=0&address=&line=&specialarea=00&from=&welfare='.format(i) for i in range(1,50)]  
  4.     for url in urls:  
  5.         getUrl(url)  

 

    1.2 崗位詳情url

        由於我們需要的是崗位詳情頁面的資訊,所以我們要找出頁面所有崗位的url。

        開啟開發者工具,找到崗位名稱所在標籤,在屬性裡發現了該頁面的url:

        又發現每一條招聘資訊都在<div class="el">…</div>裡:

所以通過如下xpath將url提取出來:

  1. //*[@id="resultList"]/div/p/span/a/@href  

 

    1.3 崗位資訊提取

        進入某一崗位具體資訊url,開啟開發者選項,在資訊所在標籤上右擊,提取所需資訊的xpath。

  1. title = selector.xpath('/html/body/div[3]/div[2]/div[2]/div/div[1]/h1/text()')  
  2. salary = selector.xpath('/html/body/div[3]/div[2]/div[2]/div/div[1]/strong/text()')  
  3. company = selector.xpath('/html/body/div[3]/div[2]/div[2]/div/div[1]/p[1]/a[1]/text()')  
  4. place = selector.xpath('/html/body/div[3]/div[2]/div[2]/div/div[1]/p[2]/text()[1]')  
  5. exp = selector.xpath('/html/body/div[3]/div[2]/div[2]/div/div[1]/p[2]/text()[2]')  
  6. edu = selector.xpath('/html/body/div[3]/div[2]/div[2]/div/div[1]/p[2]/text()[3]')  
  7. num = selector.xpath('/html/body/div[3]/div[2]/div[2]/div/div[1]/p[2]/text()[4]')  
  8. time = selector.xpath('/html/body/div[3]/div[2]/div[2]/div/div[1]/p[2]/text()[5]')  
  9. comment = selector.xpath('/html/body/div[3]/div[2]/div[3]/div[1]/div/p/text()')  
  10. url = res.url  

    跑一遍看看,

        咦,怎麼崗位要求這麼多null?點一個進去看看

        嗯,<div>標籤下咋又出現了<div>,真是亂來(笑)。看來得換個法子了,把這個父<div>標籤下的中文全部帶走。這兒需要用到xpath的steing()函式。將上述方法改造,得到新的xpath:

  1. string(/html/body/div[3]/div[2]/div[3]/div[1]/div)  

    又能跑起來了,不過把該<div>裡一些其他資訊也帶進來了,比如崗位分類等。

 

 

二、一些細節

    2.1 編碼問題

        雖然沒有系統的學過編碼,但是在與不同網頁、不同的作業系統打交道的過程中也略知一二了。與前些天爬過的智聯招聘不同,前程無憂網頁用的是GBK編碼,所以需要注意編碼格式。而且還有一個小問題:

        對,報錯了,'\ufffd'無法被轉碼。從網上找來的解釋稱:

在通過GBK從字串獲取位元組陣列時,由於一個Unicode轉換成兩個byte,如果此時用ISO-8859-1或用UTF-8構造字串就會出現兩個問號。

若是通過ISO-8859-1構造可以再通過上面所說的錯上加錯恢復(即再通過從ISO-8859-1解析,用GBK構造);

若是通過UTF-8構造則會產生Unicode字元"\uFFFD",不能恢復,若再通過StringUTF-8ByteArrayGBKString,則會出現雜碼,如a錕斤拷錕斤拷

        而在Unicode中,\uFFFD為佔位符,當從某語言向Unicode轉化時,如果在某語言中沒有該字元,得到的將是Unicode的程式碼"\uffffd"。

        針對這種情況,在開啟檔案時可設定一個引數——errors:設定不同錯誤的處理方案,預設為 'strict',意為編碼錯誤引起一個UnicodeError。所以我們需要為該引數換一個值:ignore,當遇到編碼問題市直接無視。

  1. fp = open('51job.csv','wt',newline='',encoding='GBK',errors='ignore')  
  2. writer = csv.writer(fp)  
  3. '''''title,salary,company,place,exp,edu,num,time,comment,url'''  
  4. writer.writerow(('職位','薪水','公司','地區','經驗','學歷','數量','時間','要求','url'))  

 

    2.2 網頁結構問題

        電腦端的結構太多了…資料抓取率也低,程式碼還得改改,還是移動適配又好看又好爬。

 

三、原始碼

    因為在寫這篇部落格的時候,發現了一些之前沒發現的問題,並且有了優化的想法,所以就不把程式碼貼過來了,就留github 吧,這些天再把這個專案改進一下。

    原始碼地址:51job原始碼地址

    相關:智聯招聘原始碼講解