实战案例:采集 51job 企业招聘信息

本文涉及的产品
智能开放搜索 OpenSearch行业算法版,1GB 20LCU 1个月
实时数仓Hologres,5000CU*H 100GB 3个月
实时计算 Flink 版,5000CU*H 3个月
简介: 本文基于Feapder框架,从零开始搭建企业级招聘信息爬虫管道。内容涵盖基础概念(数据管道与Feapder特点)、生动比喻(快递系统类比爬虫流程)、技术场景(代理IP、Cookie管理)及实战案例(采集51job岗位信息并分类存储)。通过完整代码示例,展示如何配置代理、自定义中间件及Pipeline。无论产品经理还是学生,均可轻松上手,构建高效稳定的爬虫系统。

爬虫代理

本文将带你从零开始,借助 Feapder 快速搭建一个企业级招聘信息数据管道。在“基础概念”部分,我们先了解什么是数据管道和 Feapder;“生动比喻”用日常场景帮助你快速理解爬虫组件;“技术场景”介绍本项目中如何使用代理等采集策略;“实战案例”通过完整代码演示采集 51job 招聘信息并分类存储;最后在“扩展阅读”推荐一些进一步学习的资源。无论你是非技术背景的产品经理,还是校园里的同学,都能轻松上手,快速构建自己的企业级爬虫管道。

一、基础概念

1. 什么是数据管道?

  • 数据管道(Data Pipeline)指的是从数据源(如网页、API)到数据仓库(如数据库、文件)的整个流转过程,通常包括数据获取、清洗、存储和监控。
  • 在企业级场景下,管道需要稳定可靠、易于扩展,并支持重试、分布式、监控告警等能力。

2. 为什么选 Feapder?

  • 轻量易用:基于 Scrapy 设计理念,但更贴合现代 Python 开发习惯。
  • 分布式支持:内置分布式队列和调度,水平扩展无压力。
  • 插件丰富:支持自定义中间件、Pipeline,持久化、监控简单接入。
  • 示例生态:官方及社区提供多种行业示例,快速上手。

二、生动比喻

想象你要送快递:

  1. 分拣中心:接收并整理包裹(任务调度)
  2. 配送员:拿着包裹去各个地址(爬虫 Worker)
  3. 快递柜:存放收集好的包裹(Pipeline 存储)
  4. 后台系统:监控每个包裹的状态(监控告警)

Feapder 就是整个快递系统的“物流总控”,帮你把每个环节串起来,保证数据顺利、稳定地流转到最终存储。

三、技术场景

在企业级爬虫中,我们常常会遇到以下需求:

1. 使用代理 IP

  • 提升并发时避免 IP 限流和封禁
  • 引入爬虫代理:
# 亿牛云爬虫代理示例 www.16yun.cn
域名: proxy.16yun.cn 
端口: 12345  
用户名: 16YUN  
密码: 16IP

2. 设置 Cookie 和 User-Agent

  • Cookie:保持登录态或跑通多页
  • User-Agent:模拟浏览器请求,降低反爬几率

Feapder 支持在中间件中统一管理这些参数,代码简洁、易维护。

四、实战案例:采集 51job 企业招聘信息

下面我们以 https://www.51job.com 为例,演示如何用 Feapder 搭建完整的爬虫管道,采集岗位名称、职位信息、工作地址、薪资待遇,并分类存储到本地 JSON 文件。

1. 环境准备

# 安装 Feapder 及依赖
pip install feapder requests

2. 项目结构

feapder_job_pipeline/
├── spider.py         # 主爬虫脚本
├── settings.py       # 配置文件
└── pipelines.py      # 数据存储模块

3. 配置文件 settings.py

# settings.py

# ---------- 分布式及队列配置(可选) ----------
# REDIS_HOST = "127.0.0.1"
# REDIS_PORT = 6379
# REDIS_PASSWORD = None

# ---------- 代理设置 亿牛云代理示例 www.16yun.cn------
PROXY = {
   
    "domain": "proxy.16yun.cn", # 亿牛云代理域名
    "port": 8100,             # 代理端口
    "username": "16YUN",     # 代理用户名
    "password": "16IP",     # 代理密码
}

# ---------- 中间件配置 ----------
DOWNLOADER_MIDDLEWARES = {
   
    # 自定义代理中间件
    "middlewares.ProxyMiddleware": 500,
    # Feapder 默认 UserAgent 中间件
    # "feapder.downloadermiddleware.useragent.UserAgentMiddleware": 400,
}

# ---------- Pipeline 配置 ----------
ITEM_PIPELINES = {
   
    "pipelines.JsonPipeline": 300,
}

4. 自定义中间件 middlewares.py

# middlewares.py
import base64
from feapder import Request

class ProxyMiddleware:
    """通过亿牛云代理发送请求的中间件"""

    def process_request(self, request: Request):
        # 构造代理认证字符串
        auth_str = f"{request.setting.PROXY['username']}:{request.setting.PROXY['password']}"
        b64_auth = base64.b64encode(auth_str.encode()).decode()

        # 设置 request.meta 中的 proxy
        request.request_kwargs.setdefault("proxies", {
   
            "http": f"http://{request.setting.PROXY['domain']}:{request.setting.PROXY['port']}",
            "https": f"http://{request.setting.PROXY['domain']}:{request.setting.PROXY['port']}"
        })
        # 注入 Proxy-Authorization 头
        request.request_kwargs.setdefault("headers", {
   })["Proxy-Authorization"] = f"Basic {b64_auth}"
        return request

