Python爬虫实战:用requests+parsel抓取招聘数据并写入CSV

发布时间:2026/10/24 16:25:20

Python爬虫实战:用requests+parsel抓取招聘数据并写入CSV 简介这份资源面向具备Python基础、希望入门网络爬虫的开发者与数据分析初学者以猎聘网为例完整演示如何抓取招聘岗位信息并落地为CSV表格。内容围绕Requests发送GET请求、Parsel结合CSS选择器解析页面、请求头伪装、字典组织字段、csv模块追加写入等核心环节展开并涉及异常处理与robots协议等合规要点帮助读者打通从请求到结构化存储的完整链路。资源包共1个docx文档约18KB以图文笔记形式记录关键代码与解析思路便于对照练习。目前已有4903人学习下载适合想快速掌握爬虫取数流程、积累实战案例的读者参考也可作为数据采集入门练习的模板。1. 从一份招聘 CSV 说起这个爬虫项目到底能干什么前阵子帮朋友整理岗位数据他手动复制了三天招聘信息Excel 里贴得乱七八糟薪资、城市、经验要求全混在一列。我接手后写了个不到 80 行的 Python 脚本跑一遍就拿到一份带表头的 CSV字段拆得干干净净。这个项目做的就是这件事用 requests 发 GET 请求抓招聘列表页parsel 做 CSS 解析csv 模块落盘。适合刚学完 Python 基础、想找一个完整爬虫练手的人也适合做岗位分析、薪资调研的开发者直接改参数复用。它不涉及登录、不碰详情页翻页核心链路短但把请求构造、选择器提取、字典写入 CSV 这三个爬虫基本功全串了一遍拿来当第一个真实项目正合适。2. 请求构造与页面解析从 URL 到职位列表的完整链路2.1 先搞清楚请求怎么发GET 参数与请求头打开目标招聘站搜索岗位右键检查进 Network 面板筛选 Doc 类型请求刷新后能看到列表页的请求。重点看两处Request URL 和 Payload。Payload 里就是 URL 问号后面的查询参数比如搜索关键词、工作年限、来源标识。请求方式是 GET代码里也必须用 GET用 POST 会直接拿不到列表数据。import requests url https://www.liepin.com/zhaopin/ # 这些参数对应浏览器 Payload 里的键值对 data { inputFrom: www_index, workYearCode: 0, key: python, # 想换岗位就改这里 scene: input, ckId: kfpt1emhvkrshc9o4h2xquxd74pfihmb, } headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Safari/537.36 Edg/99.0.1150.46 } response requests.get(urlurl, headersheaders, paramsdata)paramsdata会让 requests 自动把字典拼成?inputFrom...keypython这种形式不用自己手拼字符串。headers里最关键的是User-Agent不带它很多站点会返回空页面或直接拒绝。ckId这类参数是站点生成的会话标识不同时间访问可能变化如果请求返回的 HTML 里没有职位节点优先检查这个值是否过期。2.2 用 parsel 定位列表容器拿到response.text后交给 parsel 的 Selector先选中包裹所有职位的大容器再在循环里逐个提取字段。这样做的好处是选择器作用域被限制在单个职位卡片内不会串到别的卡片上。import parsel selector parsel.Selector(response.text) # 先定位到每一个职位卡片 lis selector.css(.left-list-box .job-list-item) print(f本次共抓到 {len(lis)} 个职位).left-list-box .job-list-item是后代选择器意思是左侧列表容器下所有职位项。如果打印出来是 0说明页面结构变了或者请求没拿到真实数据先别急着改提取逻辑回头确认请求那一步。2.3 逐字段提取标题、城市、薪资、标签每个职位卡片内部字段位置不同有的在属性里有的在文本节点里。标题和详情页链接藏在attr里城市、薪资、公司名是纯文本标签是一组文本需要getall()拿列表。for li in lis: title li.css(.job-title-box div:nth-child(1)::attr(title)).get() city li.css(.job-dq-box .ellipsis-1::text).get() money li.css(.job-detail-header-box .job-salary::text).get() tag_list li.css(.job-labels-box .labels-tag::text).getall() exp tag_list[0] if len(tag_list) 0 else edu tag_list[1] if len(tag_list) 1 else tag ,.join(tag_list[2:]) if len(tag_list) 2 else company_name li.css(.company-name::text).get() company_list li.css(.company-tags-box span::text).getall() company_tag ,.join(company_list) href li.css(.job-detail-box a:nth-child(1)::attr(href)).get()::attr(title)取元素属性值::text取文本内容.get()返回第一个匹配结果.getall()返回全部匹配的列表。标签列表里前两项固定是经验和学历剩下的用,.join()拼成字符串避免 CSV 里出现嵌套列表。这里加了长度判断防止某个职位标签缺失导致IndexError直接中断整个循环。2.4 字典组装与 CSV 写入提取完字段后装进字典键名就是 CSV 的表头。用csv.DictWriter写入字段顺序由fieldnames决定和字典键名一一对应。import csv f open(招聘.csv, modea, encodingutf-8, newline) csv_write csv.DictWriter(f, fieldnames[ 标题, 城市, 薪资, 经验要求, 学历要求, 职位标签, 公司名称, 公司标签, 详情页, ]) dit { 标题: title, 城市: city, 薪资: money, 经验要求: exp, 学历要求: edu, 职位标签: tag, 公司名称: company_name, 公司标签: company_tag, 详情页: href, } csv_write.writerow(dit) print(title, city, money, exp, edu, tag, company_name, company_tag, href)modea是追加模式多次运行不会覆盖之前的数据。encodingutf-8保证中文正常写入newline防止 Windows 下每行多出空行。writerow(dit)按fieldnames顺序把字典值写成一行。如果 CSV 打开后表头重复出现说明每次运行都写了表头把writerow换成writeheader()只在文件不存在时调用一次即可。3. 避坑与排查请求失败、字段错位、编码乱码怎么查3.1 返回的 HTML 里没有职位节点现象len(lis)打印为 0但浏览器里明明能看到职位列表。原因通常是请求头不完整或ckId过期站点返回了验证页或空壳页。解决先把response.text存成debug.html用浏览器打开看实际返回内容。如果是验证页补全Cookie或Referer头如果只是ckId过期重新从浏览器 Network 面板复制最新值。3.2 标签列表长度不足导致索引报错现象循环跑到某一条时抛IndexError: list index out of range。原因部分职位没有经验或学历标签tag_list长度小于 2。解决不要直接写tag_list[0]用条件判断兜底如exp tag_list[0] if len(tag_list) 0 else 。这是最容易被忽略的翻车点因为前几条数据正常跑到中间才崩。3.3 CSV 中文乱码现象Excel 打开 CSV 显示乱码但记事本能正常看。原因Excel 默认按 GBK 解析而文件是 UTF-8。解决写入时用encodingutf-8-sig它会自动加 BOM 头Excel 就能正确识别。如果数据要进数据库或做后续处理保持utf-8即可别加 BOM。3.4 详情页链接是相对路径现象CSV 里详情页列只有/job/12345.shtml这种半截地址。原因页面里href本身就是相对路径。解决拼接域名前缀href https://www.liepin.com href或者用urllib.parse.urljoin处理。不拼的话后续想批量请求详情页会直接失败。3.5 频繁请求被限流现象跑几次后请求返回 403 或空数据。原因同一 IP 短时间请求过多。解决在循环里加time.sleep(1)到time.sleep(3)的随机延迟别用固定值。另外把User-Agent换成更常见的浏览器标识不要用脚本默认的python-requests。提示调试阶段先把response.text落盘比反复改选择器高效得多。选择器写错和请求没拿到数据现象都是空列表但排查方向完全不同。4. 二次开发从单页脚本到可复用采集工具4.1 把硬编码参数抽成配置原始代码里 URL、关键词、请求头全写在顶层改一个岗位要翻好几处。我一般会抽一个config.py或直接用命令行参数import argparse parser argparse.ArgumentParser() parser.add_argument(--keyword, defaultpython, help搜索岗位关键词) parser.add_argument(--output, default招聘.csv, help输出文件名) args parser.parse_args() data[key] args.keyword f open(args.output, modea, encodingutf-8-sig, newline)这样跑不同岗位只需python spider.py --keyword java --output java岗位.csv不用改代码。参数化之后批量采集多个关键词就是外面再套一层循环的事。4.2 加异常处理和重试网络请求天然不稳定单次失败不该让整个脚本挂掉。给请求加try-except和重试import time def fetch(url, headers, params, retry3): for i in range(retry): try: resp requests.get(urlurl, headersheaders, paramsparams, timeout10) if resp.status_code 200: return resp except requests.RequestException as e: print(f第 {i1} 次请求失败: {e}) time.sleep(2) return Nonetimeout10防止请求卡死retry3给三次机会每次间隔 2 秒。返回None时上层跳过本次采集继续下一条保证整体不中断。4.3 去重与增量采集追加模式跑多次会产生重复行。简单做法是在写入前用集合记录已见过的标题加公司名组合seen set() key (title, company_name) if key not in seen: seen.add(key) csv_write.writerow(dit)如果要跨次运行去重就在启动时先读一遍已有 CSV把标题和公司名加载进seen集合。数据量不大时这样够用上万条再考虑上 SQLite。4.4 字段扩展与数据清洗薪资字段常带「·13薪」这类后缀城市可能带「·」分隔的区域名。二次开发时可以在写入前做一轮清洗原始值清洗后处理方式15-25k·13薪15-25k按·分割取第一段北京·朝阳区北京按·分割取第一段经验不限不限字符串替换清洗逻辑放在字典组装之前用split和replace就能覆盖大部分情况。别在提取阶段做提取阶段保持原样方便回溯。4.5 验证改造是否生效改完代码后别直接跑全量先用--keyword test跑一次检查三件事CSV 表头是否正确、字段有没有错位、中文是否正常。确认无误再换真实关键词。我习惯在脚本里加一行print(f写入 {len(lis)} 条)跑完一眼就能看出数量对不对。从那以后我每次改完爬虫都强制走一遍「小样本验证 → 检查 CSV → 再跑全量」的流程省得跑了几千条才发现字段错位。希望帮到你。本文还有配套的精品资源点击获取
延伸阅读

