2023年-7月份获取前程无忧岗位数据

1、前言

我们想要抓取前程无忧(https://we.51job.com/pc/search)的这些招聘信息。搜索关于python方面的招聘信息

2、分析

我们发现翻页请求的地址保持不变,这个就是反应了请求的是动态加载的数据

 然后我们来后台查看数据接口和返回的数据类型

我们发现这条接口(https://we.51job.com/api/job/search-pc?api_key=51job&timestamp=1689048587&keyword=python&searchType=2&function=&industry=&jobArea=000000&jobArea2=&landmark=&metro=&salary=&workYear=&degree=&companyType=&companySize=&jobType=&issueDate=&sortType=0&pageNum=1&requestId=&pageSize=20&source=1&accountId=&pageCode=sou%7Csou%7Csoulb)就是我们需要的

然后我们需要结合载荷简单分析这条链接的信息(可以设置页号为100,pageSize为500的,这样子可以多爬取多得)

 然后我们复制这个链接打开发现需要滑动验证

这些就是我们需要的数据集

2.5 selenium的作用

可以感受一下selenium的效果,

chromedriver.exe驱动下载地址(CNPM Binaries Mirror)注意该版本需要和你现在使用的版本一致

 

import os
import pandas as pd
from selenium import webdriver  # 版本号是3.141.0和urllib3需要降低版本是1.26.2
from selenium.webdriver import ActionChains
import time
import re
import urllib.parse


def save_progress(city, page):
    """保存第city个城市,第page页的数据到progress文件中"""
    with open('前程无忧断点记录.txt', 'w') as file:
        file.write(f'{city},{page}')


def load_progress():
    if os.path.exists('前程无忧断点记录.txt'):
        with open('前程无忧断点记录.txt', 'r') as file:
            """如果读到文件中保留的信息,就读取对应的数据"""
            progress = file.read().strip().split(',')
            if len(progress) == 2:
                return str(progress[0]), int(progress[1])
    # 读不到就返回默认页面和条数都为1
    return '010000', 1


def get_html(url):
    """配置chrome的一些相关配置"""
    chrome_driver = './chromedriver.exe'  # 导入Google驱动

    options = webdriver.ChromeOptions()  # 用于配置Chrome浏览器驱动程序的行为

    # options.add_argument("--headless")  # 无界面启动

    options.add_experimental_option('useAutomationExtension', False)  # 禁用Chrome的自动化拓展程序
    options.add_experimental_option('excludeSwitches', ['enable-automation'])  # 确保浏览器不会因为启用自动化模式而出现不必要的错误或异常。
    options.add_argument("--disable-blink-features=AutomationControlled")  # 禁用由自动化测试或脚本控制的 Blink 功能。
    # options.add_argument("--window-size=1200,800")#手动设置大小
    driver = webdriver.Chrome(chrome_options=options, executable_path=chrome_driver)

    # webdriver防屏蔽,不加这个就会出现滑动失败
    driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
        "source": """
        Object.defineProperty(navigator, 'webdriver', {
          get: () => false
        })
      """
    })
    driver.get(url)
    time.sleep(2)
    # 找到需要滑动的滑块元素
    slider = driver.find_element_by_xpath('//div[@class="nc_bg"]')
    # 创建操作链
    action_chains = ActionChains(driver)

    # 将鼠标移动到滑块上
    action_chains.move_to_element(slider)

    # 模拟按下鼠标左键并保持不松开
    action_chains.click_and_hold()

    # 移动鼠标使滑块达到目标位置
    action_chains.move_by_offset(100, -0.1)
    action_chains.move_by_offset(20, -0.14)
    action_chains.move_by_offset(100, 0.18)
    action_chains.move_by_offset(80, 0.11)
    time.sleep(0.5)

    # 松开鼠标左键
    action_chains.release()

    # 执行操作链
    action_chains.perform()

    time.sleep(3)

    html = driver.page_source  # 获取网页源码
    if "成功" in html:
        driver.quit()  # 清除后再退出
        return html
    else:
        with open('异常的数据页.txt', 'w', encoding='utf-8') as fp:
            fp.write(url)
        driver.quit()  # 清除后再退出
        return 0