5. 数据存储 pipelines.py

# pipelines.py
import json
import os
from feapder import Item

class JobItem(Item):
    """定义岗位信息结构"""
    def __init__(self):
        self.position = None
        self.company = None
        self.location = None
        self.salary = None

class JsonPipeline:
    """将数据按照公司分类存储到 JSON 文件"""

    def open_spider(self, spider):
        # 创建存储目录
        self.base_path = spider.setting.get("DATA_PATH", "./data")
        os.makedirs(self.base_path, exist_ok=True)

    def process_item(self, item: JobItem, spider):
        # 按公司名称分类存储
        company = item.company or "unknown"
        file_path = os.path.join(self.base_path, f"{company}.json")

        # 追加写入
        with open(file_path, "a", encoding="utf-8") as f:
            f.write(json.dumps(dict(item), ensure_ascii=False) + "\n")

        return item

6. 爬虫脚本 spider.py

# spider.py
from feapder import Spider, Request
from pipelines import JobItem
import random

class JobSpider(Spider):
    """
    Feapder 爬虫:采集 51job 企业招聘信息
    """
    def start_requests(self):
        # 入口 URL,搜索“Python 开发”岗位
        url = "https://search.51job.com/list/000000,000000,0000,00,9,99,Python开发,2,1.html"
        yield Request(url, callback=self.parse_list)

    def parse_list(self, request, response):
        # 解析列表页中的每个岗位链接
        for job in response.xpath("//div[@class='el']/p[@class='t1']/span/a"):
            job_url = job.xpath("./@href").extract_first()
            yield Request(job_url, callback=self.parse_detail)

        # 分页(示例:最多采集前 5 页)
        if int(request.url.split(",")[-1].split(".")[0]) < 5:
            next_page = int(request.url.split(",")[-1].split(".")[0]) + 1
            next_url = request.url.replace(f",{int(request.url.split(',')[-1].split('.')[0])}.html", f",{next_page}.html")
            yield Request(next_url, callback=self.parse_list)

    def parse_detail(self, request, response):
        """解析岗位详情页"""
        item = JobItem()
        item.position = response.xpath("//h1/text()").extract_first().strip()     # 岗位名称
        item.company = response.xpath("//a[@class='catn']/text()").extract_first().strip()  # 公司名称
        item.location = response.xpath("//span[@class='lname']/text()").extract_first().strip()  # 工作地点
        item.salary = response.xpath("//span[@class='salary']/text()").extract_first().strip()   # 薪资待遇
        yield item

    def download_midware(self, request):
        """
        在请求中注入 Cookie 与 User-Agent
        """
        headers = {
   
            # 随机选择常见浏览器 UA
            "User-Agent": random.choice([
                "Mozilla/5.0 (Windows NT 10.0; Win64; x64)...",
                "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)..."
            ]),
            # 示例 Cookie,可根据需要替换
            "Cookie": "your_cookie_string_here"
        }
        request.request_kwargs.setdefault("headers", {
   }).update(headers)
        return request

if __name__ == "__main__":
    JobSpider(**{
   
        "project_name": "feapder_job_pipeline",
        # 可选:指定本地分布式队列
        # "redis_key": "job_spider_requests",
        # "processes": 4,
    }).start()

7. 运行与结果

python spider.py
  • 运行后,./data/ 目录下会出现以公司名命名的 JSON 文件,每行一条岗位信息。

五、扩展阅读

  • Feapder 官方文档:https://feapder.com/
  • Scrapy 官方文档(原理参考):https://docs.scrapy.org/
  • 爬虫代理使用指引:登录亿牛云官网查看“文档中心”
  • 同类案例:使用 Playwright 架构多语言爬虫(可对比)

通过本文演示,你已经掌握了如何用 Feapder 快速构建一个带有代理、Cookie、User-Agent 的企业级爬虫管道,并能将数据分类存储。接下来可以尝试接入数据库、监控告警,或将爬虫部署到 Kubernetes 集群,打造真正的生产级数据管道。

相关文章
|
1月前
|
机器学习/深度学习 JSON 算法
京东拍立淘图片搜索 API 接入实践:从图像识别到商品匹配的技术实现
京东拍立淘图片搜索 API 是基于先进图像识别技术的购物搜索接口,支持通过上传图片、URL 或拍摄实物搜索相似商品。它利用机器学习和大数据分析,精准匹配商品特征,提供高效、便捷的搜索体验。接口覆盖京东海量商品资源,不仅支持外观、颜色等多维度比对,还结合用户行为数据实现智能推荐。请求参数包括图片 URL 或 Base64 编码,返回 JSON 格式的商品信息,如 ID、价格、链接等,助力消费者快速找到心仪商品,满足个性化需求。
118 18
|
1月前
|
机器学习/深度学习 人工智能 自然语言处理
3 秒音频也能克隆?拆解 Spark-TTS 架构的极致小样本学习
本文深入解析了 Spark-TTS 模型的架构与原理,该模型仅需 3 秒语音样本即可实现高质量的零样本语音克隆。其核心创新在于 BiCodec 单流语音编码架构,将语音信号分解为语义 Token 和全局 Token,实现内容与音色解耦。结合大型语言模型(如 Qwen 2.5),Spark-TTS 能直接生成语义 Token 并还原波形,简化推理流程。实验表明,它不仅能克隆音色、语速和语调,还支持跨语言朗读及情感调整。尽管面临相似度提升、样本鲁棒性等挑战,但其技术突破为定制化 AI 声音提供了全新可能。
174 35
|
1月前
|
存储 人工智能 API
RAG-MCP:基于检索增强生成的大模型工具选择优化框架
RAG-MCP是一种通过检索增强生成技术解决大型语言模型(LLM)工具选择困境的创新框架。它针对提示词膨胀和决策效率低的问题,利用语义检索动态筛选相关工具,显著减少提示词规模并提升准确率。本文深入解析其技术原理,包括外部工具索引构建、查询时检索处理等核心步骤,以及实验评估结果。RAG-MCP不仅优化了LLM的工具使用能力,还为AI代理的发展提供了重要支持,未来可在极端规模检索、多工具工作流等方面进一步探索。
149 16
RAG-MCP:基于检索增强生成的大模型工具选择优化框架
|
1月前
|
数据采集 运维 API
把Postman调试脚本秒变Python采集代码的三大技巧
本文介绍了如何借助 Postman 调试工具快速生成 Python 爬虫代码,并结合爬虫代理实现高效数据采集。文章通过“跨界混搭”结构,先讲解 Postman 的 API 调试功能,再映射到 Python 爬虫技术,重点分享三大技巧:利用 Postman 生成请求骨架、通过 Session 管理 Cookie 和 User-Agent,以及集成代理 IP 提升稳定性。以票务信息采集为例,展示完整实现流程,探讨其在抗封锁、团队协作等方面的价值,帮助开发者快速构建生产级爬虫代码。
把Postman调试脚本秒变Python采集代码的三大技巧
|
1月前
|
监控 Kubernetes Go
日志采集效能跃迁:iLogtail 到 LoongCollector 的全面升级
LoongCollector 在日志场景中实现了全面的重磅升级,从功能、性能、稳定性等各个方面均进行了深度优化和提升,本文我们将对 LoongCollector 的升级进行详细介绍。
299 86
|
23天前
|
存储 Rust Go
介绍一下这只小水獭 —— Fluss Logo 背后的故事
Fluss是一款开源流存储项目,致力于为Lakehouse架构提供高效的实时数据层。其全新Logo以一只踏浪前行的小水獭为核心形象,象征流动性、适应性和友好性。水獭灵感源于“Fluss”德语中“河流”的含义,传递灵活与亲和力。经过30多版设计迭代,最终呈现动态活力的视觉效果。Fluss计划捐赠给Apache软件基金会,目前已开启孵化提案。社区还推出了系列周边礼品,欢迎加入钉钉群109135004351参与交流!
508 2
介绍一下这只小水獭 —— Fluss Logo 背后的故事
|
24天前
|
机器学习/深度学习 数据采集 存储
大模型微调知识与实践分享
本文详细介绍了大型语言模型(LLM)的结构、参数量、显存占用、存储需求以及微调过程中的关键技术点,包括Prompt工程、数据构造、LoRA微调方法等。
291 72
大模型微调知识与实践分享
|
1月前
|
数据采集 人工智能 大数据
大数据+商业智能=精准决策,企业的秘密武器
大数据+商业智能=精准决策,企业的秘密武器
107 27
|
24天前
|
存储 安全 网络协议
阿里云服务器通用型实例怎么选?g7/g8y/g8i适用场景、性能对比与选择参考
在选择云服务器实例规格时,对于需要平衡计算、存储和网络性能的应用场景来说,一般会选择通用型实例规格,在阿里云目前的活动中,属于通用型实例的主要有通用型g7、通用型g8y和通用型g8i实例。为了帮助大家更好地了解这三款实例的区别,并为选择提供参考,本文将详细对比它们的实例规格、CPU、内存、计算、存储、网络等方面的性能,并附上活动价格对比,以便用户能够全面了解它们之间的不同,以作参考选择。
|
1月前
|
机器学习/深度学习 PyTorch 编译器
深入解析torch.compile:提升PyTorch模型性能、高效解决常见问题
PyTorch 2.0推出的`torch.compile`功能为深度学习模型带来了显著的性能优化能力。本文从实用角度出发,详细介绍了`torch.compile`的核心技巧与应用场景,涵盖模型复杂度评估、可编译组件分析、系统化调试策略及性能优化高级技巧等内容。通过解决图断裂、重编译频繁等问题,并结合分布式训练和NCCL通信优化,开发者可以有效提升日常开发效率与模型性能。文章为PyTorch用户提供了全面的指导,助力充分挖掘`torch.compile`的潜力。
122 17