本文将带你从零开始,借助 Feapder 快速搭建一个企业级招聘信息数据管道。在“基础概念”部分,我们先了解什么是数据管道和 Feapder;“生动比喻”用日常场景帮助你快速理解爬虫组件;“技术场景”介绍本项目中如何使用代理等采集策略;“实战案例”通过完整代码演示采集 51job 招聘信息并分类存储;最后在“扩展阅读”推荐一些进一步学习的资源。无论你是非技术背景的产品经理,还是校园里的同学,都能轻松上手,快速构建自己的企业级爬虫管道。
一、基础概念
1. 什么是数据管道?
- 数据管道(Data Pipeline)指的是从数据源(如网页、API)到数据仓库(如数据库、文件)的整个流转过程,通常包括数据获取、清洗、存储和监控。
- 在企业级场景下,管道需要稳定可靠、易于扩展,并支持重试、分布式、监控告警等能力。
2. 为什么选 Feapder?
- 轻量易用:基于 Scrapy 设计理念,但更贴合现代 Python 开发习惯。
- 分布式支持:内置分布式队列和调度,水平扩展无压力。
- 插件丰富:支持自定义中间件、Pipeline,持久化、监控简单接入。
- 示例生态:官方及社区提供多种行业示例,快速上手。
二、生动比喻
想象你要送快递:
- 分拣中心:接收并整理包裹(任务调度)
- 配送员:拿着包裹去各个地址(爬虫 Worker)
- 快递柜:存放收集好的包裹(Pipeline 存储)
- 后台系统:监控每个包裹的状态(监控告警)
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 集群,打造真正的生产级数据管道。