def get_msg(start_citty, start_page):
    """解析页面提炼数据,每个城市最多展示1千条数据"""
    number = 0
    job_type = input("请输入你想要搜索的职位:")
    qwer = ['010000', '020000', '030000', '040000']  # 如果想多爬几个城市的就在这里加城市参数
    str_len = qwer.index(start_citty)
    for q in qwer[str_len:len(qwer)]:
        for page in range(start_page, 51):  # 页数
            try:
                print(f"正在爬取{q}的第" + str(page) + "页数据...")
                result = urllib.parse.quote(job_type)  # 编码
                url_start = 'https://we.51job.com/api/job/search-pc?api_key=51job&keyword=' + result

                # 删除&timestamp参数(时间搓),可以修改&pageSize的值,jobArea参数是城市(000000是全国,010000北京,030000广州,040000深圳)
                url_end = f'&searchType=2&function=&industry=&jobArea={q}&&jobArea2=&landmark=&metro=&salary=&workYear=&degree=&companyType=&companySize=&jobType=&issueDate=&sortType=0&pageNum=' \
                          + str(page) + '&requestId=&pageSize=20&source=1&accountId=&pageCode=sou%7Csou%7Csoulb'
                url = url_start + url_end
                msg = get_html(url)  # 用seleinum写的方法处理需要滑动进入,相当于这一部分可以拿到数据了
                msg = msg.replace('\\', '')  # 将用于转义的"\"替换为空
                # `(.*?)`表示任意我们想要的内容
                # `.*?`表示任意其他字符串
                reg = re.compile(
                    r'"jobName"\s*:\s*"([^"]*)".*?'  # 岗位名称
                    r'"cityString"\s*:\s*"([^"]*)".*?'  # 城市
                    r'"provideSalaryString"\s*:\s*"([^"]*)".*?'  # 薪资
                    r'"issueDateString"\s*:\s*"([^"]*)".*?'  # 发布时间
                    r'"workYearString"\s*:\s*"([^"]*)".*?'  # 需要工作经验
                    r'"degreeString"\s*:\s*"([^"]*)".*?'  # 入职条件
                    r'"companyName"\s*:\s*"([^"]*)".*?'  # 公司名称
                    r'"companyTypeString"\s*:\s*"([^"]*)".*?'  # 公司状态
                    r'"companySizeString"\s*:\s*"([^"]*)"',  # 公司人数
                    re.DOTALL)  # 表示可以用.代替任意字符(包括那些换行符)

                items = reg.findall(msg)  # 按照正则表达式规则查找
                a=[]
                for item in items:
                    number = number + 1
                    print(number, item[0], item[1], item[2], item[3], item[4], item[5], item[6], item[7], item[8])
                    s=[item[0], item[1], item[2], item[3], item[4], item[5], item[6], item[7], item[8]]
                    a.append(s)
                    save_progress(q, page + 1)
                    time.sleep(0.5)
                down_load(a)
                number=0
                a.clear()
            except Exception as e:
                """如果某一个城市爬完,就跳出循环,下一个城市继续"""
                print(e)
        time.sleep(3)
        start_page = 1


def down_load(data):
    # 定义列名
    columns = ['岗位名称', '公司所在城市地点',"薪资","发布时间","工作经验",'学历要求','公司名称','公司性质','公司人员规模']
    # 使用pandas包将列表和列名整合到数据框架中
    df = pd.DataFrame(data, columns=columns)
    # 将数据框架保存为CSV文件
    df.to_csv('前程无忧_51Job_岗位信息.csv', index=False,mode='a')


def main():
    start_citty, start_page = load_progress()  # 初始化页面和详情
    get_msg(start_citty, start_page)  # 使用函数


if __name__ == '__main__':
    main()

 3、版本选择

本次选择的是selenium==3.141.0+urllib3==1.26.1

因为我也是因为版本选择入了好多次坑,所以我把版本选择发出来,为了让更多人少拆坑。

4、编码

所有的解释我都放在代码里面了,几乎是每一行什么意思,我都解释了在代码中

完整代码

from selenium import webdriver#版本号是3.141.0和urllib3需要降低版本是1.26.2
from selenium.webdriver import ActionChains
import time

import re
import xlwt
import urllib.parse

def get_html(url):
    chrome_driver = './chromedriver.exe'  # 导入Google驱动

    options = webdriver.ChromeOptions()  # 用于配置Chrome浏览器驱动程序的行为

    options.add_argument("headless")  # 无界面启动

    options.add_experimental_option('useAutomationExtension', False)# 禁用Chrome的自动化拓展程序
    options.add_experimental_option('excludeSwitches', ['enable-automation'])# 确保浏览器不会因为启用自动化模式而出现不必要的错误或异常。
    options.add_argument("--disable-blink-features=AutomationControlled")# 禁用由自动化测试或脚本控制的 Blink 功能。
    driver = webdriver.Chrome(chrome_options=options, executable_path=chrome_driver)

    # webdriver防屏蔽,不加这个就会出现滑动失败
    driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
        "source": """
        Object.defineProperty(navigator, 'webdriver', {
          get: () => false
        })
      """
    })

    driver.get(url)

    time.sleep(1)
    # 找到需要滑动的滑块元素
    slider = driver.find_element_by_xpath('//div[@class="nc_bg"]')

    # 创建操作链
    action_chains = ActionChains(driver)

    # 将鼠标移动到滑块上
    action_chains.move_to_element(slider)

    # 模拟按下鼠标左键并保持不松开
    action_chains.click_and_hold()

    # 移动鼠标使滑块达到目标位置
    action_chains.move_by_offset(300, 0)

    # 松开鼠标左键
    action_chains.release()

    # 执行操作链
    action_chains.perform()

    time.sleep(10)

    html = driver.page_source#获取网页源码
    driver.quit()#清除后再退出

    return html


