手把手教你,Python爬取招聘信息。一学就会,一写就废。
零基础的同学也能上手的,简单详细的python爬虫教学,也是经验的分享。
话不多说我们直接进入主题。
本次用到的python爬虫第三方库。
- requests:不是内置的,所以需要手动安装 => pip install requests
- re (正则表达式):用于requests爬取数据后进行解析,也是需要手动安装,==> pip install re 。
- Json :是一种轻量级的数据交换格式,易于人阅读和编写。
注意:(1)、因返回的数据较多,这里就不给予展示了。
(2)、代码是一段一段的,进行一步一步的讲解,最后会附上所有的源码。
一、爬虫数据思路
1.进入网址
网站连接可在代码中的 url 复制 ,因为某些不可说的原因。
输入python ,查找python招聘信息。
2.查看需要的数据在源码中的位置,判断是否为动态网页。
在源码里面进行搜索“python开发工程师”,找到其对应的位置。
在body标签中没有对应的数据,而在script中发现了数据所在。此时说明此网页是一个动态网页。可以利用re(正则表达式)来解析所需要数据。
二、代码
1.首先导入 requests 和 re模块
import requests
import re
import json
2.利用 requests 进行数据请求,此段代码有响应数据,这可以用此段代码。如果无数据或者乱码则用下面的代码。
import requests
import re
import json
#长类型字符串可以用 () 进行连接
'''
https://search.51job.com/list/000000,000000,0000,00,9,99,python,2,1.html?lang=c&postchannel=0000&workyear=99&cotype=99°reefrom=99&jobterm=99&companysize=99&ord_field=0&dibiaoid=0&line=&welfare=
'''
url = ('https://search.51job.com/list/000000,000000,0000,00,9,99,python,2,1.html?'
'lang=c&postchannel=0000&workyear=99&cotype=99&
degreefrom=99&jobterm=99&companysize=99&ord_field=0&dibiaoid=0&line=&welfare=')
resp = requests.get(url).text # .text 是属性,让返回的数据为文本格式
print(resp)
'''
如果有数据响应,并且和源码一样说明请求没问题,如果请求的是一串乱码或者没有数据。
可以加上 请求头(User-Agent) 和 Cookie
'''
Cookie的位置
请求头(User-Agent)的位置
url = ('https://search.51job.com/list/000000,000000,0000,00,9,99,python,2,1.html?'
'lang=c&postchannel=0000&workyear=99&cotype=99°reefrom=99&jobterm=99&companysize=99&ord_field=0&dibiaoid=0&line=&welfare=')
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36 Edg/100.0.1185.44",
"Cookie":"_uab_collina=165034940878617547028482; guid=22aac7caed33de3e1aa0a7e4c0d1cb66; nsearch=jobarea%3D%26%7C%26ord_field%3D%26%7C%26recentSearch0%3D%26%7C%26recentSearch1%3D%26%7C%26recentSearch2%3D%26%7C%26recentSearch3%3D%26%7C%26recentSearch4%3D%26%7C%26collapse_expansion%3D; slife=lowbrowser%3Dnot%26%7C%26; search=jobarea%7E%60000000%7C%21ord_field%7E%600%7C%21recentSearch0%7E%60000000%A1%FB%A1%FA000000%A1%FB%A1%FA0000%A1%FB%A1%FA00%A1%FB%A1%FA99%A1%FB%A1%FA%A1%FB%A1%FA99%A1%FB%A1%FA99%A1%FB%A1%FA99%A1%FB%A1%FA99%A1%FB%A1%FA9%A1%FB%A1%FA99%A1%FB%A1%FA%A1%FB%A1%FA0%A1%FB%A1%FApython%A1%FB%A1%FA2%A1%FB%A1%FA1%7C%21recentSearch1%7E%60000000%A1%FB%A1%FA000000%A1%FB%A1%FA0000%A1%FB%A1%FA00%A1%FB%A1%FA99%A1%FB%A1%FA%A1%FB%A1%FA99%A1%FB%A1%FA99%A1%FB%A1%FA99%A1%FB%A1%FA99%A1%FB%A1%FA9%A1%FB%A1%FA99%A1%FB%A1%FA%A1%FB%A1%FA0%A1%FB%A1%FApython%C5%C0%B3%E6%A1%FB%A1%FA2%A1%FB%A1%FA1%7C%21recentSearch2%7E%60190200%A1%FB%A1%FA000000%A1%FB%A1%FA0000%A1%FB%A1%FA00%A1%FB%A1%FA99%A1%FB%A1%FA%A1%FB%A1%FA99%A1%FB%A1%FA99%A1%FB%A1%FA99%A1%FB%A1%FA99%A1%FB%A1%FA9%A1%FB%A1%FA99%A1%FB%A1%FA%A1%FB%A1%FA0%A1%FB%A1%FApython%C5%C0%B3%E6%A1%FB%A1%FA2%A1%FB%A1%FA1%7C%21recentSearch3%7E%60000000%A1%FB%A1%FA000000%A1%FB%A1%FA0000%A1%FB%A1%FA00%A1%FB%A1%FA99%A1%FB%A1%FA%A1%FB%A1%FA99%A1%FB%A1%FA99%A1%FB%A1%FA12%A1%FB%A1%FA99%A1%FB%A1%FA9%A1%FB%A1%FA99%A1%FB%A1%FA%A1%FB%A1%FA0%A1%FB%A1%FAweb%C7%B0%B6%CB%A1%FB%A1%FA2%A1%FB%A1%FA1%7C%21recentSearch4%7E%60000000%A1%FB%A1%FA000000%A1%FB%A1%FA0000%A1%FB%A1%FA00%A1%FB%A1%FA99%A1%FB%A1%FA%A1%FB%A1%FA99%A1%FB%A1%FA99%A1%FB%A1%FA01%A1%FB%A1%FA99%A1%FB%A1%FA9%A1%FB%A1%FA99%A1%FB%A1%FA%A1%FB%A1%FA0%A1%FB%A1%FAweb%C7%B0%B6%CB%A1%FB%A1%FA2%A1%FB%A1%FA1%7C%21; partner=sem_pc360s1_29369; adv=ad_logid_url%3Dhttps%253A%252F%252Ftrace.51job.com%252Ftrace.php%253Fpartner%253Dsem_pc360s1_29369%2526ajp%253DaHR0cHM6Ly9ta3QuNTFqb2IuY29tL3RnL3NlbS9MUF8yMDIwXzEuaHRtbD9mcm9tPTM2MGFk%2526k%253D7d16490a53bc7f778963fbe04432456c%2526qhclickid%253Df5b179a19bec32c2%26%7C%26; acw_tc=76b20fee16504209993903119e78ac362eecffeaff8962fd8993f709e597a3; privacy=1650421060; acw_sc__v3=625f6d92716e3fa06b52c98c241a87f1989d43fe; ssxmod_itna=Yq+xyDnmDtYQqY5GHY+mDjxWqDKWh0oODr8Gu2g4GN4=oDZDiqAPGhDCb+KOhumuGtdQjfw3Ht0j8xKe6nACa+pCFZLeGLDmKDyCQiR4oD445GwD0eG+DD4DWDmWHDnxAQDjxGp9uXwV=Dm4GW8qGfDDoDYf6uDitD4qDBmOdDKqGg8qq5BA=PyRrMjmt5WmD48qDM0eGXnAaNpna7gGNP=PcxHgQDzLHDtqNMSLddx0PBldXx=gobmBvxKTwFCGGPGDxWC+4HK0GxYrqQDf5Q0AoY/24jXY8DG+Dtj0GdKiD===; ssxmod_itna2=Yq+xyDnmDtYQqY5GHY+mDjxWqDKWh0oODr8Gu2xA=ceD/0BQDFxruOtwk7hyp7KvOKC=7KGFD4E70hVi8QuTheBQ1KKIov6B8HG4V9WCBLmQwGotE8IOmYIOBF9K5r4DwwVy+CDMtGrv0ar2=BbqI2QY3Y4gmKoUEHH21WPW2hKinpi4gGdohurZpFba9HHh+mwEbikFb7bKxkLDxdrw+nsG8Lr6t9TkxAUe/SU+UL2d/TvtrGw46exiDpTqWgCGtGAtBAqxSbuszmKGaqA8iTOmL/Rmq6TFKHnG34b9E6w5gL99R3Xa+soEHULN5xs5hK4q1eda3QkkrYB4O2RYLTW4nCBbs3Ez=eWCQFSM=QlG2++E8z2RGVdo4OsUqNaqHe7Fim80QaKeh3kokxIB8F1Q+vlwIl+ekN5oG2f3umHSurO2WYE=6fbFPGLfE7dIr6EXe+QZO8dEFgARODpPIPYCedAwrPD7Q5lQPnP5ip5QwnhwS+GMS+S/YCnyhY=h0qfEhx6DKTml+pNBKtAvL2xNmpxwhos4ZYqIaqY7AYqx=ZqGGDYiw6Oe=AxDjKDeu3CAICKcMYdU8Dyiqg9D7A3hded7cM9ayxNN7xFgDCD4L/t7D4q0nhuxKyD8Y=BODKiDD==="
}
resp = requests.get(url,headers=headers).text
print(resp)
3.利用 re 正则解析 script 中的数据,并进行数据清洗
re.findall(pattern,string,flags=0) :返回string中所有与pattern匹配的全部字符串,返回形式为数组。
re.S:如果不使用re.S参数,则只在每一行内进行匹配,如果一行没有,就换下一行重新开始。而使用re.S参数以后,正则表达式会将这个字符串作为一个整体,在整体中进行匹配。
r = re.findall('window.__SEARCH_RESULT__ = (.*?)</script>',resp,re.S)
r_string = ''.join(r) # 去掉空白内容
print(r_string)
r_dic=json.loads(r_string) #转换成字典格式
print(r_dic)
print(r_dic["engine_jds"]) #获取的是数组格式的数据
print(r_dic["engine_jds"][0]["job_name"]) #获取岗位名称
print(r_dic)的返回结果
print(r_dic["engine_jds"]) 的返回结果
print(r_dic["engine_jds"][0]["job_name"]) 的返回结果
4.遍历获取数据
此时能获取到具体的数据,距离成功也就越来越近了。我抓取的数据是一页的数据,但是一页中有很多的岗位信息,所以我们要进行遍历,获取每一个岗位的具体信息。
for r_index in r_dic["engine_jds"]:
print(r_index["company_name"]) #公司名称
print(r_index["companytype_text"]) #企业类别
print(r_index["job_name"]) #岗位名称
print(r_index["providesalary_text"]) #岗位薪水jobwelf
print(r_index["jobwelf"]) #岗位福利
print(r_index["attribute_text"]) #岗位地区和岗位要求
break
#遍历一次看看信息是否正确
5.保存本地文件
注意:用 open("path","a") ,a 的方式进行存储时,如果文件存在就会报错。这里我只进行了一次存储后就 break 掉了,所以只有一条数据。要进行多次存储去掉break就行。
for r_index in r_dic["engine_jds"]:
company_name=r_index["company_name"] #公司名称
companytype_text=r_index["companytype_text"] #企业类别
job_name=r_index["job_name"] #岗位名称
providesalary_text=r_index["providesalary_text"]#岗位薪水jobwelf
jobwelf=r_index["jobwelf"] #岗位福利
attribute_text=r_index["attribute_text"]#岗位地区和岗位要求
f = open("csdn_51job.csv",'a') # 用 a(追加) 的方式 进行数据存储
f.write(f"{company_name},{companytype_text},{job_name},{providesalary_text},{jobwelf},{','.join(attribute_text)}") #把获取到的数据写入文件
f.close() #最好一定要记住关闭文件
break
csdn_51job.csv 文件内容如下:
6.最后进行多次多页爬取数据。
(1). 思路
设置的页数,在url肯定是有规律的,所以观察两个 url 的区别即可。
知道差别后进行 for 循环遍历即可。
三、最后附上完整的代码 ,这里我只爬取了一页数据,还是一样,想要多页去掉break即可
import json
import requests
import re
for pageindex in range(1,500): #多页数爬取
print(f'第{pageindex}页开始')
#进行请求url
url = (f'https://search.51job.com/list/000000,000000,0000,00,9,99,python,2,{pageindex}.html?'
'lang=c&postchannel=0000&workyear=99&cotype=99°reefrom=99&jobterm=99&companysize=99&ord_field=0&dibiaoid=0&line=&welfare=')
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36 Edg/100.0.1185.44",
"Cookie":"_uab_collina=165034940878617547028482; guid=22aac7caed33de3e1aa0a7e4c0d1cb66; nsearch=jobarea%3D%26%7C%26ord_field%3D%26%7C%26recentSearch0%3D%26%7C%26recentSearch1%3D%26%7C%26recentSearch2%3D%26%7C%26recentSearch3%3D%26%7C%26recentSearch4%3D%26%7C%26collapse_expansion%3D; slife=lowbrowser%3Dnot%26%7C%26; search=jobarea%7E%60000000%7C%21ord_field%7E%600%7C%21recentSearch0%7E%60000000%A1%FB%A1%FA000000%A1%FB%A1%FA0000%A1%FB%A1%FA00%A1%FB%A1%FA99%A1%FB%A1%FA%A1%FB%A1%FA99%A1%FB%A1%FA99%A1%FB%A1%FA99%A1%FB%A1%FA99%A1%FB%A1%FA9%A1%FB%A1%FA99%A1%FB%A1%FA%A1%FB%A1%FA0%A1%FB%A1%FApython%A1%FB%A1%FA2%A1%FB%A1%FA1%7C%21recentSearch1%7E%60000000%A1%FB%A1%FA000000%A1%FB%A1%FA0000%A1%FB%A1%FA00%A1%FB%A1%FA99%A1%FB%A1%FA%A1%FB%A1%FA99%A1%FB%A1%FA99%A1%FB%A1%FA99%A1%FB%A1%FA99%A1%FB%A1%FA9%A1%FB%A1%FA99%A1%FB%A1%FA%A1%FB%A1%FA0%A1%FB%A1%FApython%C5%C0%B3%E6%A1%FB%A1%FA2%A1%FB%A1%FA1%7C%21recentSearch2%7E%60190200%A1%FB%A1%FA000000%A1%FB%A1%FA0000%A1%FB%A1%FA00%A1%FB%A1%FA99%A1%FB%A1%FA%A1%FB%A1%FA99%A1%FB%A1%FA99%A1%FB%A1%FA99%A1%FB%A1%FA99%A1%FB%A1%FA9%A1%FB%A1%FA99%A1%FB%A1%FA%A1%FB%A1%FA0%A1%FB%A1%FApython%C5%C0%B3%E6%A1%FB%A1%FA2%A1%FB%A1%FA1%7C%21recentSearch3%7E%60000000%A1%FB%A1%FA000000%A1%FB%A1%FA0000%A1%FB%A1%FA00%A1%FB%A1%FA99%A1%FB%A1%FA%A1%FB%A1%FA99%A1%FB%A1%FA99%A1%FB%A1%FA12%A1%FB%A1%FA99%A1%FB%A1%FA9%A1%FB%A1%FA99%A1%FB%A1%FA%A1%FB%A1%FA0%A1%FB%A1%FAweb%C7%B0%B6%CB%A1%FB%A1%FA2%A1%FB%A1%FA1%7C%21recentSearch4%7E%60000000%A1%FB%A1%FA000000%A1%FB%A1%FA0000%A1%FB%A1%FA00%A1%FB%A1%FA99%A1%FB%A1%FA%A1%FB%A1%FA99%A1%FB%A1%FA99%A1%FB%A1%FA01%A1%FB%A1%FA99%A1%FB%A1%FA9%A1%FB%A1%FA99%A1%FB%A1%FA%A1%FB%A1%FA0%A1%FB%A1%FAweb%C7%B0%B6%CB%A1%FB%A1%FA2%A1%FB%A1%FA1%7C%21; partner=sem_pc360s1_29369; adv=ad_logid_url%3Dhttps%253A%252F%252Ftrace.51job.com%252Ftrace.php%253Fpartner%253Dsem_pc360s1_29369%2526ajp%253DaHR0cHM6Ly9ta3QuNTFqb2IuY29tL3RnL3NlbS9MUF8yMDIwXzEuaHRtbD9mcm9tPTM2MGFk%2526k%253D7d16490a53bc7f778963fbe04432456c%2526qhclickid%253Df5b179a19bec32c2%26%7C%26; acw_tc=76b20fee16504209993903119e78ac362eecffeaff8962fd8993f709e597a3; privacy=1650421060; acw_sc__v3=625f6d92716e3fa06b52c98c241a87f1989d43fe; ssxmod_itna=Yq+xyDnmDtYQqY5GHY+mDjxWqDKWh0oODr8Gu2g4GN4=oDZDiqAPGhDCb+KOhumuGtdQjfw3Ht0j8xKe6nACa+pCFZLeGLDmKDyCQiR4oD445GwD0eG+DD4DWDmWHDnxAQDjxGp9uXwV=Dm4GW8qGfDDoDYf6uDitD4qDBmOdDKqGg8qq5BA=PyRrMjmt5WmD48qDM0eGXnAaNpna7gGNP=PcxHgQDzLHDtqNMSLddx0PBldXx=gobmBvxKTwFCGGPGDxWC+4HK0GxYrqQDf5Q0AoY/24jXY8DG+Dtj0GdKiD===; ssxmod_itna2=Yq+xyDnmDtYQqY5GHY+mDjxWqDKWh0oODr8Gu2xA=ceD/0BQDFxruOtwk7hyp7KvOKC=7KGFD4E70hVi8QuTheBQ1KKIov6B8HG4V9WCBLmQwGotE8IOmYIOBF9K5r4DwwVy+CDMtGrv0ar2=BbqI2QY3Y4gmKoUEHH21WPW2hKinpi4gGdohurZpFba9HHh+mwEbikFb7bKxkLDxdrw+nsG8Lr6t9TkxAUe/SU+UL2d/TvtrGw46exiDpTqWgCGtGAtBAqxSbuszmKGaqA8iTOmL/Rmq6TFKHnG34b9E6w5gL99R3Xa+soEHULN5xs5hK4q1eda3QkkrYB4O2RYLTW4nCBbs3Ez=eWCQFSM=QlG2++E8z2RGVdo4OsUqNaqHe7Fim80QaKeh3kokxIB8F1Q+vlwIl+ekN5oG2f3umHSurO2WYE=6fbFPGLfE7dIr6EXe+QZO8dEFgARODpPIPYCedAwrPD7Q5lQPnP5ip5QwnhwS+GMS+S/YCnyhY=h0qfEhx6DKTml+pNBKtAvL2xNmpxwhos4ZYqIaqY7AYqx=ZqGGDYiw6Oe=AxDjKDeu3CAICKcMYdU8Dyiqg9D7A3hded7cM9ayxNN7xFgDCD4L/t7D4q0nhuxKyD8Y=BODKiDD==="
}
resp = requests.get(url,headers=headers).text
#用re进行数据解析
r = re.findall('window.__SEARCH_RESULT__ = (.*?)</script>',resp,re.S)
r_string = ''.join(r)
r_dic=json.loads(r_string) #转换成字典格式
#遍历每一页的数据
for r_index in r_dic["engine_jds"]:
company_name=r_index["company_name"] #公司名称
companytype_text=r_index["companytype_text"] #企业类别
job_name=r_index["job_name"] #岗位名称
providesalary_text=r_index["providesalary_text"]#岗位薪水jobwelf
jobwelf=r_index["jobwelf"] #岗位福利
attribute_text=r_index["attribute_text"]#岗位地区和岗位要求
#存储所解析的数据到 csdn_51job.csv 文件中
f = open("csdn_51job.csv",'a') # 用 a(追加) 的方式 进行数据存储 ,前提:csdn_51job.csv文件必须由系统创建
f.write(f"{company_name},{companytype_text},{job_name},{providesalary_text},{jobwelf},{','.join(attribute_text)}\n") #把获取到的数据写入文件
f.close() #最好一定要记住关闭文件
print(f'第{pageindex}页结束')
break
这段代码存在一个BUG,也就是网站的一个反爬机制,人机验证的一个拖拽验证。
所以会报错
r_string = ''.join(r)
r_dic=json.loads(r_string)
这段代码会报一个这个错误: json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
究其原因也就是 r_string 会返回一个空列表,json.loads() 方法就报错了。
其实也不是什么大问题。代码用肯定是能用的,过个把小时就能用了。
解决办法:解决滑块验证的问题