本人最近由于失业,需要求职,去了很多求职网站,特发其想,想知道现在的人才市场行情,所以写了个爬虫来了解一下。
*本爬虫用于学习交流使用,请勿用于商业用途,使用时请遵守第三方网站的相关要求。
由于近期主要在BOSS直聘上投简历,而大多的回复都是在BOSS直聘上的,所以突发其想,就去研究一下上面的市场状况
前期说明:
本爬早用到的库有如下:
requests:这个是获取响应对象的
lxml:用lxml+xpath快速可以获取相要的内容,速度比BeautifulSoup快
pandas:将获取到的内容保存为csv文件,而且用pandas的话,可以节省几行代码
time:爬虫在爬取过程中需要休眠,减轻网站压力
现在正式开始爬虫:
第一步:导入相对应的包
# Power by JackyHon 2018-09-13
# 文件仅供学习使用,他用无效
# 使用时请遵守第三方网站的规定或查看robots.txt
import requests
from lxml import etree
import pandas as pd
import time
第二步:为了给代码解耦,所以将获取网站response对象(如果不知道什么是response对象的话,真心要百度一下再学爬虫吧)的功能封装在一起。其次,按照惯例还是创建一个head信息,模拟浏览器行为。这段代码有个心比较大的地方,就是exception,这里我直接写Exception,只要出错就退出。
# 获取网站对象的函数,获取boss直聘上的信息
def spider(query, page):
query = query
# 创造headers
head = {'User-Agent': "Mozilla/5.0 (Windows NT 6.1; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36"}
while True:
try:
# 构造需要爬取的URL,由于后续需要使用lxml,所以需要转换编码utf8
url = 'https://www.zhipin.com/c101280100/h_101280100/?query={0}&page={1}'.format(query, page)
response_obj = requests.get(url=url, headers=head)
response_obj.encoding = 'utf8'
return response_obj
except Exception:
print('-'*20 + '退出搜索'+'-'*20)
break
第三步:对获取的response对象做解释,获取我想要的数据
因为我是刚用xpath,所以不是太熟悉,但是用了之后觉得xpath真是太好用了,速度快,爬取路径直观,比BeautifulSoup效率高,当然,也是有一定学习成本。
def get_data(response_obj):
detail = []
# 为了构造职位详细信息的URL前缀
front_url = 'https://www.zhipin.com'
html = etree.HTML(response_obj.text, parser=etree.HTMLParser(encoding='utf-8'))
# 获取职位名称
job_title = html.xpath("//div[@class='job-title']/text()")
# 获取薪水范围
salary = html.xpath("//span[@class='red']/text()")
# 获取公司名称
company = html.xpath("//div[@class='company-text']/h3/a/text()")
# 获取地区,经验,学位
area_ex_degree = html.xpath("//div[@class='info-primary']/p/text()")
# 获取职位详情URL后缀,后期需要用front_url+后缀组合成完成的职位详情URL
link = html.xpath("div[@class='info-primary']/h3/a/@href")
# 详情分组
for i in range(0, len(area_ex_degree), 3):
detail.append(area_ex_degree[i:i+3])
# 获取发布时间
date_of_issue = html.xpath("//div[@class='info-publis']//p/text()")
# 以字典形式返回结果
return {'job_title': job_title,
'salary': salary,
'company': company,
'detail': detail,
'publish_date': date_of_issue,
'detail_link': [front_url+i for i in link]
}
第四步:主要的功能模块编写完毕,然后就是到主程序这块了。由于需要连续获取网页信息,所以主程序中需要有循环控制。由于BOSS直聘上搜索任何关键词,最多返回10页的搜索结果,而问题就在于如何判断是最后一页,所以这里用到
if set(result['company']) > set(get_data(obj)['company'])
来判断最后一页爬取的是否已经爬取过,如果是则退出程序;如果不是则添加进结果,程序继续爬取。
# 启动爬虫
if __name__ == '__main__':
# 储存爬取结果
result = None
# 循环标记
flag = True
# 从第1页开始
pg = 1
# 输入需要搜索的职位关键字
words = input('请输入需要搜索的关键字:')
while flag:
obj = spider(words, pg)
if result is None:
print('第{}页'.format(pg))
result = get_data(obj)
print(result.keys(), ":", result.values())
else:
if set(result['company']) > set(get_data(obj)['company']):
flag = False
print('程序结束')
else:
print('第{}页'.format(pg))
for key, value in get_data(obj).items():
result[key].extend(value)
print(key, ":", value)
pg = pg + 1
# 为了减轻服务器负担,所以选择休眠3秒
time.sleep(3)
data = pd.DataFrame(result)
data.to_csv('{}.csv'.format(words), encoding='gbk')
最后,程序会将爬取的结果保存为CSV文件,为什么保存CSV呢?因为人家给你撑死才300条数据啊,还用鬼数据库啊?
针对爬取的结果,可以自己再做数据归纳整理。后面若我有空的话,会继续补充。多多交流!
后记:
其实这个爬虫可以用scrapy写,但是如果用scrapy的话,就整个功能基本写好了,犹其是保存数据部分,真心方便,缺少了思考,所以最后还是用最原始的方法尝试。本人水平一般,请多多见谅!