思路梳理
打开拉勾网输入职位信息,可以看到我们想要的数据,当我们翻页的时候可以发现地址是没有任何变化的,因此可以确定我们整个输入查询的过程是通过post请求和异步加载完成的 ;
打开控制台再次加载页面看看我们得到了什么,我们想要的职位信息都好好的躺在这里的,信息都是以json格式传输的,我们只需要调用json的包读取这些数据然后保存下来就ok了 ;
我们自己看其实在json的url里面是包含了城市的这个变量的,因此我们想要查看不同城市的职位只需要在url里面改变城市就好;
但当我们直接访问这个地址的时候我们是看不到职位信息的,看来服务器对headers是有检查的,因此我们在发送请求的时候还必须加上headers;
下面是我们的headers和需要post的数据,其中需要注意的是headers中Referer是一个变量,根据职位的信息不同改变的,Referer是服务器需要确定你是从哪个页面访问过来的,后面的调试中也确定了拉勾网是对Referer进行了检查的,如果Referer不对,服务器会拒绝请求然后出现上图的页面;
我们需要post的数据又三个,多切换几次页面也会发现,first是表示’是否为第一页’,pn是表示’页码’,kd是表示’职位关键字’,因此我们只需要结合json的地址中的city变量+post的职位和页码就能获取到我们想要的数据了!
代码部分
首先是将字符串转成URL编码,如果是utf-8编码直接传入到地址里面,是无法访问到,这个在后面的城市和职位都需要用来转换;
#字符串转URL编码
def StringToUrl(string):
urlcode = urllib.quote(string)
return urlcode
我们获取到整个json数据中是会包含职位数的,每页是显示15个职位,职位数除以15向上取整,便是我们需要循环的次数
#获取职位数与页码 def GetPagnum(url,keyword,headers): values = {'first': 'true','pn': '1', 'kd': keyword} data = urllib.urlencode(values) req = urllib2.Request(url,data,headers) jsondata = urllib2.urlopen(req).read() totalCount = int(json.loads(str(jsondata))["content"]["positionResult"]["totalCount"]) print('***本次搜索到%d个职位***'%totalCount) pagenum = int (math.ceil(totalCount/15) ) return pagenum |
下面是完整代码,整体思路是先根据职位+城市获取到总页数,然后通过循环post页码获取到职位信息,通过pandas保存数据为DataFrame,最后保存为excel
# -*- coding:utf-8 -*- import re,json import urllib2 import urllib import pandas as pd import math #字符串转URL编码 def StringToUrl(string): urlcode = urllib.quote(string) return urlcode #获取职位数与页码 def GetPagnum(url,keyword,headers): values = {'first': 'true','pn': '1', 'kd': keyword} data = urllib.urlencode(values) req = urllib2.Request(url,data,headers) jsondata = urllib2.urlopen(req).read() totalCount = int(json.loads(str(jsondata))["content"]["positionResult"]["totalCount"]) print('***本次搜索到%d个职位***'%totalCount) pagenum = int (math.ceil(totalCount/15) ) return pagenum def LagouSpider(keyword): keyword_url = StringToUrl(keyword) city_list = ['北京','上海','深圳','广州','杭州','成都','南京','武汉','西安','厦门','长沙','苏州','天津'] for n in list(range(len(city_list))): city = city_list[n] print('***正在保存'+city+'的职位***') city_url = StringToUrl(city) url = 'https://www.lagou.com/jobs/positionAjax.json?city='+city_url+'&needAddtionalResult=false&isSchoolJob=0' Referer = 'https://www.lagou.com/jobs/list_'+keyword_url+'?city='+city_url+'=false&fromSearch=true&labelWords=&suginput=' headers = { 'Accept':'application/json, text/javascript, */*; q=0.01', 'Accept-Encoding':'gzip, deflate, br', 'Accept-Language':'zh-CN,zh;q=0.8,en;q=0.6,zh-TW;q=0.4', 'Connection':'keep-alive', 'Content-Length':'55', 'Content-Type':'application/x-www-form-urlencoded; charset=UTF-8', 'Cookie':'user_trace_token=20170912104426-9ba6e9c6-3053-45fd-9025-681bef8b0c8f; LGUID=20170916191219-e783b163-9acf-11e7-952a-525400f775ce; index_location_city=%E6%B7%B1%E5%9C%B3; TG-TRACK-CODE=index_search; _gid=GA1.2.1386711592.1505703954; _ga=GA1.2.351899359.1505560343; Hm_lvt_4233e74dff0ae5bd0a3d81c6ccf756e6=1505560343,1505703955; Hm_lpvt_4233e74dff0ae5bd0a3d81c6ccf756e6=1505703988; LGRID=20170918110627-5c595dd3-9c1e-11e7-9196-5254005c3644; JSESSIONID=ABAAABAAAIAACBIF3290756E031DCE7CCEA3986CB372F49; SEARCH_ID=d30eb13562344eb9b5f6b8f05eb2cefc', 'Host':'www.lagou.com', 'Origin':'https://www.lagou.com', 'Referer':Referer, 'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36', 'X-Anit-Forge-Code':'0', 'X-Anit-Forge-Token':'None', 'X-Requested-With':'XMLHttpRequest' } Pagenum = GetPagnum(url,keyword,headers) for i in range(0,Pagenum): if i == 0: values = {'first': 'true','pn': '1', 'kd': keyword} data = urllib.urlencode(values) else: values = {'first': 'false','pn': (i+1), 'kd': keyword} data = urllib.urlencode(values) req = urllib2.Request(url,data,headers) data = urllib2.urlopen(req).read() jsondata = json.loads(str(data))['content']['positionResult']['result'] for t in list(range(len(jsondata))): jsondata[t].pop('companyLogo') jsondata[t].pop('businessZones') jsondata[t].pop('explain') jsondata[t].pop('plus') jsondata[t].pop('gradeDescription') jsondata[t].pop('promotionScoreExplain') jsondata[t].pop('positionLables') jsondata[t].pop('district') jsondata[t].pop('adWord') jsondata[t].pop('appShow') jsondata[t].pop('approve') jsondata[t].pop('companyId') jsondata[t].pop('companyLabelList') jsondata[t].pop('deliver') jsondata[t].pop('imState') jsondata[t].pop('industryLables') jsondata[t].pop('pcShow') jsondata[t].pop('positionId') jsondata[t].pop('score') jsondata[t].pop('publisherId') if t == 0: rdata=pd.DataFrame(pd.Series(data=jsondata[t])).T else: rdata=pd.concat([rdata,pd.DataFrame(pd.Series(data=jsondata[t])).T]) if i == 0: citydata=rdata else: citydata=pd.concat([citydata,rdata]) print('***正在保存第%d页***'%(i+1)) if n == 0: totaldata = citydata else: totaldata=pd.concat([totaldata,citydata]) totaldata.to_excel('LagouSpider.xls',sheet_name='sheet1') if __name__ == "__main__": keyword = raw_input('请输入要爬取的关键词:') LagouSpider(keyword) print '***LagouSpider@Awesome_Tang***' |
运行结果
上文内容不用于商业目的,如涉及知识产权问题,请权利人联系博为峰小编(021-64471599-8017),我们将立即处理。