學習了一段時間的web前端,感覺有點看不清前進的方向,於是就寫了一個小爬蟲,爬了51job上前端相關的崗位,看看招聘方對技術方面的需求,再有針對性的學習。
我在此之前接觸過Python,也寫過一些小腳本,於是決定用Python來完成這個小項目。
首先說說一個爬蟲的組成部分:
1.目標連接,就是我需要爬取信息的網頁的鏈接;
2.目標信息,就是網頁上我需要抓取的信息;
3.信息梳理,就是對爬取的信息進行整理。
下面我來說說整個爬蟲的設計思路:
總體思路:以“前端”關鍵字進行搜索,把搜索結果上面每一個招聘信息的鏈接爬取下來,再通過這些招聘職位的鏈接去抓取相應頁面上的具體要求。
1.先在51job上以“前端”為關鍵字進行搜索,從搜索結果來看,跟我的目標職位相似度還是很高的,所以用“前端”作為關鍵字是沒問題的。
2.獲取搜索結果的鏈接,通過比較1,2兩頁的鏈接,發現只有一個數字的差別,所以我可以直接更改這個數字來獲取每一頁的鏈接
3.在搜索結果頁面按F12可以看到網頁結構,按下左上角的鼠標按鈕,再去點網頁上的元素,網頁結構會自動展現相應的標簽
4.按下左上角的鼠標按鈕,再去點招聘信息的崗位鏈接,可以在網頁結構中看到,我們需要的每一個崗位的具體鏈接是放在一個a標簽里面的
5.再點進這個職位的詳情頁面,按F12查看網頁結構,再按左上角鼠標按鈕,之后點擊網頁上的職位信息,我發現職位信息都是放在一個div標簽里面,這個div有一個樣式類屬性class="bmsg job_msg inbox",具體的信息是放在這個div下的p標簽中,我查看了其他幾個招聘頁面,也是相同的結構
所以我的爬蟲要先爬取搜索結果頁面中的職位鏈接,再進到相應的鏈接爬取div標簽下p標簽的內容,最后對這些內容做一個詞頻分析。
為了簡化這個小項目的結構,我決定把這3個任務分成3個小腳本來執行。
首先是爬取搜索結果頁面中的職位鏈接。代碼如下
1 #爬取職位鏈接這一步用到了3個庫 2 import requests 3 from bs4 import BeautifulSoup 4 import chardet 5 6 f = open('info.txt', 'a') # f是我存儲爬取信息的文本文件,使用追加模式,就是說后面寫入的信息會放在已有的信息后面,這樣就不會把之前的信息覆蓋掉 7 url = 'https://search.51job.com/list/020000,000000,0000,00,9,99,%25E5%2589%258D%25E7%25AB%25AF,2,{}.html?' \ 8 'lang=c&stype=1&postchannel=0000&workyear=99&cotype=99°reefrom=99&jobterm=99&companysize=99&' \ 9 'lonlat=0%2C0&radius=-1&ord_field=0&confirmdate=9&fromType=4&dibiaoid=0&address=&line=&' \ 10 'specialarea=00&from=&welfare=#top' # url里面關乎頁面跳轉的數字我用{}占位,后面可以通過format函數動態替換 11 header = { 12 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 ' 13 'Safari/537.36', 14 'Connection': 'keep-alive', 15 }# header是為了把爬蟲偽裝的像是正常的訪問。 16 17 #for循環結構,循環10次,也就是說爬取10頁上面的職位鏈接 18 for i in range(11): 19 # 用requests庫的get方法與服務器進行鏈接,返回一個requests.models.Response的類 20 pageConnect = requests.get(url.format(i), headers=header) 21 #用chardet庫的detect方法獲取網頁編碼格式,返回的是dict字典,具體的編碼格式在encoding這個鍵對應的值中 22 pageConnect.encoding = chardet.detect(pageConnect.content)['encoding'] 23 #設置好編碼格式后,用text方法把Response這個類轉化為字符串供beautifulSoup處理 24 page = pageConnect.text 25 #使用BeautifulSoup函數把page字符串轉化為一個BeautifulSoup對象,lxml是解析器的類型 26 soup = BeautifulSoup(page, 'lxml') 27 #使用BeautifulSoup對象的select方法,可以用css選擇器把存放有職位鏈接的a標簽選出來 28 #每一個a標簽都是放在class=el的div標簽下class=t1的p標簽下 29 aLabel = soup.select('div.el > p.t1 a') 30 #每一個搜索結果頁有50個職位,也就有50個a標簽,通過for循環,獲取每個a標簽的title屬性,href屬性 31 #title屬性存放了職位名稱,我可以通過職位名稱把不是我需要的職位鏈接篩選出去 32 #href屬性存放了每一個職位的鏈接 33 for each in aLabel: 34 #把這些信息存放到f也就是info.txt這個文本中 35 print(each['title'], each['href'], file=f)
接着要做的就是爬取每一個鏈接頁面上的職位要求了
代碼如下
1 import requests 2 from bs4 import BeautifulSoup 3 import chardet 4 5 #打開我存放鏈接的文本,使用readlines方法讀取文本內容,返回的是一個list列表,每一行為列表中的一項 6 with open('info.txt') as info: 7 link = info.readlines() 8 #打開一個文本文件,存放抓取到的職位要求,編碼格式設為utf-8 9 job = open('job.txt', 'a', encoding='UTF-8') 10 header = { 11 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 ' 12 'Safari/537.36', 13 'Connection': 'keep-alive', 14 } 15 16 for each in link: 17 #info.txt中存放的信息是職位名 + 鏈接:Web前端開發工程師 https://***** 18 #所以先對列表中的每一項,也就是說一個字符串調用find方法,搜索關鍵字http,返回的是一個整數,表示的是字符串中http開頭h的索引值 19 index = each.find('http') 20 #利用這個索引值,可以獲取字符串中鏈接的部分 21 url = each[index:] 22 pageConnect = requests.get(url, headers=header) 23 pageConnect.encoding = chardet.detect(pageConnect.content)['encoding'] 24 page = pageConnect.text 25 soup = BeautifulSoup(page, 'lxml') 26 #所有的職位要求是放在一個div中,它的樣式類為class=bmsg job_msg inbox,div中的p標簽包含具體的信息,返回的是一個list列表 27 div = soup.select('div.bmsg.job_msg.inbox p') 28 #經過測試發現,最后2個p標簽存放着關鍵字,所以去掉 29 jobInfo = div[:-2] 30 for eachInfo in jobInfo: 31 #每個列表項存放着如<p>***</P>的bs4.element.Tag,要獲取其中文字部分,要使用.string方法 32 print(eachInfo.string, file=job)
最后job.txt中存放着我抓取到的所有職位要求,但是我不可能一條一條的去看,所以借助jieba這個庫進行分詞
1 import jieba 2 3 with open('job.txt', encoding='utf-8') as job: 4 info = job.readlines() 5 for eachLine in info: 6 for eachWord in jieba.cut(eachLine): 7 print(eachWord)
為了節省時間,分詞結果直接打印出來,然后復制到excel表中,使用數據透視表統計一下,最后整理結果如下

這是一個非常簡陋的小項目,不過它也實現了我的目標。
