网上的各种爬虫方面的资料我都差不多了解了,感觉不知道该怎么提高,所以想看看人家招聘的职位要求是什么,好有个提高的方向。
选择了几个找工作的网站,感觉还是拉勾靠谱点,所以下面是获取拉勾网职位要求的代码。
注意:我抓的是任职要求,不是拉勾填充网页时的那个json包的数据,我感觉那个其实没什么用。~.~
开始:
# 初始化pymongo
def __init__(self):
self.client = pymongo.MongoClient(host = 'localhost')
self.ip_pool = self.client.ip
self.ua = self.ip_pool.ua
self.ip = self.ip_pool.ip_pool
# 这是我的ip和ua池
创建获取ua和ip的函数
def getUA(self):
return random.choice([i['ua'] for i in self.ua.find()])
# 选中的随机ua的格式是unicode,所以后来使用的时候,记得encode
def getIP(self):
return random.choice([i['ip'] for i in self.ip.find()])
def method(self,ip):
return {'http':'http://'+ip,'https':'https://'+ip}
# 这个函数是构造requests.get()中proxies参数
然后是get_content()函数
由于ip池内的ip或许在使用的时候正好失效了,所以最大允许三次重连的机会,如果三次之后还是不能用的话,就将这个目标网页放到无法抓取列表中,然后单独处理
# 想大批量抓取拉勾网的数据,却没有自己的ip和ua池的话,还是先把自己的池建好
def get_cotent(self,url,refer = None,params = None,try_time = 3):
headers = {
'User-Agent':self.getUA().encode('utf-8'),
'Referer':url
# 拉勾网对于referer头的检测相当严格,我建议使用当前的url最为referer头,因为刷新时,我验证头的时候,发现可以获取内容
}
if refer:
headers['Referer'] = refer
for i in range(try_time):
ip_pro = self.method(self.getIP())
# print ip_pro
response = self.get(url,headers,ip_pro,params)
# 到这里所有的数据都是必填的
if response:
return response
# 如果存在的话就返回,然后结束循环
else:
pass
def get(self,url,headers,ip_pro,params = None):
print url,headers,ip_pro
try:
response = requests.get(url,headers = headers,params = None,proxies = ip_pro)
time.sleep(random.randint(3,4))
except Exception as error:
print ('====>>>> is {}'.format(error))
return None
if response.status_code == 200 or response.status_code == 302:
print (response.url,'==ok')
return response
else:
print (response.url,'==no')
return None
# 各种不希望出现的情况,返回值全部设置为空
当写好get_content()函数后,开始写parse函数
def get_job_urls(self,response):
xresponse = etree.HTML(response.text)
job_urls = xresponse.xpath('//div[@class="p_top"]/a/@href')
return [''.join(i) for i in job_urls]
# 获取当前页的所有招聘职位的个人页面的地址列表
对职位的个人页面的职位要求的数据获取
def parse_job_require2(self,listed):
# 问题在于如何将不同格式的数据清理出来
# 拉勾网很鸡贼,一共大概有3-4种排版格式,好像
# 所以获取内容还是费了我一番心思的,如下
# 拉勾网的任职要求的数据,无论哪种格式都是p或者span的内容,所以对限定节点下的任意p和span内容进行获取
job_require_list = []
for i in listed:
try:
print 'url is {}'.format(i)
contain = ''
response = self.get_cotent(i,refer = i)
print ('wating ------')
print ('')
time.sleep(2)
if response:
xresponse = etree.HTML(response.text)
total = xresponse.xpath('//dd[@class="job_bt"]/div')
for i in total:
p = ''.join(i.xpath('.//p/text()'))
span = ''.join(i.xpath('.//span/text()'))
contain += p
contain += span
print contain
else:
print '所有ip都失败,记录下失败的html'
self.fail.append(i)
except Exception as error:
print error
注意几点:
1.如果ip不被允许访问的话,会直接获取不到内容,如果你测试连接使用的网址是baidu的话那么很可能百度能上,而拉勾不能上,这就是免费代理的坏处,毕竟用的人太多了
2.ua不被允许的话就会跳转到登录界面,这时候需要验证response.text的长度,登录界面的长度好像是552
3.我记得搜索之后的界面是json填充的,而那中首页可以点击直接进去的页面不是json填充的,json填充的页面:
params = {
"needAddtionalResult": False,
"isSchoolJob": 0
# 无关紧要,但还是加上去吧
}
data = {
'first':False # 是否是第一页?
}
kd = urllib.quote(keyword) # 汉字转码
data['pn'] = pn # 第几页
data['kd'] = keyword # 搜索关键字
# 添加类似的data和params参数就可以了