当前位置: 首页 > article >正文

Python爬虫实战:利用代理IP获取招聘网站信息

文章目录

  • 一、前言
  • 二、爬取目标
  • 三、为什么要使用代理IP?
  • 四、准备工作
    • 4.1 编程环境准备
    • 4.2 获取代理IP
  • 五、爬虫代码实战
    • 5.1 翻页分析
    • 5.2 数据位置分析
    • 5.3 获取日志列表
    • 5.4 获取接口数据
    • 5.5 将数据保存到Excel
    • 5.6 完整源码
    • 5.7 爬取结果展示
  • 六、总结

一、前言

马上就要到一年一度的跳槽季(金三四银),应粉丝要求,这篇文章来教教大家怎么批量获取你的 “目标岗位” 招聘信息,附上代码思路和完整源码,话不多说请看下文~

二、爬取目标

爬虫目标为某招聘网站,首先可以看到博主这里没有登录注册也可以岗位信息,那接下来写代码就不用去登录:
https://www.liepin.com

三、为什么要使用代理IP?

使用代理IP可以带来以下好处:

  • 匿名保护,保护隐私安全
  • 安全采集公开数据信息
  • 分散访问压力,提高爬取效率和稳定性。
  • 收集不同地区或代理服务器上的数据,用于数据分析和对比。

博主使用的是亮数据家的动态住宅代理IP,因为是住宅IP隐匿性更强,动态切换安全性更高,个人感觉还不错,并且可以免费使用:

四、准备工作

4.1 编程环境准备

Python:3.10

编辑器:PyCharm

第三方模块,自行安装:

pip install pandas # 数据处理
pip install requests # 网页数据爬取
pip install selenium # 自动化操作浏览器

使用selenium还需要安装谷歌浏览器,下载配置浏览器驱动WebDriver,不会配置驱动的小伙伴请看这篇文章:https://blog.csdn.net/yuan2019035055/article/details/125772198

4.2 获取代理IP

1、首先打开官网:亮数据官网

2、填写信息:

3、填写完上图中的注册页面信息,点击“新建账户”提交后,网页会显示(如下图)验证邮件已发送至注册邮箱:

4、很快就可以在注册邮箱里(如下图),找到一封名为“Bright Data - Welcome”的验证邮件,点击登录,即可直接进入产品界面,开始使用。此时完成所有注册步骤均已完成:

5、注册登录后,在控制台选择查看代理IP产品:

6、选择住宅代理:

7、如果特殊需求默认配置即可,然后点击添加:

8、勾选确定:

9、参考代码语言选择Python,然后找到你的代理IP链接:

10、代码设置代理IP链接:

proxies = {
    'http': '放置你的代理url',
    'https': '放置你的代理url'
}

五、爬虫代码实战

5.1 翻页分析

博主通过删除url的参数发现,只有三个参数是有用的,city控制:城市,currentPage控制:页码,key控制:关键词

那么Python代码中我们就可以分别传入上面三个参数:

key = 'Python爬虫工程师'  # 需要检索的岗位
city_code = '410'  # 城市代码(自行从官网选择城市后查找)
page_num = 1  # 爬取的页数
for currentPage in range(0,page_num):
    url =f'https://www.liepin.com/zhaopin/?city={city_code}&currentPage={currentPage}&key={key}'

5.2 数据位置分析

1、我们打开网页,右键或者按f12点开检查,然后点击Network,然后刷新网页:

2、根据下面图片操作找到接口中的数据:

3、点击Headers查看接口地址,等一下我们需要用到:

5.3 获取日志列表

下面这段代码主要用于使用Selenium WebDriver启动Chrome浏览器,访问指定的招聘网站页面,并获取该页面加载过程中的性能日志(特别是网络请求日志)。通过配置DesiredCapabilities和ChromeOptions,可以定制浏览器的启动行为和日志记录偏好。最后,通过解析性能日志的JSON数据,可以获取到详细的网络请求信息:

# 导入Selenium WebDriver的DesiredCapabilities模块,用于设置浏览器的一些高级配置
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
# 导入Selenium的webdriver模块,用于控制浏览器
from selenium import webdriver
# 导入json模块,用于处理JSON数据
import json