def get_msg(excel1, sheet1):
    number = 0
    job_type = input("请输入你想要搜索的职位:")
    for i in range(1, 20):  # 页数自己随便改
        try:
            print("正在爬取第" + str(i) + "页数据...")
            result = urllib.parse.quote(job_type)#编码
            url_start = 'https://we.51job.com/api/job/search-pc?api_key=51job&keyword=' + result

            # 删除&timestamp参数,修改&pageSize=500
            url_end = '&searchType=2&function=&industry=&jobArea=000000&jobArea2=&landmark=&metro=&salary=&workYear=&degree=&companyType=&companySize=&jobType=&issueDate=&sortType=0&pageNum=' \
                      + str(i) + '&requestId=&pageSize=1000&source=1&accountId=&pageCode=sou%7Csou%7Csoulb'
            url = url_start + url_end
            msg = get_html(url)#用seleinum写的方法处理需要滑动进入,相当于这一部分可以拿到数据了
            msg = msg.replace('\\', '')  # 将用于转义的"\"替换为空

            # `(.*?)`表示任意我们想要的内容
            # `.*?`表示任意其他字符串
            reg = re.compile(
                r'"jobName"\s*:\s*"([^"]*)".*?'
                r'"cityString"\s*:\s*"([^"]*)".*?'
                r'"provideSalaryString"\s*:\s*"([^"]*)".*?'
                r'"issueDateString"\s*:\s*"([^"]*)".*?'
                r'"workYearString"\s*:\s*"([^"]*)".*?'
                r'"degreeString"\s*:\s*"([^"]*)".*?'
                r'"companyName"\s*:\s*"([^"]*)".*?'
                r'"companyTypeString"\s*:\s*"([^"]*)".*?'
                r'"companySizeString"\s*:\s*"([^"]*)"',
                re.DOTALL)#表示可以用.代替任意字符(包括那些换行符)

            items = reg.findall(msg)#按照正则表达式规则查找

            for item in items:
                number = number + 1
                print(number,item[0],item[1],item[2],item[3],item[4],item[5],item[6],item[7],item[8])
                sheet1.write(number, 0, number)
                sheet1.write(number, 1, item[0])
                sheet1.write(number, 2, item[6])
                sheet1.write(number, 3, item[1])
                sheet1.write(number, 4, item[7])
                sheet1.write(number, 5, item[2])
                sheet1.write(number, 6, item[5])
                sheet1.write(number, 7, item[4])
                sheet1.write(number, 8, item[8])
                sheet1.write(number, 9, item[3])

                # 表格文件保存是可以选择两种情况,
                # 一种在for循环里面,每写一行保存一次,这样可以放在程序中途出现异常后,文件内容啥也没有
                # 另一种是在for循环之外,所有内容写完再保存
                excel1.save("51job.xlsx")
                time.sleep(0.5)  # 休息间隔
        except:
            pass

def creat_xls(excel1):
    # 设置单元格格式
    sheet1 = excel1.add_sheet('Job', cell_overwrite_ok=True)
    sheet1.write(0, 0, '序号')
    sheet1.write(0, 1, '职位')
    sheet1.write(0, 2, '公司名称')
    sheet1.write(0, 3, '公司地点')
    sheet1.write(0, 4, '公司性质')
    sheet1.write(0, 5, '薪资')
    sheet1.write(0, 6, '学历要求')
    sheet1.write(0, 7, '工作经验')
    sheet1.write(0, 8, '公司规模')
    sheet1.write(0, 9, '发布时间')
    return sheet1

def main():
    # 新建表格空间
    excel1 = xlwt.Workbook()#创建工作簿
    sheet1 = creat_xls(excel1)#创建工作表

    get_msg(excel1, sheet1)#使用函数

if __name__ == '__main__':
    main()

 5、结果

这个是正常的结果,存储到xls中了

评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值