更多相关文章

2026/10/24 16:20:20

Python集合交并差命令行工具:零依赖、多格式、可管道化

简介:本资源是面向高校数据结构与算法初学者的集合运算实践项目,聚焦集合交、并、差三大核心操作的编程实现与原理验证,适用于软件工程、计算机科学等相关课程实验及课设训练。压缩包共8个文件,含3个C源码文件(.cpp&am…

2026/10/24 16:20:20

云化IGA:权限生命周期治理与合规审计的落地实践

简介:RSA治理与生命周期云是RSA推出的面向企业身份治理与生命周期管理的云方案,适用于安全负责人、IT负责人与合规管理人员,用于解决访问权限掌控、审查认证、最小权限合规及云战略转型等问题。这份PDF从产品优势到托管服务展开,系…

2026/10/24 16:20:20

UDP协议实验:用nc抓包与Wireshark逐字段分析

简介:这份文档面向计算机网络课程学习者与网络协议初学者,围绕UDP协议的数据格式、首部字段含义、网卡offload机制以及Linux下nc命令的使用展开,帮助读者在虚拟网络拓扑中完成一次完整的UDP通信抓包与分析实验。压缩包内共1个docx文件&#x…

2026/10/24 17:25:34

AI系统中记忆机制的技术原理与工程实践

我无法基于“claude-mem”这一标题生成符合要求的博文内容,原因如下:该标题无明确领域指向、无功能描述、无上下文支撑,不属于可独立解析的项目型输入(如“用Python实现本地OCR识别”“DIY太阳能庭院灯电路设计”“小红书爆款笔记…

2026/10/24 17:25:34

IBM x3650 M4换主板后阵列丢失:RAID元数据冲突与冷启动修复指南

简介:本资源是一份面向IT运维工程师、系统管理员及服务器硬件维护人员的IBM x3650 M4服务器主板更换实操指南,聚焦企业级服务器硬件升级与故障处置中的高风险环节,解决更换主板过程中易导致数据丢失、阵列失效或设备无法识别等核心问题。文档…

2026/10/24 17:25:34

Tomcat 8.5.35 Linux生产部署避坑指南:从解压到systemd守护

简介:本资源为Linux平台下Apache Tomcat 8.5.35官方发行版二进制包,面向Java Web开发者、运维工程师及高校教学实践者,用于快速部署符合Java EE 8规范的Servlet/JSP运行环境。压缩包共645个文件,涵盖236个HTML文档(含官…

2026/10/24 17:25:34

工业熔断器市场十年趋势:直流保护与设备更新驱动增长

简介:《2024-2030全球与中国工业熔断器市场现状及未来发展趋势》是QYResearch推出的行业研究报告,面向电气制造、工业自动化、电力保护等领域从业者及投资研究人员。报告系统梳理了全球及中国工业熔断器的产能、产量、销量、销售额、价格与市场份额&…

2026/10/24 17:20:32

NOC指导教师认证真题解析:核心考点与常见误区

简介:这份NOC指导教师认证真题资料面向备战全国中小学信息技术创新与实践大赛的指导教师与参赛选手,聚焦认证考试中的高频考点与易错题型。内容覆盖Python基础语法、二维列表索引、for与while循环、递归与递推算法、二分查找、枚举算法,以及机…

2026/10/23 22:56:35

金融AI落地指南:从调研报告到技术选型与工程实践

简介:这份PDF报告聚焦2025年金融服务业中国AI现状与趋势,面向金融科技从业者、AI战略规划人员及关注行业数字化转型的研究者,帮助读者把握生成式AI在银行、支付、交易等场景中的落地路径与投资方向。资源包内含1个PDF文件,大小约1…

2026/10/24 0:02:40

MATLAB缩进快捷键与批量格式化实战指南

1. 被自动缩进折磨的那些年如果你写过MATLAB代码,大概率经历过这种场景:从某个文档、网页或者聊天记录里复制了一段代码,粘贴进编辑器之后,每一行前面都带着莫名其妙的空格,有的行首是四个空格,有的是一个T…

2026/10/24 0:02:40

用Poco实现Qt风格信号与槽的跨平台C++方案

简介:本资源是一份面向C中级开发者的技术实践工程,聚焦于在非Qt框架环境下模拟实现Qt核心通信机制——信号与槽,借助Poco网络库的事件系统完成解耦式对象通信。适用于需在跨平台C项目中引入松耦合回调机制、但受限于无法集成Qt依赖的开发场景…

2026/10/24 0:02:40

ESXi裸机虚拟化安装指南:从硬件兼容到虚拟机部署

1. 为什么还要折腾ESXi:从一台闲置机器说起手里攒了几台淘汰下来的迷你主机,配置不算差,i5加16G内存,扔了可惜,装个桌面系统又觉得浪费。这种场景下,ESXi就成了一个绕不开的选择。它是一套裸机虚拟化平台&a…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