def get_data(url):
    # 创建一个ChromeOptions对象,用于配置Chrome浏览器的启动选项
    chrome_options = webdriver.ChromeOptions()
    # 添加一个实验性选项,启用W3C标准模式
    chrome_options.add_experimental_option('w3c', True)
    # 获取Chrome浏览器的默认配置
    caps = DesiredCapabilities.CHROME
    # 设置日志偏好,这里特别指定了性能日志(performance)记录所有信息
    caps["goog:loggingPrefs"] = {"performance": "ALL"}
    # 使用指定的配置和选项启动Chrome浏览器
    driver = webdriver.Chrome(desired_capabilities=caps, options=chrome_options)  # 启动浏览器
    # 设置隐式等待时间,单位为秒,这里设置为8秒,用于等待页面元素加载完成
    driver.implicitly_wait(8)
    # 访问指定的URL
    driver.get(url)  # 打开网页
    # 获取网络请求日志
    # 通过driver.get_log('performance')获取性能日志,然后使用列表推导式解析日志中的JSON数据
    logs = [json.loads(log['message'])['message'] for log in driver.get_log('performance')]
    # 遍历日志列表,并打印每条日志
    for log in logs:
        print(log)


# 定义要访问的URL,这里是一个招聘网站的链接,搜索Python爬虫工程师
url = 'https://www.liepin.com/zhaopin/?city=410&currentPage=1&key=Python%E7%88%AC%E8%99%AB%E5%B7%A5%E7%A8%8B%E5%B8%88'
get_data(url)

运行结果,可以看到有很多请求链接:

问题来了,怎么从那么多请求信息中找到我们需要的数据接口?

通过if判断限制结果只返回我们刚才找到的数据接口:

# 判断限制结果只返回我们刚才找到的数据接口
if log['method'] == 'Network.responseReceived' and 'https://api-c.liepin.com/api/com.liepin.searchfront4c.pc-search-job' in log['params']['response']['url']:
    print(log)

运行结果:

5.4 获取接口数据

通过日志解析,接口中的数据:

def get_data(url, data_list):
    """定义一个函数,用于从指定URL获取数据并填充到data_list列表中"""
    # 创建一个ChromeOptions对象,用于配置Chrome浏览器的启动选项
    chrome_options = webdriver.ChromeOptions()
    # 添加一个实验性选项,启用W3C标准模式,这对于与WebDriver的交互很重要
    chrome_options.add_experimental_option('w3c', True)
    # 获取Chrome浏览器的默认配置
    caps = DesiredCapabilities.CHROME
    # 设置日志偏好,这里特别指定了性能日志(performance)记录所有信息,用于后续分析网络请求
    caps["goog:loggingPrefs"] = {"performance": "ALL"}
    # 使用指定的配置和选项启动Chrome浏览器
    driver = webdriver.Chrome(desired_capabilities=caps, options=chrome_options)  # 启动浏览器
    # 设置隐式等待时间,单位为秒,这里设置为8秒,用于等待页面元素加载完成
    driver.implicitly_wait(8)
    # 访问指定的URL
    driver.get(url)  # 打开网页
    # 获取网络请求日志
    # 通过driver.get_log('performance')获取性能日志,然后使用列表推导式解析日志中的JSON数据
    logs = [json.loads(log['message'])['message'] for log in driver.get_log('performance')]
    # 遍历日志列表,并打印每条日志
    for log in logs:
        # 判断限制结果只返回我们刚才找到的数据接口(根据URL判断)
        if log['method'] == 'Network.responseReceived' and 'https://api-c.liepin.com/api/com.liepin.searchfront4c.pc-search-job' in \
                log['params']['response']['url']:
            requestId = log['params']['requestId']
            try:
                # 使用Chrome DevTools Protocol (CDP) 获取响应体
                response_dict = driver.execute_cdp_cmd('Network.getResponseBody', {'requestId': requestId})
                body = response_dict["body"]
                body_dict = json.loads(body)  # 将响应体解析为JSON
                # 尝试从JSON响应中提取具体的数据
                try:
                    jobCardList = body_dict['data']['data']['jobCardList']
                    print(len(jobCardList))  # 打印找到的岗位数量
                    for i in jobCardList:
                        # 尝试提取每个岗位的具体信息,如果提取失败则设置为None
                        try:
                            compName = i['comp']['compName']  # 公司名称
                        except:
                            compName = None
                        try:
                            compScale = i['comp']['compScale']  # 公司规模
                        except:
                            compScale = None

                        try:
                            compStage = i['comp']['compStage']  # 公司发展阶段
                        except:
                            compStage = None
                        try:
                            compIndustry = i['comp']['compIndustry']  # 行业
                        except:
                            compIndustry = None
                        try:
                            title = i['job']['title']  # 岗位名称
                        except:
                            title = None
                        try:
                            salary = i['job']['salary']  # 薪资
                        except:
                            salary = None
                        try:
                            dq = i['job']['dq']  # 办公地点
                        except:
                            dq = None
                        try:
                            requireWorkYears = i['job']['requireWorkYears']  # 年限要求
                        except:
                            requireWorkYears = None
                        try:
                            requireEduLevel = i['job']['requireEduLevel']  # 学历要求
                        except:
                            requireEduLevel = None

                        # 打印并添加到data_list列表中
                        print(
                            {'岗位名称': title, '薪资': salary, '办公地点': dq, '年限要求': requireWorkYears, '学历要求': requireEduLevel,
                             '公司名称': compName, '规模': compScale, '阶段': compStage, '行业': compIndustry})
                        data_list.append(
                            {'岗位名称': title, '薪资': salary, '办公地点': dq, '年限要求': requireWorkYears, '学历要求': requireEduLevel,
                             '公司名称': compName, '规模': compScale, '阶段': compStage, '行业': compIndustry})
                except:
                    print('body err!')  # 如果解析JSON时出错,打印错误信息
            except:
                pass  # 如果获取响应体时出错,则忽略
            print('------------')  # 打印分隔符,便于查看日志输出

