爬蟲實戰(二) 51job移動端數據采集


    在上一篇51job職位信息的爬取中,對崗位信息div下各式各樣雜亂的標簽,簡單的Xpath效果不佳,加上string()函數后,也不盡如人意。因此這次我們跳過桌面web端,選擇移動端進行爬取。

 

一、代碼結構

    按照下圖所示的爬蟲基本框架結構,我將此份代碼分為四個模塊——URL管理、HTML下載、HTML解析以及數據存儲。

 

二、URL管理模塊

    這個模塊負責搜索框關鍵詞與對應頁面URL的生成,以及搜索結果不同頁數的管理。首先觀察某字段(大數據, UTF-8為'E5A4A7 E695B0 E68DAE') 全國范圍內的結果,前三頁結果的URL如下:

    URL前半部分:

    這部分中我們可以看到兩處處不同,第一處為編碼后'2,?.html'中間的數字,這是頁數。另一處為參數stype的值,除第一頁為空之外,其余都為1。另外,URL中有一連串的數字,這些是搜索條件,如地區、行業等,在這兒我沒有用上。后面的一連串字符則為搜索關鍵詞的字符編碼。值得注意的是,有些符號在URL中是不能直接傳輸的,如果需要傳輸的話,就需要對它們進行編碼。編碼的格式為'%'加上該字符的ASCII碼。因此在該URL中,%25即為符號'%'。

    URL后半部分:

    后半部分很明顯的就能出首頁與后面頁面的URL參數相差很大,非首頁的URL后半部分相同。

    因此我們需要對某關鍵字的搜索結果頁面分兩次處理,第一次處理首頁,第二次可使用循環處理后續的頁面。

  1. if __name__ == '__main__':  
  2.     key = '數據開發'  
  3.     第一頁  
  4.     url = 'https://search.51job.com/list/000000,000000,0000,00,9,99,'+key+',2,1.html?lang=c&stype=&postchannel=0000&workyear=99&cotype=99°reefrom=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='  
  5.     getUrl(url)  
  6.     后頁[2,100)  
  7.     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(2,30)]  
  8.     for url in urls:  
  9.         getUrl(url)  

 

三、HTML下載模塊

    下載HTMl頁面分為兩個部分,其一為下載搜索結果某一頁的HTML頁面,另一部分為下載某一崗位具體頁面。由於頁面中具體崗位URL需要從搜索結果頁面中獲取,所以將下載搜索結果頁面及獲取具體崗位URL放入一個函數中,在提取到具體崗位URL后,將其傳入至另一函數中。

3.1搜索結果頁面下載與解析

    下載頁面使用的是requests庫的get()方法,得到頁面文本后,通過lxml庫的etree將其解析為樹狀結構,再通過Xpath提取我們想要的信息。在搜索結果頁面中,我們需要的是具體崗位的URL,打開開發者選項,找到崗位名稱。

    我們需要的是<a>標簽里的href屬性。右鍵,復制——Xpath,得到該屬性的路徑。

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

    由於xpath返回值為一個列表,所以通過一個循環,將列表內URL依次傳入下一函數。

  1. def getUrl(url):  
  2.     print('New page')  
  3.     res = requests.get(url)  
  4.     res.encoding = 'GBK'  
  5.     if res.status_code == requests.codes.ok:  
  6.         selector = etree.HTML(res.text)  
  7.         urls = selector.xpath('//*[@id="resultList"]/div/p/span/a/@href')  
  8.         #                      //*[@id="resultList"]/div/p/span/a  
  9.         for url in urls:  
  10.             parseInfo(url)  
  11.             time.sleep(random.randrange(1, 4))  

 

3.2具體崗位信息頁面下載

    該函數接收一個具體崗位信息的參數。由於我們需要對移動端網頁進行處理,所以在發送請求時需要進行一定的偽裝。通過設置headers,使用手機瀏覽器的用戶代理,再調用get()方法。

  1. def parseInfo(url):  
  2.     headers = {  
  3.         'User-Agent''Opera/9.80 (Android 2.3.4; Linux; Opera Mobi/ADR-1301071546) Presto/2.11.355 Version/12.10'  
  4.     }  
  5.     res = requests.get(url, headers=headers)  

 

四、HTML解析模塊

    在3.2中,我們已經得到了崗位信息的移動端網頁源碼,因此再將其轉為etree樹結構,調用Xpath即可得到我們想要的信息。

    需要注意的是頁面里崗位職責div里,所有相關信息都在一個<article>標簽下,而不同頁面的<article>下層標簽並不相同,所以需要將該標簽下所有文字都取出,此處用上了string()函數。

 

  1. selector = etree.HTML(res.text)  
  2.     
  3. title = selector.xpath('//*[@id="pageContent"]/div[1]/div[1]/p/text()')  
  4. salary = selector.xpath('//*[@id="pageContent"]/div[1]/p/text()')  
  5. company = selector.xpath('//*[@id="pageContent"]/div[2]/a[1]/p/text()')  
  6. companyinfo = selector.xpath('//*[@id="pageContent"]/div[2]/a[1]/div/text()')  
  7. companyplace = selector.xpath('//*[@id="pageContent"]/div[2]/a[2]/span/text()')  
  8. place = selector.xpath('//*[@id="pageContent"]/div[1]/div[1]/em/text()')  
  9. exp = selector.xpath('//*[@id="pageContent"]/div[1]/div[2]/span[2]/text()')  
  10. edu = selector.xpath('//*[@id="pageContent"]/div[1]/div[2]/span[3]/text()')  
  11. num = selector.xpath('//*[@id="pageContent"]/div[1]/div[2]/span[1]/text()')  
  12. time = selector.xpath('//*[@id="pageContent"]/div[1]/div[1]/span/text()')  
  13. info = selector.xpath('string(//*[@id="pageContent"]/div[3]/div[2]/article)')  
  14. info = str(info).strip()  

 

五、數據存儲模塊

    首先創建.csv文件,將不同列名稱寫入首行。

  1. fp = open('51job.csv','wt',newline='',encoding='GBK',errors='ignore')  
  2. writer = csv.writer(fp)  
  3. writer.writerow(('職位','薪資','公司','公司信息','公司地址','地區','工作經驗','學歷','人數','時間','崗位信息'))  

    再在解析某一頁面數據后,將數據按行寫入.csv文件。

  1. writer.writerow((title,salary,company,companyinfo,companyplace,place,exp,edu,num,time,info))  

 

 

源碼:爬取51job移動端源碼(12月)

 

相關:智聯招聘源碼分析

    貪吃蛇鏈表實現及部分模塊優化


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM