您好,登錄后才能下訂單哦!
這篇文章將為大家詳細(xì)講解有關(guān)爬取前程無憂python職位信息的方法步驟,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。
爬取前程無憂python職位信息的步驟:
1、分析網(wǎng)頁,查找需要的數(shù)據(jù)所在位置
網(wǎng)站地址:
https://search.51job.com/list/000000,000000,0000,00,9,99,%2520,2,1.html
(1)進(jìn)入該網(wǎng)站,輸入關(guān)鍵詞“python”,如下:
可以發(fā)現(xiàn)輸入關(guān)鍵字后鏈接也對應(yīng)出現(xiàn)了“python”關(guān)鍵字,根據(jù)這個規(guī)律可以實現(xiàn)進(jìn)入任意搜索關(guān)鍵詞的網(wǎng)頁。
(2)緊接著檢查網(wǎng)頁源代碼,看看網(wǎng)頁數(shù)據(jù)是否在源代碼內(nèi):
可以發(fā)現(xiàn)職位的詳情網(wǎng)址、職位名稱、薪資等信息都顯示在網(wǎng)頁源代碼內(nèi),確定改數(shù)據(jù)為靜態(tài)數(shù)據(jù),可以使用xpath解析語法來獲取。職位的詳情頁也可以根據(jù)此方法來判斷是否存在網(wǎng)頁源代碼,結(jié)果也是存在的。
(3)我們點擊第二頁后發(fā)現(xiàn)網(wǎng)址也對應(yīng)發(fā)生改變:
第一頁:
https://search.51job.com/list/000000,000000,0000,00,9,99,python,2,1.html
第二頁:
https://search.51job.com/list/000000,000000,0000,00,9,99,python,2,2.html
可以發(fā)現(xiàn)鏈接的倒數(shù)第一個數(shù)字發(fā)生了變化,由1變成2,由此可以判斷這個位置的數(shù)字是控制頁數(shù)的。接下來可以實現(xiàn)代碼了。
2、導(dǎo)入需要使用到的模塊,編寫爬取函數(shù)以及存儲函數(shù)
(1)爬蟲使用到的模塊:
import requests # 網(wǎng)絡(luò)請求庫 from lxml import etree # 解析模塊 import time # 時間模塊 import csv # csv模塊 import urllib3 # urllib3,主要用來關(guān)掉警告信息 from requests.adapters import HTTPAdapter # HTTPAdapter,主要用來重新請求
(2)__init__初始化函方法:
def __init__(self): self.keyword = input("請輸入搜索關(guān)鍵詞:") self.url = 'https://search.51job.com/list/000000,000000,0000,00,9,99,{},2,{}.html' # 網(wǎng)頁url self.headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36'} # 設(shè)置請求頭 self.requests = requests.Session() # 創(chuàng)建csv對象,用于保存會話 self.requests.mount('http://', HTTPAdapter(max_retries=3)) # 增加http請求次數(shù),這里是因為有時候我們這邊網(wǎng)絡(luò)不好,導(dǎo)致請求出不來,或者對方?jīng)]響應(yīng)給我們,導(dǎo)致報錯。添加這段代碼可以重新請求 self.requests.mount('https://', HTTPAdapter(max_retries=3)) # 增加https請求次數(shù),這里是因為有時候我們這邊網(wǎng)絡(luò)不好,導(dǎo)致請求出不來,或者對方?jīng)]響應(yīng)給我們,導(dǎo)致報錯。添加這段代碼可以重新請求 self.header = ['position', 'company', 'wages', 'place', 'education','work_experience', 'release_date', 'limit_people', 'address', 'company_type', 'company_size', 'industry', 'point_information'] # csv頭部信息 self.fp = open('python招聘職位.csv', 'a', encoding='utf-8', newline='') # 創(chuàng)建保存csv的句柄 self.writer = csv.DictWriter(self.fp, self.header) # 創(chuàng)建writer,用于后面寫入數(shù)據(jù) self.writer.writeheader() # 保寫入csv頭部信息 urllib3.disable_warnings() # 下面的請求中移除了ssl認(rèn)證會生成警告信息,所以這里取消警告輸出
(3)下面單獨實現(xiàn)一個可以獲取總頁數(shù)的方法:
def get_end_page(self): # 該函數(shù)可以獲取最后一頁的頁數(shù) response = self.requests.get(self.url.format(self.keyword, str(1)), headers=self.headers, timeout=4, verify=False) text = response.content.decode('gb18030') # 使用gb18030解碼幾乎適用所有網(wǎng)頁,不適用的網(wǎng)頁只有個別,是從其他網(wǎng)站加載的,解析方式不一樣,直接忽略掉。 html = etree.HTML(text) txt = "".join(html.xpath("//div[@class='dw_page']//div[@class='p_in']/span[1]/text()")) # 獲取包含總頁數(shù)的一段字符串txt end_page = int(txt.split('頁', 1)[0][1:]) # 從字符串txt提取總頁數(shù) return end_page
(4)獲取詳情頁信息的方法:
def parse_url(self, url): response = self.requests.get(url=url, headers=self.headers, timeout=5, verify=False) try: # 這里可能會出現(xiàn)解碼錯誤,因為有個別很少的特殊網(wǎng)頁結(jié)構(gòu),另類來的,不用管 text = response.content.decode('gb18030') except Exception as e: print("特殊網(wǎng)頁字節(jié)解碼錯誤:{},結(jié)束執(zhí)行該函數(shù),解析下一個詳情url".format(e)) return # 直接結(jié)束函數(shù),不解析 html = etree.HTML(text) try: # 如果職位名獲取不到會異常,因為這個詳情url的網(wǎng)頁形式也很特殊,很少會出現(xiàn)這種url,所以就return結(jié)束函數(shù),進(jìn)入下一個詳情url position = html.xpath("//div[@class='tHeader tHjob']//div[@class='cn']/h2/@title")[0] # 職位名 except: return company = "".join(html.xpath("//div[@class='tHeader tHjob']//div[@class='cn']/p[1]/a[1]//text()")) # 公司名 wages = "".join(html.xpath("//div[@class='tHeader tHjob']//div[@class='cn']/strong/text()")) # 工資 informations = html.xpath("//div[@class='tHeader tHjob']//div[@class='cn']/p[2]/text()") # 獲取地點經(jīng)驗學(xué)歷等信息 informations = [i.strip() for i in informations] # 將元素兩邊去除空格 place = informations[0] # 工作地點 education = "".join([i for i in informations if i in '本科大專應(yīng)屆生在校生碩士']) # 通過列表推導(dǎo)式獲取學(xué)歷 work_experience = "".join([i for i in informations if '經(jīng)驗' in i ]) # 獲取工作經(jīng)驗 release_date = "".join([i for i in informations if '發(fā)布' in i]) # 獲取發(fā)布時間 limit_people = "".join([i for i in informations if '招' in i]) # 獲取招聘人數(shù) address = "".join(html.xpath("//div[@class='tCompany_main']/div[2]/div[@class='bmsg inbox']/p/text()")) # 上班地址 company_type = "".join(html.xpath("//div[@class='tCompany_sidebar']/div[1]/div[2]/p[1]/@title")) # 公司類型 company_size = "".join(html.xpath("//div[@class='tCompany_sidebar']/div[1]/div[2]/p[2]/@title")) # 公司規(guī)模 industry = "".join(html.xpath("//div[@class='tCompany_sidebar']/div[1]/div[2]/p[3]/@title")) # 所屬行業(yè) point_information = html.xpath('//div[@class="tBorderTop_box"]//div[@class="bmsg job_msg inbox"]//text()') point_information = "".join([i.strip() for i in point_information if i != '\xa0\xa0\xa0\xa0']).replace("\xa0", "") # 職位信息 if len(point_information) == 0: # 有一些詳情url的職位信息的html標(biāo)簽有點區(qū)別,所以判斷一下,長度為0就換下面的解析語法 point_information = html.xpath('//div[@class="tBorderTop_box"]//div[@class="bmsg job_msg inbox"]/text()') point_information = "".join([i.strip() for i in point_information]) if len(point_information) == 0: # 有一些詳情url的職位信息的html標(biāo)簽有點區(qū)別,所以判斷一下,長度為0就換下面的解析語法 point_information = html.xpath('//div[@class="tBorderTop_box"]//div[@class="bmsg job_msg inbox"]//tbody//text()') point_information = "".join([i.strip() for i in point_information]) if len(point_information) == 0: # 有一些詳情url的職位信息的html標(biāo)簽有點區(qū)別,所以判斷一下,長度為0就換下面的解析語法 point_information = html.xpath('//div[@class="tBorderTop_box"]//div[@class="bmsg job_msg inbox"]/ol//text()') point_information = "".join([i.strip() for i in point_information]) item = {'position':position, 'company':company, 'wages':wages, 'place':place, 'education':education, 'work_experience':work_experience, 'release_date':release_date, 'limit_people':limit_people, 'address':address, 'company_type':company_type, 'company_size':company_size, 'industry':industry,'point_information':point_information} # 把解析到的數(shù)據(jù)放入字典中 self.writer.writerow(item) # 保存數(shù)據(jù)
(5)完整代碼:
#!/usr/bin/env python # _*_ coding:utf-8 _*_ # # @Version : 1.0 # @Time : xxx # @Author : xx # @File : 51job.py import requests # 網(wǎng)絡(luò)請求庫 from lxml import etree # 解析模塊 import time # 時間模塊 import csv # csv模塊 import urllib3 # urllib3,主要用來關(guān)掉警告信息 from requests.adapters import HTTPAdapter # HTTPAdapter,主要用來重新請求 class PositionSpider(object): def __init__(self): self.keyword = input("請輸入搜索關(guān)鍵詞:") self.url = 'https://search.51job.com/list/000000,000000,0000,00,9,99,{},2,{}.html' # 網(wǎng)頁url self.headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36'} # 設(shè)置請求頭 self.requests = requests.Session() # 創(chuàng)建csv對象,用于保存會話 self.requests.mount('http://', HTTPAdapter(max_retries=3)) # 增加http請求次數(shù),這里是因為有時候我們這邊網(wǎng)絡(luò)不好,導(dǎo)致請求出不來,或者對方?jīng)]響應(yīng)給我們,導(dǎo)致報錯。添加這段代碼可以重新請求 self.requests.mount('https://', HTTPAdapter(max_retries=3)) # 增加https請求次數(shù),這里是因為有時候我們這邊網(wǎng)絡(luò)不好,導(dǎo)致請求出不來,或者對方?jīng)]響應(yīng)給我們,導(dǎo)致報錯。添加這段代碼可以重新請求 self.header = ['position', 'company', 'wages', 'place', 'education','work_experience', 'release_date', 'limit_people', 'address', 'company_type', 'company_size', 'industry', 'point_information'] # csv頭部信息 self.fp = open('python招聘職位.csv', 'a', encoding='utf-8', newline='') # 創(chuàng)建保存csv的句柄 self.writer = csv.DictWriter(self.fp, self.header) # 創(chuàng)建writer,用于后面寫入數(shù)據(jù) self.writer.writeheader() # 保寫入csv頭部信息 urllib3.disable_warnings() # 下面的請求中移除了ssl認(rèn)證會生成警告信息,所以這里取消警告輸出 def get_end_page(self): # 該函數(shù)可以獲取最后一頁的頁數(shù) response = self.requests.get(self.url.format(self.keyword, str(1)), headers=self.headers, timeout=4, verify=False) text = response.content.decode('gb18030') # 使用gb18030解碼幾乎適用所有網(wǎng)頁,不適用的網(wǎng)頁只有個別,是從其他網(wǎng)站加載的,解析方式不一樣,直接忽略掉。 html = etree.HTML(text) txt = "".join(html.xpath("//div[@class='dw_page']//div[@class='p_in']/span[1]/text()")) # 獲取包含總頁數(shù)的一段字符串txt end_page = int(txt.split('頁', 1)[0][1:]) # 從字符串txt提取總頁數(shù) return end_page def get_url(self, count): num = 0 # 用于判斷是請求響應(yīng)失敗,還是頁數(shù)到底了 while True: # 這里設(shè)置while是因為有時候請求太快,響應(yīng)跟不上,會獲取不到數(shù)據(jù)。也可以使用睡眠的方法。 num += 1 response = self.requests.get(url=self.url.format(self.keyword, count), headers=self.headers, timeout=4, verify=False) # 發(fā)起get請求 text = response.content.decode('gb18030') html = etree.HTML(text) detail_urls = html.xpath("//div[@class='dw_table']/div[@class='el']//p/span/a/@href") # 使用xpath語法提取該頁所有詳情url if len(detail_urls) == 0: # 列表長度為零就重新請求,這一步是因為有時候發(fā)送請求過快,對方服務(wù)器跟不上我們速度,導(dǎo)致返回數(shù)據(jù)為空,所以下面睡眠一下,重新請求 time.sleep(2) # 睡眠一下 continue else: break return detail_urls # 返回列表,將詳情url給下一個函數(shù)進(jìn)行解析獲取數(shù)據(jù) def parse_url(self, url): response = self.requests.get(url=url, headers=self.headers, timeout=5, verify=False) try: # 這里可能會出現(xiàn)解碼錯誤,因為有個別很少的特殊網(wǎng)頁結(jié)構(gòu),另類來的,不用管 text = response.content.decode('gb18030') except Exception as e: print("特殊網(wǎng)頁字節(jié)解碼錯誤:{},結(jié)束執(zhí)行該函數(shù),解析下一個詳情url".format(e)) return # 直接結(jié)束函數(shù),不解析 html = etree.HTML(text) try: # 如果職位名獲取不到會異常,因為這個詳情url的網(wǎng)頁形式也很特殊,很少會出現(xiàn)這種url,所以就return結(jié)束函數(shù),進(jìn)入下一個詳情url position = html.xpath("//div[@class='tHeader tHjob']//div[@class='cn']/h2/@title")[0] # 職位名 except: return company = "".join(html.xpath("//div[@class='tHeader tHjob']//div[@class='cn']/p[1]/a[1]//text()")) # 公司名 wages = "".join(html.xpath("//div[@class='tHeader tHjob']//div[@class='cn']/strong/text()")) # 工資 informations = html.xpath("//div[@class='tHeader tHjob']//div[@class='cn']/p[2]/text()") # 獲取地點經(jīng)驗學(xué)歷等信息 informations = [i.strip() for i in informations] # 將元素兩邊去除空格 place = informations[0] # 工作地點 education = "".join([i for i in informations if i in '本科大專應(yīng)屆生在校生碩士']) # 通過列表推導(dǎo)式獲取學(xué)歷 work_experience = "".join([i for i in informations if '經(jīng)驗' in i ]) # 獲取工作經(jīng)驗 release_date = "".join([i for i in informations if '發(fā)布' in i]) # 獲取發(fā)布時間 limit_people = "".join([i for i in informations if '招' in i]) # 獲取招聘人數(shù) address = "".join(html.xpath("//div[@class='tCompany_main']/div[2]/div[@class='bmsg inbox']/p/text()")) # 上班地址 company_type = "".join(html.xpath("//div[@class='tCompany_sidebar']/div[1]/div[2]/p[1]/@title")) # 公司類型 company_size = "".join(html.xpath("//div[@class='tCompany_sidebar']/div[1]/div[2]/p[2]/@title")) # 公司規(guī)模 industry = "".join(html.xpath("//div[@class='tCompany_sidebar']/div[1]/div[2]/p[3]/@title")) # 所屬行業(yè) point_information = html.xpath('//div[@class="tBorderTop_box"]//div[@class="bmsg job_msg inbox"]//text()') point_information = "".join([i.strip() for i in point_information if i != '\xa0\xa0\xa0\xa0']).replace("\xa0", "") # 職位信息 if len(point_information) == 0: # 有一些詳情url的職位信息的html標(biāo)簽有點區(qū)別,所以判斷一下,長度為0就換下面的解析語法 point_information = html.xpath('//div[@class="tBorderTop_box"]//div[@class="bmsg job_msg inbox"]/text()') point_information = "".join([i.strip() for i in point_information]) if len(point_information) == 0: # 有一些詳情url的職位信息的html標(biāo)簽有點區(qū)別,所以判斷一下,長度為0就換下面的解析語法 point_information = html.xpath('//div[@class="tBorderTop_box"]//div[@class="bmsg job_msg inbox"]//tbody//text()') point_information = "".join([i.strip() for i in point_information]) if len(point_information) == 0: # 有一些詳情url的職位信息的html標(biāo)簽有點區(qū)別,所以判斷一下,長度為0就換下面的解析語法 point_information = html.xpath('//div[@class="tBorderTop_box"]//div[@class="bmsg job_msg inbox"]/ol//text()') point_information = "".join([i.strip() for i in point_information]) item = {'position':position, 'company':company, 'wages':wages, 'place':place, 'education':education, 'work_experience':work_experience, 'release_date':release_date, 'limit_people':limit_people, 'address':address, 'company_type':company_type, 'company_size':company_size, 'industry':industry,'point_information':point_information} # 把解析到的數(shù)據(jù)放入字典中 self.writer.writerow(item) # 保存數(shù)據(jù) if __name__ == '__main__': print("爬蟲開始") spider = PositionSpider() # 創(chuàng)建類的對象spider end_page = spider.get_end_page() # 獲取該職位的總頁數(shù) print("總頁數(shù):{}".format(str(end_page))) for count in range(1, end_page+1): # 遍歷總頁數(shù) detail_urls = spider.get_url(count) # 獲取詳情url方法,接收列表 for detail_url in detail_urls: # 遍歷獲取的詳情url time.sleep(0.2) # 稍微睡眠一下 spider.parse_url(detail_url) # 解析詳情頁獲取數(shù)據(jù) print("已爬取第{}頁".format(count)) spider.fp.close() # 關(guān)閉句柄 print("爬取結(jié)束")
采集結(jié)果:
關(guān)于爬取前程無憂python職位信息的方法步驟就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。