运行结果打印所有数据:

5.5 将数据保存到Excel

将获取到的数据写入Excel:

def to_excel(data_list):
    """写入Excel"""
    df = pd.DataFrame(data_list)
    df.drop_duplicates() # 删除重复数据
    df.to_excel('招聘信息.xlsx')

5.6 完整源码

由于招聘网站反爬虫比较厉害,多次翻页就不会返回数据了,所以我们需要给下面的函数加上proxies参数,需要看4.2获取并修改proxies中的代理IP链接。还可以修改关键词、爬取的页数和城市代码(自行从官网选择城市后查找):

# 导入Selenium WebDriver的DesiredCapabilities模块,用于设置浏览器的一些高级配置
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
# 导入Selenium的webdriver模块,用于控制浏览器
from selenium import webdriver
# 用于写入Excel文件
import pandas as pd
# 导入json模块,用于处理JSON数据
import json
import time


def get_data(url, data_list):
    """定义一个函数,用于从指定URL获取数据并填充到data_list列表中"""

    # 创建一个ChromeOptions对象,用于配置Chrome浏览器的启动选项
    chrome_options = webdriver.ChromeOptions()
    # 添加代理IP
    proxies = {
        'http': '放置你的代理url',  # 需要看4.2自行获取代理IP链接
        'https': '放置你的代理url'  # 需要看4.2自行获取代理IP链接
    }
    chrome_options.add_argument(f'--proxy-server=http://{proxies}')
    # 添加一个实验性选项,启用W3C标准模式,这对于与WebDriver的交互很重要
    chrome_options.add_experimental_option('w3c', True)
    # 获取Chrome浏览器的默认配置
    caps = DesiredCapabilities.CHROME
    # 设置日志偏好,这里特别指定了性能日志(performance)记录所有信息,用于后续分析网络请求
    caps["goog:loggingPrefs"] = {"performance": "ALL"}
    # 使用指定的配置和选项启动Chrome浏览器
    driver = webdriver.Chrome(desired_capabilities=caps, options=chrome_options)  # 启动浏览器
    # 设置隐式等待时间,单位为秒,这里设置为8秒,用于等待页面元素加载完成
    driver.implicitly_wait(8)
    # 访问指定的URL
    driver.get(url)  # 打开网页
    # 获取网络请求日志
    # 通过driver.get_log('performance')获取性能日志,然后使用列表推导式解析日志中的JSON数据
    logs = [json.loads(log['message'])['message'] for log in driver.get_log('performance')]
    # 遍历日志列表,并打印每条日志
    for log in logs:
        # 判断限制结果只返回我们刚才找到的数据接口(根据URL判断)
        if log['method'] == 'Network.responseReceived' and 'https://api-c.liepin.com/api/com.liepin.searchfront4c.pc-search-job' in \
                log['params']['response']['url']:
            requestId = log['params']['requestId']
            try:
                # 使用Chrome DevTools Protocol (CDP) 获取响应体
                response_dict = driver.execute_cdp_cmd('Network.getResponseBody', {'requestId': requestId})
                body = response_dict["body"]
                body_dict = json.loads(body)  # 将响应体解析为JSON
                # 尝试从JSON响应中提取具体的数据
                try:
                    jobCardList = body_dict['data']['data']['jobCardList']
                    print(len(jobCardList))  # 打印找到的岗位数量
                    for i in jobCardList:
                        # 尝试提取每个岗位的具体信息,如果提取失败则设置为None
                        try:
                            compName = i['comp']['compName']  # 公司名称
                        except:
                            compName = None
                        try:
                            compScale = i['comp']['compScale']  # 公司规模
                        except:
                            compScale = None

                        try:
                            compStage = i['comp']['compStage']  # 公司发展阶段
                        except:
                            compStage = None
                        try:
                            compIndustry = i['comp']['compIndustry']  # 行业
                        except:
                            compIndustry = None
                        try:
                            title = i['job']['title']  # 岗位名称
                        except:
                            title = None
                        try:
                            salary = i['job']['salary']  # 薪资
                        except:
                            salary = None
                        try:
                            dq = i['job']['dq']  # 办公地点
                        except:
                            dq = None
                        try:
                            requireWorkYears = i['job']['requireWorkYears']  # 年限要求
                        except:
                            requireWorkYears = None
                        try:
                            requireEduLevel = i['job']['requireEduLevel']  # 学历要求
                        except:
                            requireEduLevel = None

                        # 打印并添加到data_list列表中
                        print(
                            {'岗位名称': title, '薪资': salary, '办公地点': dq, '年限要求': requireWorkYears, '学历要求': requireEduLevel,
                             '公司名称': compName, '规模': compScale, '阶段': compStage, '行业': compIndustry})
                        data_list.append(
                            {'岗位名称': title, '薪资': salary, '办公地点': dq, '年限要求': requireWorkYears, '学历要求': requireEduLevel,
                             '公司名称': compName, '规模': compScale, '阶段': compStage, '行业': compIndustry})
                except:
                    print('body err!')  # 如果解析JSON时出错,打印错误信息
            except:
                pass  # 如果获取响应体时出错,则忽略
            print('------------')  # 打印分隔符,便于查看日志输出


