1.目前测试情况看只能抓取头3页,后续得重新换cookie抓取。
2.如果登录自己boss账户,有可能导致账户临时被封,测试情况是个人账户被封了一个小时。

#!/usr/bin/python
# -*- coding:utf-8 -*-

import requests
from bs4 import BeautifulSoup
import time
import xlrd
import xlwt
import random
import datetime

# 将日志打印到下述文件
f = open("./test.log", 'w+')
# url:域名+地级市+区/县级市,以 '/' 结尾,例:https://www.zhipin.com/c101210100/b_%E6%BB%A8%E6%B1%9F%E5%8C%BA/
# job:岗位,例 PHP
# cookie:登录后的cookie,F12打开开发者模式,选择Network,点击Doc找到Request Headers下面的cookie,复制字符串
# path:Excel文档保存的路径,以 '/' 结尾
def spider4boss(url, job, cookie, path, page_start):
    # header头信息 模拟火狐浏览器,加上自己的 cookie
    headers = {
        'user-agent': 'Mozilla/5.0',
        'cookie': cookie
    }
    # 打开Excel表 定义sheet 定义表头
    workbook = xlwt.Workbook(encoding='utf-8')
    sheet = workbook.add_sheet('job_detail')
    head = ['职位名', '薪资', '公司名', '经验', '学历', '融资阶段', '公司人数', '发布时间', '实际经验要求', '岗位网址', 'JD ']
    for h in range(len(head)):
        sheet.write(0, h, head[h])
    row = 1  # 第0行用来写表头
    # 判断程序是否结束的标志位
    is_end = 0

    for page in range(page_start, page_start+3):  # boss每个ip一次只能爬3页
        # 一级url  c101210100:杭州市代号 b_%E6%BB%A8%E6%B1%9F%E5%8C%BA:滨江区转码
        main_url = url + "?query=" + job + "&page=" + str(page) + "&ka=page-" + str(page)
        print('第' + str(page) + '页  ' + main_url)
        hud = ['职位名', '薪资', '公司名', '经验', '学历', '融资阶段', '公司人数', '发布时间', '实际经验要求', '岗位网址', 'JD']
        print('\t'.join(hud))
        # 请求对象
        html = requests.get(main_url, headers=headers)
        # bs对象
        soup = BeautifulSoup(html.text, 'html.parser')
        #print(soup, file=f)
        # 标记 如果ip被反爬限制此行报错,这一步需要进行滑块验证
        # 安装Firefox后不再出现ip限制
        if soup.find('div', 'job-box') is None:
            print('又被限制ip了')
            return page_start
        # 判断该页是否已经无数据
        is_null = soup.find('div', 'job-box').find('div', 'job-list').find('ul')                    
                if len(is_null) == 1:  # 当前页面为空值为1说明该页无信息,退出循环
            # return 0  # 此处使用return返回不会进行Excel表保存,所以选择用break结束循环
            # 标志位,可以结束程序
            is_end = 1
            break
        for n in soup.find_all('div', 'job-primary'):
            res = []
            pass  # 不写pass上面行会出warning,强迫症必须消除
            res.append(n.find('div', 'job-title').find('a').string)  # 添加职位名
            res.append(n.find('span', 'red').string)  # 添加薪资
            res.append(n.find('div', 'company-text').find('a').string)  # 添加公司名
            require = n.find('div', 'info-primary').find('p').contents
            res.append(require[0])  # 添加地区
            res.append(require[2])  # 添加经验
            #res.append(require[4])  # 添加学历
            info = n.find('div', 'company-text').find('p').contents
            #res.append(info[0])  # 行业
            if 4 > len(info) > 2 and info[2].index('人') != 0:
                res.append('无信息')  # 融资
                res.append(info[2])  # 规模
            else:
                res.append(info[2])  # 融资
                res.append(info[4])  # 规模
            hr = n.find('div', 'info-publis').find('h3', 'name').contents
            #res.append(hr[3] + '--' + hr[1])  # 发布者
            res.append(n.find('div', 'job-title').find('span','job-pub-time').string)
            #if n.find('div', 'info-publis').find('p').string[3:] == '昨天':  # 如果发布时间是 "昨天",格式化为日期
            #    res.append(str(datetime.date.today()-datetime.timedelta(days=1))[5:])  # 发布时间
            #elif n.find('div', 'info-publis').find('p').string[5:6] == ':':
            #    res.append(str(datetime.date.today())[5:])  # 发布时间
            #else:  # 格式化日期
            #    res.append(n.find('div', 'info-publis').find('p').string[3:].replace('月', '-').replace('日', ''))
            job_detail = n.find('div', 'job-title').find('span', 'job-name').find('a')
            job_url = 'https://www.zhipin.com/' + job_detail['href']  # 岗位详情url
            # 提取真正的工作经验要求
            html2 = requests.get(job_url, headers=headers)
            soup2 = BeautifulSoup(html2.text, 'html.parser')
            # 标记 如果ip被反爬限制此行报错,下一步需要进行滑块验证
            # 安装Firefox后不再出现ip限制
            if soup2.find('div', 'job-sec') is None:
                print('又被限制ip了')
                return page_start
            job_sec = soup2.find('div', 'job-sec').find('div', 'text').contents
            exp = 0  # 初始为0 取到一个工作经验要求后置1
            # 将JD保存
            job_description = []
            for i in range(len(job_sec)):
                if i % 2 == 0:  # job_sec中还存了html标签 <br> 不是字符串,用find方法返回None,需要去除
                    job_description.append(job_sec[i])
                    # 确定位置                                                                                 
                    pot = job_sec[i].find('年')
                    if pot != -1 and exp == 0:
                        pot2 = job_sec[i].find('年以上')
                        if pot2 != -1:
                            # 再做一次判断,有的公司在数字后敲了空格
                            if job_sec[i][pot - 1:pot] == ' ':
                                res.append(job_sec[i][pot - 2:pot + 3])
                            else:
                                res.append(job_sec[i][pot - 1:pot + 3])
                        else:
                            if job_sec[i][pot - 1:pot] == ' ':
                                res.append(job_sec[i][pot - 2:pot + 1])
                            else:
                                res.append(job_sec[i][pot - 1:pot + 1])
                        # 只输出一个时间要求 不重复输出,需要用户手动检查岗位描述中的要求
                        exp = 1
            # 如果岗位描述中没有经验要求,填空字符
            if exp == 0:
                res.append('')
            res.append(job_url)  # 岗位描述链接
            job_description = ' '.join(job_description)[33:-29]
            res.append(job_description)  # 岗位描述
            # 写入Excel
            for i in range(len(res)):
                sheet.write(row, i, res[i])
            row += 1
            #print(res)
            # quit()
            time.sleep(random.randint(100, 500)/1000)
    workbook.save(path + str(datetime.date.today())[5:] + '_' + str(int(page_start/3+1)) + '_boss_job.xls')  # 保存Excel
    print('写入excel成功')
    if 0 == is_end:
        return 200
    else:
        return 0


