这次布置的作业是爬取拉勾网职位信息。之前有积极童鞋投稿了。正好供小白小鉴一下。
收获
一、第一次成功伪装浏览器
二、第一次接触异常处理(谢谢程老师点拨)
三、第一次拿到7000多条信息数据
思路:
先了解拉勾网的代码结构。
打开网页输入职位“数据分析师”,选择地址“上海”
可以看到相关招聘职位情况。翻页选择第二页,url地址仍然不变。可以看出他是动态加载的网页结构。
打开抓包,选择第一页,观察XHR,如图一
选择第二页,观察XHR,如图二
可以看出加载项多了2个,打开其中一个positionAjax.json文件,且所有positionAjax.json文件URL都是一样都。如下:可以看网页地址是一个带Ajax的
preview一下内容。
我们网页上的职位相关信息都在这里全部有了。更可以肯定这个是一个动态加载网站。请求方式是POST,也就是我们需要浏览器提交表单给服务器请求,服务器才会反馈加载页面。
为啥不可以直接用https://www.lagou.com/jobs/list_数据分析师?city=上海&cl=false&fromSearch=true&labelWords=&suginput=
直接 requests.get(url)
得到网页信息?因为其中之一无法构造下一页url得到下一页的加载信息。
继续看一下其他信息,以下2张是我们提交网站的参数。其中pn:1代表第一页,pn:2代表第二页。kd:数据分析师 就是我们在输入栏上的关键词。
所以我们需要用这些信息来模拟游览器去抓去数据。
由于这次是post方式请求,所以需要datas,也就是上边提到的2个图的参数。
url=是固定不变的Ajax那个地址
**datas={'first':'true','pn':?,'kd':?} ** 可以参考上图
为了不被拉勾网站发现我们是爬虫,所以需要在加上一个cookie信息。user-agent信息,cookie和user-agent信息可以通过抓包获得。如下:
所以我们先做一个简单的测试以下:是否可以抓取信息。
#-*-coding:utf-8-*-
import requests
import sys
import json
reload(sys)
sys.setdefaultencoding('utf8')
header={'Cookie': 'user_trace_token=20170409190556-fb6a80e8d2304d2ca6818849d3a1589a; LGUID=20170409190556-816c5024-1d14-11e7-9d7c-5254005c3644; index_location_city=%E4%B8%8A%E6%B5%B7; JSESSIONID=0894912C02FB7DFB8F48129EFCEC6FC4; PRE_UTM=; PRE_HOST=; PRE_SITE=https%3A%2F%2Fwww.lagou.com%2Fjobs%2Flist_%25E6%2595%25B0%25E6%258D%25AE%25E5%2588%2586%25E6%259E%2590%25E5%25B8%2588%3FlabelWords%3D%26fromSearch%3Dtrue%26suginput%3D; PRE_LAND=https%3A%2F%2Fwww.lagou.com%2Fjobs%2FallCity.html%3Fkeyword%3D%25E6%2595%25B0%25E6%258D%25AE%25E5%2588%2586%25E6%259E%2590%25E5%25B8%2588%26px%3Ddefault%26city%3D%25E4%25B8%258A%25E6%25B5%25B7%26positionNum%3D500%2B%26companyNum%3D0%26isCompanySelected%3Dfalse%26labelWords%3D; Hm_lvt_4233e74dff0ae5bd0a3d81c6ccf756e6=1493212645,1493213972,1493216685,1493216698; Hm_lpvt_4233e74dff0ae5bd0a3d81c6ccf756e6=1493309101; _ga=GA1.2.132571186.1491735956; LGSID=20170428000155-d640004d-2b62-11e7-b417-5254005c3644; LGRID=20170428000501-44ee1923-2b63-11e7-b417-5254005c3644; TG-TRACK-CODE=search_code; SEARCH_ID=a392542f875744dba6ba24201fa42eb6','User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36'}
datas={'first':'true','pn':1,'kd':'数据分析师'}
url='https://www.lagou.com/jobs/positionAjax.json?px=default&city=%s&needAddtionalResult=false' %'上海'
html=requests.post(url,data=datas,headers=header).text
html=json.loads(html)
job=html['content']['positionResult']['result'][1]['companyFullName']
print job
反馈结果是:
说明我们的爬虫伪装成功。可以获取信息。
下边就是完整的代码:
#-*-coding:utf-8-*-
import requests
import sys
import json
import csv
import time
reload(sys)
sys.setdefaultencoding('utf8')
header={'Cookie': 'user_trace_token=20170409190556-fb6a80e8d2304d2ca6818849d3a1589a; LGUID=20170409190556-816c5024-1d14-11e7-9d7c-5254005c3644; index_location_city=%E4%B8%8A%E6%B5%B7; JSESSIONID=0894912C02FB7DFB8F48129EFCEC6FC4; PRE_UTM=; PRE_HOST=; PRE_SITE=https%3A%2F%2Fwww.lagou.com%2Fjobs%2Flist_%25E6%2595%25B0%25E6%258D%25AE%25E5%2588%2586%25E6%259E%2590%25E5%25B8%2588%3FlabelWords%3D%26fromSearch%3Dtrue%26suginput%3D; PRE_LAND=https%3A%2F%2Fwww.lagou.com%2Fjobs%2FallCity.html%3Fkeyword%3D%25E6%2595%25B0%25E6%258D%25AE%25E5%2588%2586%25E6%259E%2590%25E5%25B8%2588%26px%3Ddefault%26city%3D%25E4%25B8%258A%25E6%25B5%25B7%26positionNum%3D500%2B%26companyNum%3D0%26isCompanySelected%3Dfalse%26labelWords%3D; Hm_lvt_4233e74dff0ae5bd0a3d81c6ccf756e6=1493212645,1493213972,1493216685,1493216698; Hm_lpvt_4233e74dff0ae5bd0a3d81c6ccf756e6=1493309101; _ga=GA1.2.132571186.1491735956; LGSID=20170428000155-d640004d-2b62-11e7-b417-5254005c3644; LGRID=20170428000501-44ee1923-2b63-11e7-b417-5254005c3644; TG-TRACK-CODE=search_code; SEARCH_ID=a392542f875744dba6ba24201fa42eb6','User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36'}
def totalpage(url,datas,header):
html = requests.post(url, data=datas, headers=header).text
html = json.loads(html)
totalpage=html['content']['positionResult']['totalCount']/15+1
return totalpage
def info(url,datas,header):
html = requests.post(url, data=datas, headers=header).text
html = json.loads(html)
results=html['content']['positionResult']['result']
totaljob=[]
for result in results:
info=[]
companyfullname=result['companyFullName']
companysize=result['companySize']
positionname=result['positionName']
education=result['education']
financestage=result['financeStage']
salary=result['salary']
city=result['city']
positionadvantage=result['positionAdvantage']
info.append(companyfullname)
info.append(companysize)
info.append(positionname)
info.append(education)
info.append(financestage)
info.append(salary)
info.append(city)
info.append(positionadvantage)
totaljob.append(info)
return totaljob
if __name__=="__main__":
csvfile = file('lago.csv', 'wb')
writer = csv.writer(csvfile)
positions=['数据分析师','python工程师','business analyst','数据挖掘','数据库']
citys=['上海','杭州','北京','深圳','广州','西安','天津','南京']
job=[]
for position in positions:
for city in citys:
datas={'first':'true','pn':1,'kd':position}
url='https://www.lagou.com/jobs/positionAjax.json?px=default&city=%s&needAddtionalResult=false' %city
try:
totalpages=totalpage(url,datas,header)
except:
pass
time.sleep(5)
for page in range(1,totalpages):
detail=[]
data1={'first':'true','pn':page,'kd':position}
try:
details=info(url,data1,header)
except:
pass
for detail in details:
writer.writerow(detail)
csvfile.close()
总结
1、在开始做一个小爬虫测试的时候,发现'result':=[],是空的。后来问了下彭老师可能是编码问题。经过检查,发现开头第一行#-*-coding:‘'utf-8'-*-
不应该加引号。问题时我之前写七日热点的时候也木有出错啊。
2、爬虫速度太快,被网站拒绝链接而导致数据中断。程老师说需要加time.sleep()。延迟请求响应
3、爬取的时候,数据会中断。提示:ValueError:NO JSON OBJECT could be decoded.部分网站的没有json对象可以decoded。我一时也不知道怎么处理。程老师说做异常处理。只是这样会有部分信息丢失。我也不知道怎么更好的处理这种情况。如有有人知道,可以指导我。谢谢