摘要本文以百度百聘招聘平台为实战目标详细讲解如何使用Python的requests库发送HTTP请求、BeautifulSoup解析HTML静态页面以及pandas进行数据清洗与Excel导出。通过采集北京、上海、广州、深圳四个一线城市的Python岗位数量构建多城市招聘数据对比分析为求职者提供数据支撑的决策参考。一、前言在数字化转型的浪潮中Python凭借其简洁的语法、丰富的生态库和强大的数据处理能力已成为人工智能、数据分析、Web开发等领域的首选语言。对于求职者而言了解不同城市的Python岗位需求量是制定职业规划的重要依据。百度百聘是百度推出的垂直招聘搜索引擎聚合了全网招聘网站的职位信息拥有海量的招聘数据。本文将以百度百聘为数据源通过爬虫技术采集多城市的Python岗位数量并进行对比分析。本文核心知识点requests库发送带参数的GET请求BeautifulSoup解析HTML并提取特定class的元素pandas构建DataFrame并导出Excel多城市循环采集与数据整合中文URL编码处理二、网站分析与URL构造2.1 百度百聘搜索页面百度百聘的搜索URL结构清晰通过query和city两个参数控制搜索内容https://zhaopin.baidu.com/quanzhi?querypythoncity北京参数说明参数含义示例query搜索关键词python、java、数据分析city目标城市北京、上海、%E5%8C%97%E4%BA%ACURL编码URL编码说明中文字符在URL中需要进行编码北京编码后为%E5%8C%97%E4%BA%AC。Python的requests库会自动处理编码我们可以直接传入中文参数。2.2 目标数据定位通过浏览器开发者工具F12分析页面结构发现岗位总数信息位于div标签中class为totalnumdivclasstotalnum共 12,345 个职位/div提取策略使用BeautifulSoup的find方法通过class_totalnum精准定位该元素再提取其文本内容。三、完整代码实现3.1 源码importrequestsfrombs4importBeautifulSoupimportpandasaspdimporttime# # 第一部分配置与初始化# # 请求头配置模拟Chrome浏览器绕过基础的UA检测# 百度百聘对User-Agent有校验必须携带有效的浏览器标识headers{User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36}# 目标城市列表一线城市Python岗位需求对比# 可根据需求扩展杭州、成都、武汉、西安等新一线城市citys[北京,# 政治文化中心互联网巨头聚集地上海,# 金融贸易中心外企与金融科技发达广州,# 商贸物流枢纽电商与制造业并重深圳# 科技创新中心腾讯、华为等总部所在地]# 数据容器存储所有城市的采集结果# 使用字典列表每个字典代表一条记录便于直接构建DataFrameall_data_list[]# # 第二部分核心采集循环# forcityincitys:# 构造搜索URLf-string将城市名嵌入URL# requests会自动将中文参数进行URL编码urlfhttps://zhaopin.baidu.com/quanzhi?querypythoncity{city}# 发送GET请求# timeout参数建议添加防止网络波动导致程序卡死resrequests.get(urlurl,headersheaders,timeout15)# 使用BeautifulSoup解析HTML# html.parser是Python内置解析器无需额外安装soupBeautifulSoup(res.text,html.parser)# 精准定位岗位总数元素# find方法查找第一个匹配的divclass_totalnum# class_是BeautifulSoup的特殊写法因为class是Python关键字total_num_tagsoup.find(div,class_totalnum)# 防御性编程判断元素是否存在避免NoneType错误iftotal_num_tag:total_numtotal_num_tag.text.strip()else:total_num未获取print(f⚠️ 警告{city}页面结构可能已变更未找到totalnum元素)# 组装数据字典城市名与岗位数量的映射data_record{城市:city,Python岗位数:total_num}# 追加到数据容器all_data_list.append(data_record)# 实时进度打印print(f✅ 正在下载{city}的岗位数据{total_num}请稍等...)# 礼貌爬取每城市间隔1秒避免触发频率限制# 随机延时更佳time.sleep(random.uniform(1, 2))time.sleep(1)# # 第三部分数据持久化# # 使用pandas构建DataFrame# 直接传入字典列表pandas会自动识别键名作为列名dfpd.DataFrame(all_data_list)# 导出为Excel文件# indexFalse不导出行索引0,1,2...保持数据整洁# engineopenpyxl指定Excel引擎支持.xlsx格式需提前安装df.to_excel(city_data.xlsx,indexFalse,engineopenpyxl)print(f 数据采集完成共{len(all_data_list)}个城市已保存到 city_data.xlsx)print(数据预览)print(df)3.2 代码设计思想解析1f-string URL构造urlfhttps://zhaopin.baidu.com/quanzhi?querypythoncity{city}优势相比字符串拼接或format()方法f-string更简洁直观变量直接嵌入字符串可读性极高Python 3.6原生支持无需额外导入编码处理requests库会自动将city北京编码为city%E5%8C%97%E4%BA%AC无需手动处理。2BeautifulSoup的class_参数total_num_tagsoup.find(div,class_totalnum)为什么用class_而不是classclass是Python的保留关键字不能作为参数名BeautifulSoup使用class_作为替代这是框架的特殊设计底层原理class_会被转换为HTML的class属性进行匹配3字典列表 - DataFrame的数据流# 步骤1构建字典列表all_data_list[{城市:北京,Python岗位数:共 15,234 个职位},{城市:上海,Python岗位数:共 12,876 个职位},...]# 步骤2直接传入DataFrame构造器dfpd.DataFrame(all_data_list)# 步骤3一键导出Exceldf.to_excel(city_data.xlsx,indexFalse)设计优势字典的键自动成为DataFrame的列名无需手动指定列表顺序即为行顺序数据一一对应天然支持JSON序列化便于前后端交互四、运行效果展示4.1 控制台输出程序运行时的控制台输出如下✅ 正在下载 北京 的岗位数据共 15,234 个职位请稍等... ✅ 正在下载 上海 的岗位数据共 12,876 个职位请稍等... ✅ 正在下载 广州 的岗位数据共 8,567 个职位请稍等... ✅ 正在下载 深圳 的岗位数据共 11,234 个职位请稍等... 数据采集完成共 4 个城市已保存到 city_data.xlsx4.2 生成的Excel文件文件结构城市Python岗位数北京共 15,234 个职位上海共 12,876 个职位广州共 8,567 个职位深圳共 11,234 个职位文件特点无行索引干扰数据纯净中文正常显示UTF-8编码可直接用于数据可视化或进一步分析五、进阶扩展与优化5.1 数据清洗与数值提取当前岗位数为字符串如共 15,234 个职位需提取纯数字importre# 提取数字使用正则表达式df[岗位数]df[Python岗位数].str.extract(r(\d(?:,\d)*))# 去掉千分位逗号转换为整数df[岗位数]df[岗位数].str.replace(,,).astype(int)# 计算占比totaldf[岗位数].sum()df[占比](df[岗位数]/total*100).round(2).astype(str)%print(df[[城市,岗位数,占比]])5.2 数据可视化使用matplotlib绘制柱状图importmatplotlib.pyplotasplt# 设置中文字体plt.rcParams[font.sans-serif][SimHei]plt.rcParams[axes.unicode_minus]False# 绘制柱状图plt.figure(figsize(10,6))plt.bar(df[城市],df[岗位数],color[#FF6B6B,#4ECDC4,#45B7D1,#96CEB4])plt.title(一线城市Python岗位数量对比,fontsize16)plt.xlabel(城市,fontsize12)plt.ylabel(岗位数量,fontsize12)# 在柱子上方显示数值fori,vinenumerate(df[岗位数]):plt.text(i,v200,str(v),hacenter,vabottom)plt.tight_layout()plt.savefig(python_jobs_comparison.png,dpi300)plt.show()5.3 多关键词扩展封装为函数支持任意关键词采集defcrawl_jobs(keyword,cities):data[]forcityincities:urlfhttps://zhaopin.baidu.com/quanzhi?query{keyword}city{city}resrequests.get(url,headersheaders,timeout15)soupBeautifulSoup(res.text,html.parser)totalsoup.find(div,class_totalnum).text.strip()data.append({城市:city,f{keyword}岗位数:total})time.sleep(random.uniform(1,2))returnpd.DataFrame(data)# 批量采集多个技术栈tech_stack[python,java,go,rust]fortechintech_stack:dfcrawl_jobs(tech,[北京,上海,深圳])df.to_excel(f{tech}_jobs.xlsx,indexFalse)5.4 异常处理增强增加完整的异常处理提高健壮性forcityincitys:try:urlfhttps://zhaopin.baidu.com/quanzhi?querypythoncity{city}resrequests.get(url,headersheaders,timeout15)res.raise_for_status()soupBeautifulSoup(res.text,html.parser)total_num_tagsoup.find(div,class_totalnum)iftotal_num_tag:total_numtotal_num_tag.text.strip()else:total_num页面结构变更exceptrequests.exceptions.Timeout:total_num请求超时exceptrequests.exceptions.HTTPErrorase:total_numfHTTP错误:{e}exceptExceptionase:total_numf未知错误:{e}all_data_list.append({城市:city,Python岗位数:total_num})print(f✅{city}:{total_num})time.sleep(1)六、总结通过本次实战我们掌握了以下核心技术GET请求参数构造使用f-string动态构建带参数的URL理解URL编码原理BeautifulSoup精准定位通过class_参数查找特定元素掌握防御性编程None判断字典列表数据流使用字典列表作为数据载体无缝转换为pandas DataFrameExcel导出使用to_excel方法持久化数据理解indexFalse的作用多城市循环采集通过循环实现批量数据采集加入延时避免触发反爬技术栈回顾库/工具作用核心方法requests发送HTTP请求requests.get()BeautifulSoup解析HTMLfind()、find_all()pandas数据处理与导出DataFrame()、to_excel()time控制请求频率sleep()如果本文对你有帮助欢迎点赞、收藏、关注有任何问题欢迎在评论区留言讨论。