def to_excel(data_list):
    """写入Excel"""
    df = pd.DataFrame(data_list)
    df.drop_duplicates() # 删除重复数据
    df.to_excel('招聘信息.xlsx')


if __name__ == '__main__':
    key = 'Python爬虫工程师'  # 需要检索的岗位
    city_code = '410'  # 城市代码(自行从官网选择城市后查找)
    page_num = 4  # 爬取的页数
    data_list = []  # 存放数据
    # 一、循环翻页
    for currentPage in range(0,page_num):
        url =f'https://www.liepin.com/zhaopin/?city={city_code}&currentPage={currentPage}&key={key}'
        # 二、发送请求,解析数据
        get_data(url,data_list)
        time.sleep(2) # 限制速度
    # 三、写入Excel
    to_excel(data_list)

免责声明:本文爬虫思路、相关技术和代码仅用于学习参考,对阅读本文后的进行爬虫行为的用户不承担任何法律责任。

5.7 爬取结果展示

使用代理IP后获取数据成功,在脚本同路径下生成Excel,我们打开来看看:

六、总结

代理IP对于爬虫是密不可分的,但使用代理IP需要遵守相关法律法规和目标网站的使用规则,不得进行非法活动或滥用代理IP服务。亮数据家的动态住宅代理IP可以帮助爬虫安全采集公开数据信息,最近更是推出了限时5 折优惠,新老客户同享,有需要代理IP的小伙伴可以试试:亮数据官网


http://www.kler.cn/a/546235.html

相关文章:

  • Vue 2 路由指南:从基础到高级
  • 机器学习 - 线性模型
  • 在springboot加vue项目中加入图形验证码
  • 【linux】文件与目录命令 - ln
  • 渗透测试工具:SQLmap安装教程及使用
  • 【算法专场】哈希表
  • 庞氏骗局(Ponzi Scheme):金融投资与公司经营中的隐形陷阱(中英双语)
  • 在我的世界地下城开发mod的第一天
  • 怎么才能DeepSeek批量写作和内容导出?
  • 傅里叶变换推导
  • 【黑马点评优化】1-使用JWT登录认证+redis实现自动续期
  • Django 进行数据库操作(ORM框架+mysqlclient+mysql)
  • 2.14学习记录
  • 网络安全RSA加密
  • 美团 字节 view
  • 比较34个结构的分类准确率
  • 【Linux】--- 基础开发工具之yum/apt、vim、gcc/g++的使用
  • C++算法竞赛基础语法-9
  • Linux 设备驱动 -- I2C 子系统快速入门
  • 数据可视化+SpringBoot+协同过滤推荐算法的美食点餐管理平台