{"id":20450012,"url":"https://github.com/turboway/spiderman","last_synced_at":"2025-04-04T23:06:45.573Z","repository":{"id":37086670,"uuid":"262529259","full_name":"TurboWay/spiderman","owner":"TurboWay","description":"基于 scrapy-redis 的通用分布式爬虫框架","archived":false,"fork":false,"pushed_at":"2023-03-31T14:54:24.000Z","size":4463,"stargazers_count":601,"open_issues_count":8,"forks_count":128,"subscribers_count":17,"default_branch":"master","last_synced_at":"2025-03-28T22:11:28.351Z","etag":null,"topics":["hbase","hive","kafka","rdbm","scapy-redis","scrapy","spiderman"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/TurboWay.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2020-05-09T08:52:49.000Z","updated_at":"2025-03-25T09:24:26.000Z","dependencies_parsed_at":"2024-01-16T06:07:48.686Z","dependency_job_id":"fc1cae9a-1f74-470f-835b-a93b1af7b943","html_url":"https://github.com/TurboWay/spiderman","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TurboWay%2Fspiderman","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TurboWay%2Fspiderman/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TurboWay%2Fspiderman/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TurboWay%2Fspiderman/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TurboWay","download_url":"https://codeload.github.com/TurboWay/spiderman/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247261600,"owners_count":20910108,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["hbase","hive","kafka","rdbm","scapy-redis","scrapy","spiderman"],"created_at":"2024-11-15T10:49:40.068Z","updated_at":"2025-04-04T23:06:45.556Z","avatar_url":"https://github.com/TurboWay.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# spiderman\n![](https://img.shields.io/badge/python-3.6-brightgreen)\n![](https://img.shields.io/badge/Scrapy-1.6%2B-orange)\n![](https://img.shields.io/badge/scrapy--redis-0.6%2B-yellowgreen)\n![](https://img.shields.io/badge/SQLAlchemy-1.3%2B-green)\n\n基于 scrapy-redis 的通用分布式爬虫框架\n\n\n\n****\n## 目录\n* [效果图](#demo采集效果)\n\n    * [采集效果](#demo采集效果)\n    * [爬虫元数据](#爬虫元数据)\n    * [分布式爬虫运行](#cluster模式)\n    * [单机爬虫运行](#standalone模式)\n    * [附件下载](#附件下载)      \n    * [kafka实时采集监控示例](#kafka实时采集监控)   \n    \n* [介绍](#功能)\n    * [功能](#功能)\n    * [原理说明](#原理说明)    \n\n* [快速开始](#下载安装)\n    * [下载安装](#下载安装)\n    * [如何开发一个新爬虫](#如何开发一个新爬虫)\n    * [如何进行补爬](#如何进行补爬)\n    * [如何下载附件](#如何下载附件)\n    * [如何扩展分布式爬虫](#如何扩展分布式爬虫)\n    * [如何管理爬虫元数据](#如何管理爬虫元数据)\n    * [如何配合kafka做实时采集监控](#如何配合kafka做实时采集监控)\n    * [如何使用爬虫api](#如何使用爬虫api)\n    \n* [其它](#注意事项)\n    * [注意事项](#注意事项)\n    * [hive环境问题](#hive环境问题)\n    * [更新日志](#更新日志)\n    * [TODO](#TODO)\n\n### demo采集效果\n\n![image](https://gitee.com/TurboWay/blogimg/raw/master/img/file.jpg)\n\n![image](https://gitee.com/TurboWay/blogimg/raw/master/img/image-20210317145454296.png)\n\n![image](https://gitee.com/TurboWay/blogimg/raw/master/img/image-20210317145413391.png)\n\n### 爬虫元数据\n![meta](https://gitee.com/TurboWay/blogimg/raw/master/img/meta.jpg)\n\n### cluster模式\n![cluster](https://gitee.com/TurboWay/blogimg/raw/master/img/cluster.jpg)\n\n### standalone模式\n![image-20210323141940525](https://gitee.com/TurboWay/blogimg/raw/master/img/image-20210323141940525.png)\n\n### 附件下载\n![image-20210318161618307](https://gitee.com/TurboWay/blogimg/raw/master/img/image-20210318161618307.png)\n\n\n### kafka实时采集监控\n![mon](https://gitee.com/TurboWay/blogimg/raw/master/img/mon.jpg)\n\n### 功能\n\n- 自动建表\n- 自动生成爬虫代码，只需编写少量代码即可完成分布式爬虫\n- 自动存储元数据，分析统计和补爬都很方便\n- 适合多站点开发，每个爬虫独立定制，互不影响\n- 调用方便，可以根据传参自定义采集的页数以及启用的爬虫数量\n- 扩展简易，可以根据需要选择采集模式，单机 standalone (默认) 或者 分布式cluster\n- 采集数据落地方便，支持多种数据库，只需在 spider 中启用相关的管道\n\n    关系型\n    - [x] mysql\n    - [x] sqlserver\n    - [x] oracle\n    - [x] postgresql\n    - [x] sqlite3    \n  \n    非关系型\n    - [x] hbase    \n    - [x] mongodb\n    - [x] elasticsearch\n    - [x] hdfs\n    - [x] hive \n    - [x] doris\n    - [x] datafile, 比如 csv\n    \n- 反爬处理简易，已封装各种反爬中间件\n    - [x] 随机 UserAgent\n    - [x] 定制请求头 Headers\n    - [x] 定制 Cookies 池\n    - [x] 定制代理 ip\n    - [x] 在 scrapy 中使用 requests\n    - [x] Payload 请求\n    - [x] 使用 Splash 渲染 js\n\n\n### 原理说明\n1. 消息队列使用 redis，采集策略使用广度优先，先进先出\n2. 每个爬虫都有一个 job 文件，使用 job 来生成初始请求类 ScheduledRequest，并将其推送到 redis；\n初始请求全部推到 redis 后，运行 spider 解析生成数据 并迭代新的请求到redis, 直到 redis 中的全部请求被消耗完\n```python\n# scrapy_redis请求类\nclass ScheduledRequest:\n\n    def __init__(self, **kwargs):\n        self.url = kwargs.get('url')                 # 请求url\n        self.method = kwargs.get('method', 'GET')   # 请求方式 默认get\n        self.callback = kwargs.get('callback')  # 回调函数，指定spider的解析函数\n        self.body = kwargs.get('body')  # body, method为post时, 作为 post表单\n        self.meta = kwargs.get('meta')  # meta, 携带元数据，比如 pagenum\n```\n3. item 类定义表名、字段名、排序号(自定义字段顺序)、注释说明(便于管理元数据)、字段类型(仅关系型数据库管道有效) \n```python\nclass zhifang_list_Item(scrapy.Item):\n    #  define table\n    tablename = 'zhifang_list'\n    tabledesc = '列表'\n    # define the fields for your item here like:\n    # 关系型数据库，可以自定义字段的类型、长度，默认 VARCHAR(length=255)\n    # colname = scrapy.Field({'idx': 1, 'comment': '名称', 'type': VARCHAR(255)})\n    tit = scrapy.Field({'idx': 1, 'comment': '房屋标题'})\n    txt = scrapy.Field({'idx': 2, 'comment': '房屋描述'})\n    tit2 = scrapy.Field({'idx': 3, 'comment': '房屋楼层'})\n    price = scrapy.Field({'idx': 4, 'comment': '房屋价格'})\n    agent = scrapy.Field({'idx': 5, 'comment': '房屋中介'})\n    # default column\n    detail_full_url = scrapy.Field({'idx': 100, 'comment': '详情链接'})  # 通用字段\n    pkey = scrapy.Field({'idx': 101, 'comment': 'md5(detail_full_url)'})  # 通用字段\n    pagenum = scrapy.Field({'idx': 102, 'comment': '页码'})  # 通用字段\n```\n\n4. 去重策略，默认不去重，每次采集独立，即每次启动 job 都会清空上一次未完成的 url，并且不保留 redis 中上一次已采集的 url 指纹。 \n   如需调整可以修改以下配置\n\n- job 文件（单个爬虫）\n```python\nclass zhifang_job(SPJob):\n\n    def __init__(self):\n        super().__init__(spider_name=zhifang_Spider.name)\n        # self.delete()   # 如需去重、增量采集，请注释该行\n```\n\n- spider 文件（单个爬虫）\n```python\n    custom_settings = {\n        ...,\n        'DUPEFILTER_CLASS': 'scrapy_redis.dupefilter.RFPDupeFilter',\n        'SCHEDULER_PERSIST': True, # 开启持久化\n    }\n   \n    def get_callback(self, callback):\n        # url去重设置：True 不去重 False 去重\n        callback_dt = {\n            'list': (self.list_parse, False),\n            'detail': (self.detail_parse, False),\n        }\n        return callback_dt.get(callback)\n```\n\n- 布隆过滤器。\n\n\u003e 当采集的数据量很大时，可以使用布隆过滤器，该算法占用空间小且可控，适合海量数据去重。\n\u003e 但是该算法会有漏失率，对爬虫而言就是漏爬。可以通过调整过滤器负载个数、内存配置、哈希次数以降低漏失率。\n\u003e 默认 1 个过滤器，256 M 内存，使用 7 个 seeds，这个配置表示漏失概率为 8.56e-05 时，可满足 0.93 亿条字符串的去重。当漏失率为 0.000112 时，可满足 0.98 亿条字符串的去重。[调参与漏失率参考](https://blog.csdn.net/Bone_ACE/article/details/53107018)\n\n```python\n    custom_settings = {\n        ...,\n        'DUPEFILTER_CLASS': 'SP.bloom_dupefilter.BloomRFDupeFilter',  # 使用布隆过滤器\n        'SCHEDULER_PERSIST': True,  # 开启持久化\n        'BLOOM_NUM': 1,  # 布隆过滤器负载个数，当内存达到限制时，可以增加负载个数\n        'BLOOM_MEM': 256,  # 布隆过滤器内存大小（单位 M），内存最大 512 M （因为 redis string 最大只能 512 M）\n        'BLOOM_K': 7,  # 布隆过滤器哈希次数，次数越少，去重越快，但是漏失率越高\n    }\n   \n    def get_callback(self, callback):\n        # url去重设置：True 不去重 False 去重\n        callback_dt = {\n            'list': (self.list_parse, False),\n            'detail': (self.detail_parse, False),\n        }\n        return callback_dt.get(callback)\n```\n\n### 下载安装\n\n1. git clone https://github.com/TurboWay/spiderman.git; cd spiderman;\n2. 【不使用虚拟环境的话，可以跳过步骤23】virtualenv -p /usr/bin/python3 venv\n3. 【不使用虚拟环境的话，可以跳过步骤23】source venv/bin/activate\n4. pip install -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt\n5. 修改配置 vi SP/settings.py\n6. 运行demo示例 python SP_JOBS/zhifang_job.py\n\n\n### 如何开发一个新爬虫\n\n运行 easy_scrapy.py 会根据模板自动生成以下代码文件，并自动在编辑器打开 spidername_job.py 文件；\n\n| 类别 | 路径  | 说明  |\n| ------------ | ------------ | ------------ |\n| job       | SP_JOBS/spidername_job.py             | 编写初始请求 |\n| spider    | SP/spiders/spidername.py              | 编写解析规则，产生新的请求  |\n| items     | SP/items/spidername_items.py          | 定义表名字段  |\n\n以上代码文件编写完成后，直接执行 python SP_JOBS/spidername_job.py\n\n或者动态传参（参数说明 -p 采集页数， -n 启用爬虫数量） python SP_JOBS/spidername_job.py -p 10 -n 1\n\n\n### 如何进行补爬\n\n运行 easy_scrapy.py 会根据模板自动生成以下代码文件，并自动在编辑器打开 spidername_job_patch.py 文件；\n\n| 类别 | 路径  | 说明  |\n| ------------ | ------------ | ------------ |\n| job | SP_JOBS/spidername_job_patch.py  | 编写补爬请求 |\n\n以上代码文件编写完成后，直接执行 python SP_JOBS/spidername_job_patch.py\n\n### 如何下载附件\n\n提供两种方式下载：\n* 1、直接在 spider 中启用附件下载管道\n* 2、使用自定义的下载器 execute_download.py 传参下载\n\n\u003e jpg/pdf/word...等各种各样的文件，统称为附件。\n\u003e 下载附件是比较占用带宽的行为，所以在大规模采集中，最好是先把结构化的表数据、附件的元数据入库，\n\u003e 保证数据的完整性，然后再根据需要，通过下载器进行附件下载。\n\n\n### 如何扩展分布式爬虫\n\n采集模式有两种(在 settings 控制)： 单机 standalone(默认) 和 集群分布式\n\n如果想切换成分布式爬虫，需要在 spiderman/SP/settings.py 中启用以下配置\n\n \u003cfont color='red'\u003e  注意：前提是 所有SLAVE机器的爬虫代码一致、python环境一致，都可以运行爬虫demo \u003c/font\u003e\n\n```python\n# 集群模式 False 单机 (默认);  True 分布式 需要配置下方的 slaves\nCLUSTER_ENABLE = True\n```\n\n| 配置名称 | 意义  | 示例  |\n| ------------ | ------------ | ------------ |\n| SLAVES       | 【二选一】爬虫机器配置列表  | [{'host': '172.16.122.12', 'port': 22, 'user': 'spider', 'pwd': 'spider'}，\u003cbr\u003e{'host': '172.16.122.13', 'port': 22, 'user': 'spider', 'pwd': 'spider'} ] |\n| SLAVES_BALANCE | 【二选一】爬虫机器配置(ssh负载均衡) | {'host': '172.16.122.11', 'port': 2202, 'user': 'spider', 'pwd': 'spider'}  |\n| SLAVES_ENV     | 【可选】爬虫机器虚拟环境路径  | /home/spider/workspace/spiderman/venv  |\n| SLAVES_WORKSPACE | 【必填】爬虫机器代码工程路径  | /home/spider/workspace/spiderman  |\n\n\n### 如何管理爬虫元数据\n\n运行 easy_meta.py 自动生成当前项目所有爬虫的元数据, 默认记录到sqlite meta.db, 可以在 setting 中自行配置; \n\n```python\n# 爬虫 meta\nMETA_ENGINE = 'sqlite:///meta.db'\n```\n\n元数据表meta字典如下：\n\n| 字段名 | 类型 | 注释  |\n| ------------ | ------------ | ------------ |\n| spider        | varchar(50) | 爬虫名 |\n| spider_comment| varchar(100) | 爬虫描述 |\n| tb             | varchar(50) | 表名 |\n| tb_comment     | varchar(100) | 表描述 |\n| col_px        | int | 字段序号 |\n| col           | varchar(50) | 字段名 |\n| col_comment   | varchar(100) | 字段描述 |\n| author        | varchar(20) | 开发人员 |\n| addtime       | varchar(20) | 开发时间 |\n| insertime     | varchar(20) | 元数据更新时间 |\n\n\n### 如何配合kafka做实时采集监控\n\n1. 配置 kafka（修改 setting 的 KAFKA_SERVERS）\n2. 自定义监控规则（修改编写 kafka_mon.py , 并运行该脚本程序, 开始监控）\n3. 在 spider 中启用 kafka 管道（运行爬虫 job , 开始采集）\n\n### 如何使用爬虫api\n\n直接运行 api.py，然后可以通过 http://127.0.0.1:2021/docs 查看相关的 api 文档\n\n### 注意事项\n1. 字段名称不能使用 tablename、isload、ctime、bizdate、spider 等字段，因为这些字段被作为通用字段，避免冲突\n2. items 文件每个字段建议添加注释，生成元数据时，会将注释导入到元数据表，便于管理爬虫\n\n\n### hive环境问题\n在 windows 环境下，使用 python3 连接 hive 会有很多坑，所以使用 hdfs 管道时，hive 自动建表功能默认关闭，便于部署。\n假如需要启用 hive 自动建表功能，请进行如下操作：\n\n1. pip install -i https://pypi.tuna.tsinghua.edu.cn/simple -r requirements.txt\n2. pip install --no-deps thrift-sasl==0.2.1\n3. 验证环境，执行 SP.utils.ctrl_hive \n\n如果执行成功，说明 hive 环境准备完毕，可以直接启用 hive 自动建表功能；如果遇到问题，可以参考 [【大数据】windows 下python3连接hive](https://www.cnblogs.com/TurboWay/p/12975034.html)\n\n\n### 更新日志\n\n| 日期       | 更新内容                                                                                                                                                                                                                          |\n|----------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| 20200803 | 1.使用更优雅的方式来生成元数据; \u003cbr\u003e 2.管道函数传参的写法调整; \u003cbr\u003e 3.附件表通用字段更名：下载状态 (isload =\u003e status)                                                                                                                                                |\n| 20200831 | 1.解决数据入库失败时，一直重试入库的问题; \u003cbr\u003e 2.所有管道优化，入库失败时，自动切换成逐行入库，只丢弃异常记录                                                                                                                                                                  |\n| 20201104 | 1.requests 中间件支持 DOWNLOAD_TIMEOUT、DOWNLOAD_DELAY                                                                                                                                                                              |\n| 20201212 | 1.payload 中间件支持 DOWNLOAD_TIMEOUT、DOWNLOAD_DELAY; \u003cbr\u003e 2.get_sp_cookies 方法优化，使用轻量级的 splash 替换 selenium; \u003cbr\u003e 3.md 的原理部分增加去重策略的说明                                                                                               |\n| 20210105 | 1.增加布隆过滤器                                                                                                                                                                                                                     |\n| 20210217 | 1.elasticsearch 管道调整，兼容 elasticsearch7 以上版本，直接使用表名作为索引名                                                                                                                                                                       |\n| 20210314 | 1.所有反爬中间件合并到 SPMiddleWare                                                                                                                                                                                                     |\n| 20210315 | 1.使用更优雅的方式生成 job 初始请求; \u003cbr\u003e 2.headers 中间件优化，减少 redis 的内存占用; \u003cbr\u003e 3.删除 cookie 中间件，cookie 只是 headers 里面的一个值，可以直接使用 headers 中间件; \u003cbr\u003e 4.删除 Payload 中间件，Payload 请求可以直接使用 requests 中间件 \u003cbr\u003e 5.增加 CookiesPool 中间件，用于需要多个账号随机切换采集的场景 |\n| 20210317 | 1.增加可以脱离 scrapy 独立工作的、支持分布式的附件下载器                                                                                                                                                                                             |\n| 20210318 | 1.增加 api 服务                                                                                                                                                                                                                   |\n| 20210323 | 1.job 日志输出优化                                                                                                                                                                                                                  |\n| 20210330 | 1.kafka 管道优化，如果主题有多个分区，则数据均匀地写到每个分区                                                                                                                                                                                           |\n| 20230210 | 1.增加支持 Apache Doris |                                                                                                                                                                                                          |                                                                                                                                                                                                                      |                                                                                                                                                                                                                        |                                                                                                                                                                                                                        |","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fturboway%2Fspiderman","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fturboway%2Fspiderman","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fturboway%2Fspiderman/lists"}