def verify_slider():
    from selenium import webdriver
    from selenium.webdriver import ActionChains
    browser = webdriver.Firefox()
    browser.implicitly_wait(5)
    browser.get('https://www.zhipin.com/verify/slider')
    browser.execute_script("Object.defineProperties(navigator,{webdriver:{get:() => false}});")
    element = browser.find_element_by_id('nc_1_n1z')
    action = ActionChains(browser)
    action.drag_and_drop_by_offset(element, 280, 0).perform()
    time.sleep(5)
    browser.close()    

def rec_spider(page=1):
    res = spider4boss(url, job, cookie, path, page)
    if 200 == res:
        page += 3
        rec_spider(page)
    elif 200 > res > 0:
        print('在第 ' + str(res) + ' 页需要进行人机验证')
        # 调用验证方法进行验证
        verify_slider()
        # 继续爬取
        rec_spider(res)
    else:  # 爬取完成
        print('爬取完成')
        quit()


def merge_excel(date):
    pass


if __name__ == "__main__":
    cookie = 'Hm_lpvt_194df3105ad7148dcf2b98a91b5e727a=1585822170; Hm_lvt_194df3105ad7148dcf2b98a91b5e727a=1585819697,1585822166; __a=27860491.1585819695..1585819695.6.1.6.2; __l=l=%2Fwww.zhipin.com%2Fweb%2Fgeek%2Fchat%3Fka%3Dheader-message&r=&friend_source=0&g=%2Fwww.zhipin.com%2Fbeijing%2F%3Fsid%3Dsem_pz_bdpc_dasou_title&friend_source=0; __zp_stoken__=b67aky0C7VtMD%2Fpa0jX2j%2FVQSUxVDSdHyYt%2BCMenwdUjlJFNoctlW21JHqhbxHLLCbg2cSgMj7gGe7oIZpRAU6Ghs8YsUgf8chDqcQ8DgAI7KbhiNugjm0yxNosIk1aX15g7; __g=sem_pz_bdpc_dasou_title; __zp_seo_uuid__=ed543f89-cf6c-4764-882f-f8cf15281dbf; lastCity=101010100; sid=sem_pz_bdpc_dasou_title; _uab_collina=158581969696974364880318; __c=1585819695; _bl_uid=81kFe8Iqi0sk8a3Lsov96t3r67pL'
    #url = 'https://www.zhipin.com/c101210100/b_%E6%BB%A8%E6%B1%9F%E5%8C%BA/'
    url = 'https://www.zhipin.com/c101010100/'
    job = 'go'
    path = './'
    # spider4boss(url, job, cookie, path, 1)
    # verify_slider()
    rec_spider()                                                                                          

参考:
Python爬取Boss直聘上面的招聘信息

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