我要提问
ARTICLE DETAIL

资讯详情

前沿编程新知与开发实战干货的深度解读。

Scrapy框架爬取Boss直聘网Python职位信息的源码

Scrapy框架爬取Boss直聘网Python职位信息的源码 前言这个标题要求「可直接使用的源码」。先说明为什么本文不会给出那样的代码——这不是技术做不到而是不该做。判断能不能抓第一步是读目标站点的 robots.txt。Boss 直聘的 robots.txt 对User-agent: *给出的规则相当严格其中包含一条覆盖面极广的Disallow: /*?*——任何带查询参数的 URL 都在禁止之列而职位搜索列表页恰恰形如.../web/geek/job?querypythoncity...正好命中此外/web/geek/*、/web/boss/*、/job_detail/l*.html等路径也被显式禁止SemrushBot、Jobuispider等爬虫更是被整站拒绝。再加上职位信息需要登录后才有完整内容、站点对自动化访问有明确的技术与条款限制——综合起来「绕过这些限制去批量抓取职位信息」这件事本身就不合规。所以本文改讲三件真正有用的事第一拿到一个目标时如何系统性地判断「能不能抓」第二要获取职位类数据正规路径有哪些第三同样的 Scrapy 技术如何在一个允许抓取的靶子上练熟——毕竟你要学的从来不是「怎么绕过某个站」而是解析、清洗、结构化这套通用能力。文中也不会出现构造特殊请求头、伪造设备指纹、破解验证码之类的内容。本文的代码以 Python 3 为基准。老教程里常见的 Python 2 写法print语句、xrange、dict.iteritems()都已失效Python 2.7 于 2020 年 1 月 1 日停止维护请一律改用print(...)、range、.items()。一、合规评估清单拿到任何抓取目标先跑一遍这张清单任何一项不通过就应该停下来检查项Boss 直聘的情况判定robots.txt 是否允许目标路径Disallow: /*?*覆盖所有带参 URL不允许是否需要登录才能看到内容职位详情需登录不允许抓取使用条款是否禁止自动化访问通常有相关条款需自行核对是否有官方 API / 开放平台需走商务合作优先走此路抓取频率是否会打扰对方大规模抓取必然造成压力应避免看清单就知道问题出在前两项而不是出在「你的 Scrapy 写得不够好」。遇到 robots.txt 明确禁止的路径正确动作是停止而不是换 IP、换 UA、上代理池。二、获取职位数据的正规路径想做数据分析、职位趋势研究下面这些路子既合规又往往更省事官方开放平台 / 商业数据接口。招聘平台大多有面向企业的开放能力通过商务合作拿到结构化数据质量远高于自己爬。站点提供的导出功能。部分平台允许用户导出自己的投递记录或收藏属于用户授权范围内。公开数据集与行业报告。学术与行业机构会发布招聘相关的匿名化数据集直接拿来研究完全没问题。自建或明确授权的靶站。这也是本文第三节采用的方式用一个允许抓取的页面练技术。如果你的目的只是「练习 Scrapy」那么抓什么站并不重要重要的是解析、分页、清洗、落地这套链路。选一个允许抓取的靶子你学到的东西一模一样还不用担心踩线。三、用允许抓取的靶子练同一套技术招聘类页面的解析难点是固定的卡片列表、分页、薪资区间文本、标签化的城市与经验要求。这些技术在任何结构相似的页面上都能练到。先看解析这一环。Scrapy 的选择器能力来自parsel这个库它可以脱离爬虫单独使用非常适合离线调试解析规则——也就是说你可以把一段允许使用的 HTML 存下来反复调规则完全不产生任何网络请求# 适用于 Python 3.8parsel 是 Scrapy 的依赖库可单独导入from parsel import Selectorhtml ul classjob-listli classjob-cardh3 classjob-namePython 后端开发/h3span classjob-area杭州/spanspan classsalary15-25K/spana classjob-link href/job/123查看/a/li/ulsel Selector(texthtml)for card in sel.css(li.job-card):row {name: card.css(h3.job-name::text).get(),area: card.css(span.job-area::text).get(),salary: card.css(span.salary::text).get(),href: card.css(a.job-link::attr(href)).get(),}print(row)同样的选择器规则放进 Spider 就是在真实页面上工作# 适用于 Python 3.8Scrapy 2.x# 注意start_urls 必须指向你被允许抓取的站点或你自建的页面import scrapyclass JobListSpider(scrapy.Spider):name job_list# 换成你拥有、或明确允许你抓取的靶站地址start_urls [https://example.com/jobs/]allowed_domains [example.com]custom_settings {ROBOTSTXT_OBEY: True, # 永远保留这一条CONCURRENT_REQUESTS_PER_DOMAIN: 1, # 单域名串行DOWNLOAD_DELAY: 1.5, # 请求间隔宁慢勿快USER_AGENT: job-demo/0.1 (https://example.com/bot),}def parse(self, response):for card in response.css(li.job-card):yield {name: card.css(h3.job-name::text).get(),area: card.css(span.job-area::text).get(),salary: card.css(span.salary::text).get(),detail_url: response.urljoin(card.css(a.job-link::attr(href)).get()),}next_page response.css(a.next::attr(href)).get()if next_page is not None:yield response.follow(next_page, callbackself.parse)把start_urls换成你自己的博客、公司官网、或者练习站点这段代码就是完全合规的。技术是中性的靶子的选择决定了它是否越界。四、字段清洗把文本变成可比的数据招聘数据真正有价值的部分在于清洗。原始页面给你的是「15-25K」「15k-25k·13薪」「面议」这类文本直接存下来没法做统计。清洗要单独写函数并且只对能确定格式的值做转换拿不准的一律保留原文# 适用于 Python 3.8import redef parse_salary(text):把薪资文本转成 (最小值, 最大值) 的千元整数无法解析返回 (None, None)。if not text:return (None, None)t text.strip().lower().replace(k, 000)nums re.findall(r\d, t)if not nums:return (None, None)if len(nums) 1:return (int(nums[0]), int(nums[0]))return (int(nums[0]), int(nums[1]))print(parse_salary(15-25K)) # (15000, 25000)print(parse_salary(面议)) # (None, None)注意最后一行「面议」这类无法解析的值必须老老实实返回(None, None)而不是硬凑一个 0——0 会被后续统计当成「薪资为零」的样本把结论带偏。常见坑点1. 看到禁止就去研究怎么绕❌ robots.txt 明确禁止就改用代理池、伪造 UA、模拟设备指纹。 ✅ 被禁止就是被拒绝改找官方 API、授权数据源或换一个允许抓取的靶子。2. 把「能跑通」当成「可以上线」❌ 脚本跑通了就长期高频运行。 ✅ 上线前再过一遍合规清单robots、条款、登录限制、频率影响。3. 薪资字段直接存字符串❌ 存下 15-25K·13薪后面做统计时无从下手。 ✅ 写成parse_salary这类清洗函数无法解析的返回(None, None)而非 0。4. 把不确定的值硬编码成默认值❌ 解析不到就填 0 或空字符串污染统计结果。 ✅ 用None表示缺失让下游显式处理缺失。5. 忘记urljoin补全相对链接❌item[detail_url] /job/123单独请求时解析失败。 ✅ 用response.urljoin(...)或response.follow()。6. 直接对列表页做详情页跟进请求量翻十几倍❌ 每个职位都开详情页几千次请求压向对方。 ✅ 只取列表页必要字段或严格限制详情页数量练手阶段别做详情跟进。7. 用 Python 2 的老代码❌ 照抄print ...、xrange之类的旧写法。 ✅ 改成print(...)、range、.items()。8. 在parse里做网络请求之外的重活❌ 在解析回调里同步处理大量数据拖慢整条流水线。 ✅ 解析只管取字段清洗与入库交给管道Item Pipeline。总结判断/做法要点先判断能不能抓读 robots.txt、看是否需要登录、核条款Boss 直聘的结论Disallow: /*?*覆盖带参 URL列表搜索页被禁止合规替代官方 API、授权数据、公开数据集、自建靶站练技术parsel.Selector离线调试 Scrapy 骨架清洗只转确定格式解析不到返回None底线的表达「不允许」就是不允许不是「难度不够」写爬虫的能力一半在解析与清洗一半在判断边界。前一半靠练后一半靠纪律。当目标站明确说「不」的时候一个成熟工程师的回应是换一条合规的路而不是去修一条绕过它的路。把这篇文章里的技术练熟、把合规清单养成习惯你就同时具备了这两半。
返回列表