写点什么

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

作者:袁袁袁袁满
  • 2025-02-14
    四川
  • 本文字数:7761 字

    阅读完需:约 25 分钟

一、前言

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

二、爬取目标

爬虫目标为某招聘网站,首先可以看到博主这里没有登录注册也可以岗位信息,那接下来写代码就不用去登录: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 jsonimport 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 的小伙伴可以试试:亮数据官网

用户头像

还未添加个人签名 2022-04-28 加入

还未添加个人简介

评论

发布
暂无评论
Python爬虫实战:利用代理IP获取招聘网站信息_袁袁袁袁满_InfoQ写作社区