51job 招聘岗位爬虫逆向
新人帖,佬勿喷
抓取站点:前程无忧
在线工具: 在线HmacSHA256
最近发现之前写的前程无忧岗位爬虫的代码没法用了,上去看了一眼,好家伙,网页渲染方式果然又又又更新了,之前的岗位数据是直接放在源码里的,现在放在了接口里。
用F12浅浅抓个包,就能很快找到找到接口。
这个接口是get请求方式,直接请求一下接口,发现鉴权失败,签名错误
,昂,果然有反爬措施。
回去看看接口的请求头部分,熟悉的大佬们一眼就能看出这个sign
非常可疑,结合刚刚的错误提示,可以知道,sign
就是signature
即签名的缩写。
按下Ctrl+Shift+F
,搜索下sign
。
可以看到有一大堆文件包含了sign
这个单词,首先排除css
文件,这种加密的参数大概率是由js
文件生成的。
在搜索出来的js
文件中再不断搜索关键词sign
,可以看到
return e.headers.sign = p.a.HmacSHA256(t, s["a"].state.commonStore.cupid_sign_key),
这块地方设置了headers.sign
属性,并且,这里使用了HmacSHA256
加密方式,这和我们需要破解的请求头sign
参数是相关联的,所以可以尝试一下,在前面打个断点,再搜索一次其他岗位,看看会不会断住。
可以看到,我们成功断点断住了。
在控制台里看一下加密方法中的参数
t
:'/open/noauth/search-pc?api_key=51job×tamp=1677644880&keyword=python%E5%AE%9E%E4%B9%A0%E7%94%9F&searchType=2&function=&industry=&jobArea=000000&jobArea2=&landmark=&metro=&salary=&workYear=°ree=&companyType=&companySize=&jobType=&issueDate=&sortType=0&pageNum=1&requestId=&pageSize=50&source=1&accountId=&pageCode=sou%7Csou%7Csoulb'
s["a"].state.commonStore.cupid_sign_key
:'abfc8f9dcf8c3f3d8aa294ac5f2cf2cc7767e5592590f39c3f503271dd68562b'
很明显,t
是请求的路径,那么s["a"].state.commonStore.cupid_sign_key
是什么呢?
我们在这个js
文件中查看一下,可以看到,key
是静态不变的,就是一个前端写好的加密密钥。
得到这样的结果,我们用在线HmacSHA256加密一下这两个参数,看看和这次请求的sign
是否对应
再看看这次请求的参数
没错,一毛一样,基本完工。
这里需要注意的是,每次搜索时,会对当前的关键词进行url
编码
可以拿在线工具对比一下。
接下来给出Python实现的爬虫代码,这里把数据存储为了csv
文件。
import hmac
from hashlib import sha256
import time
import requests
from urllib.parse import quote
import pandas as pd
# 实现 返回 hmac_sha256 算法
def hmac_sha256(key, value):
message = value.encode('utf-8')
return hmac.new(key.encode('utf-8'), message, digestmod=sha256).hexdigest()
# 抓取数据
# 参数为需要搜索的招聘信息内容,页码
def get_data(search,page):
target = "https://cupid.51job.com"
# hmac_sha256 密钥
key = "abfc8f9dcf8c3f3d8aa294ac5f2cf2cc7767e5592590f39c3f503271dd68562b"
# hmac_sha256 加密信息 时间戳 搜索的关键词
value = f"/open/noauth/search-pc?api_key=51job×tamp={str(int(time.time()))}&keyword={search}&searchType=2&function=&industry=&jobArea=000000&jobArea2=&landmark=&metro=&salary=&workYear=°ree=&companyType=&companySize=&jobType=&issueDate=&sortType=0&pageNum={page}&requestId=&pageSize=50&source=1&accountId=&pageCode=sou%7Csou%7Csoulb"
# 请求头
headers = {
"sign": hmac_sha256(key, value),
}
print("sign:",headers['sign'])
# 获取响应 json 格式化
response = requests.get(url=target+value,headers=headers).json()
return response
# 生成csv
# 参数 csv文件名,csv数据
def generate_csv(file_name,data):
csv_data = pd.DataFrame(data)
csv_data.to_csv(f"./{file_name}.csv")
def main():
#岗位
search_word = "python实习生"
# 最后的csv的数据
result = list()
# 对关键词进行url编码 否则无法实现中文爬虫
# 翻页
for page in range(1,10):
job_data = get_data(search=quote(search_word), page=page)["resultbody"]['job']["items"]
print(f"[Success] Crawler Page:{page} | OVER",)
result += job_data
# 生成csv
generate_csv(file_name=search_word, data=result)
print(f"[Success] Generate-Csv {search_word}.csv | OVER")
if __name__ == "__main__":
main()
看到评论反馈,发现上传帖子后value的变量值还有一些源码内容会发生改变
所以大家直接参考源码截图吧
有需要也可以直接下载源码
51jobs.zip
(215.91 KB, 下载次数: 101)
运行效果
csv预览