赞
踩
官网:https://feapder.com/#/
feapder是一款上手简单,功能强大的Python爬虫框架,内置AirSpider、Spider、TaskSpider、BatchSpider四种爬虫解决不同场景的需求,但像任何工具一样,它也有其优点和缺点。以下是 feapder 的一些优缺点:
优点:
pip install feapder #精简版,不支持浏览器渲染、不支持基于内存去重、不支持入库mongo
pip install "feapder[render]" #浏览器渲染版,不支持基于内存去重、不支持入库mongo
pip install "feapder[all]" #完整版,支持所有功能
使用:feapder <command> [options] [args]
create:创建项目
shell:交互式环境
zip:压缩项目,项目打包
retry:重试
-h, --help 查看create命令行帮助信息,feapder create -h
-p , --project 创建项目,feapder create -p <project_name>
-s , --spider 创建爬虫,feapder create -s <spider_name>
-i , --item 创建item ,feapder create -i <table_name> 支持模糊匹配 如 feapder create -i %table_name%
-t , --table 根据json创建表,feapder create -t <table_name>
-init 创建__init__.py,会自动引入当前目录下的所有py文件到__all__中,feapder create -init
-j, --json 创建json,feapder create -j
-sj, --sort_json 创建有序json,feapder create -sj
-c, --cookies 创建cookie
--params 解析地址中的参数
--setting 创建全局配置文件feapder create --setting
# feapder create -i spider_data --host localhost --db feapder --username feapder --password feapder123
--host mysql 连接地址,常和-i搭配使用,也可直接在setting文件配置mysql配置
--port mysql 端口,常和-i搭配使用,也可直接在setting文件配置mysql配置
--username mysql 用户名,常和-i搭配使用,也可直接在setting文件配置mysql配置
--password mysql 密码,常和-i搭配使用,也可直接在setting文件配置mysql配置
--db mysql 数据库名,常和-i搭配使用,也可直接在setting文件配置mysql配置
-h, --help 查看shell命令行帮助信息,feapder shell -h
-u , --url 请求指定地址, feapder shell --url http://www.spidertools.cn/
-c, --curl 执行curl,调试响应, feapder shell --curl http://www.spidertools.cn/
-h, --help 查看shell命令行帮助信息,feapder zip -h
-i 忽略文件,逗号分隔,支持正则
-I 忽略文件夹,逗号分隔,支持正则
-o 输出路径,默认为当前目录
-h, --help 查看shell命令行帮助信息,feapder retry -h
-r , --request 重试失败的request 如 feapder retry --request <redis_key>
-i , --item 重试失败的item 如 feapder retry --item <redis_key>
item为与数据库表的映射,与数据入库的逻辑相关。 在使用此命令前,需在数据库中创建好表,且setting.py中配置好数据库连接地址
Item和UpdateItem区别,UpdateItem可以根据数据库的唯一索引,插入数据时发现数据已存在,则更新数据,而item不会更新
#创建douban表
CREATE TABLE IF NOT EXISTS douban(
id INT AUTO_INCREMENT,
title VARCHAR(255),
rating FLOAT,
quote VARCHAR(255),
intro TEXT,
PRIMARY KEY(id)
)
from feapder import Item
class DoubanItem(Item):
"""
This class was generated by feapder
command: feapder create -i douban
"""
__table_name__ = "douban"
def __init__(self, *args, **kwargs):
super().__init__(**kwargs)
# self.id = None
self.intro = None
self.quote = None
self.rating = None
self.title = None
from feapder import Item
class DoubanItem(Item):
"""
This class was generated by feapder
command: feapder create -i douban 1
"""
__table_name__ = "douban"
def __init__(self, *args, **kwargs):
super().__init__(**kwargs)
# self.id = kwargs.get('id')
self.intro = kwargs.get('intro')
self.quote = kwargs.get('quote')
self.rating = kwargs.get('rating')
self.title = kwargs.get('title')
from feapder import UpdateItem
class DoubanItem(UpdateItem):
"""
This class was generated by feapder
command: feapder create -i douban
"""
__table_name__ = "douban"
def __init__(self, *args, **kwargs):
super().__init__(**kwargs)
# self.id = None
self.intro = None
self.quote = None
self.rating = None
self.title = None
from feapder import UpdateItem
class DoubanItem(UpdateItem):
"""
This class was generated by feapder
command: feapder create -i douban 1
"""
__table_name__ = "douban"
def __init__(self, *args, **kwargs):
super().__init__(**kwargs)
# self.id = kwargs.get('id')
self.intro = kwargs.get('intro')
self.quote = kwargs.get('quote')
self.rating = kwargs.get('rating')
self.title = kwargs.get('title')
redis_key:用于任务调度的 Redis 键名。任务队列中的任务将根据此键名进行调度和分发。
thread_count:爬虫的线程数。指定同时运行的线程数量,用于并发地处理任务。
begin_callback:爬虫开始时调用的回调函数。可以指定一个函数,在爬虫开始时执行特定的操作。
end_callback:爬虫结束时调用的回调函数。可以指定一个函数,在爬虫结束时执行特定的操作。
delete_keys:在爬虫结束时要删除的 Redis 键列表。可以传递一个包含要删除的键名的列表,用于清理任务队列中的任务。
keep_alive:指定是否保持爬虫在后台运行。设置为 True 时,爬虫将保持运行状态,不会自动退出。
auto_start_requests:指定是否自动开始爬取任务。设置为 True 时,爬虫会自动开始处理任务队列中的任务。
batch_interval:任务批处理的时间间隔。可以指定一个时间间隔(以秒为单位),用于控制任务的批处理。
wait_lock:指定是否等待锁释放。设置为 True 时,爬虫在获取任务锁时会等待,直到锁被释放才继续执行。
**kwargs:其他自定义参数。可以传递其他自定义参数作为关键字参数,用于配置爬虫的其他行为和属性。
redis_key:用于任务调度的 Redis 键名。任务队列中的任务将根据此键名进行调度和分发。
task_table:任务表的名称或对象。可以是一个字符串,表示任务表的名称,也可以是一个任务表对象,用于操作任务表。
task_table_type:任务表的类型,默认为 "mysql"。可以是 "mysql"、"mongodb" 或其他支持的任务表类型。
task_keys:任务键列表。指定任务表中的键名列表,用于唯一标识任务。
task_state:任务状态字段名,默认为 "state"。任务表中的该字段用于标识任务的状态。
min_task_count:最小任务数。指定任务表中的最小任务数量,当任务数量低于此值时,会触发任务补充。
check_task_interval:检查任务的时间间隔(秒)。指定任务补充的检查间隔,用于定期检查任务数量并进行补充。
task_limit:任务限制数。指定每次从任务表中获取的任务数量上限。
related_redis_key:关联的 Redis 键名。指定一个关联的 Redis 键名,用于在任务补充时进行关联任务的获取。
related_batch_record:关联任务的批处理记录。指定一个关联任务的批处理记录对象,用于在任务补充时进行关联任务的获取。
task_condition:任务查询条件。指定一个查询条件,用于筛选任务表中的任务。
task_order_by:任务排序方式。指定一个排序方式,用于对任务表中的任务进行排序。
thread_count:爬虫的线程数。指定同时运行的线程数量,用于并发地处理任务。
begin_callback:爬虫开始时调用的回调函数。可以指定一个函数,在爬虫开始时执行特定的操作。
end_callback:爬虫结束时调用的回调函数。可以指定一个函数,在爬虫结束时执行特定的操作。
delete_keys:在爬虫结束时要删除的 Redis 键列表。可以传递一个包含要删除的键名的列表,用于清理任务队列中的任务。
keep_alive:指定是否保持爬虫在后台运行。设置为 True 时,爬虫将保持运行状态,不会自动退出。
batch_interval:任务批处理的时间间隔。可以指定一个时间间隔(以秒为单位),用于控制任务的批处理。
use_mysql:是否使用 MySQL 数据库,默认为 True。设置为 False 时,将不会使用 MySQL 数据库进行任务操作。
**kwargs:其他自定义参数。可以传递其他自定义参数作为关键字参数,用于配置爬虫的其他行为和属性。
task_table:任务表的名称或对象。可以是一个字符串,表示任务表的名称,也可以是一个任务表对象,用于操作任务表。
batch_record_table:批处理记录表的名称或对象。可以是一个字符串,表示批处理记录表的名称,也可以是一个批处理记录表对象,用于操作批处理记录表。
batch_name:批处理的名称。指定批处理的名称,用于在批处理记录表中标识批处理的记录。
batch_interval:批处理的时间间隔(秒)。指定批处理的时间间隔,用于控制批处理的频率。
task_keys:任务键列表。指定任务表中的键名列表,用于唯一标识任务。
task_state:任务状态字段名,默认为 "state"。任务表中的该字段用于标识任务的状态。
min_task_count:最小任务数。指定任务表中的最小任务数量,当任务数量低于此值时,会触发任务补充。
check_task_interval:检查任务的时间间隔(秒)。指定任务补充的检查间隔,用于定期检查任务数量并进行补充。
task_limit:任务限制数。指定每次从任务表中获取的任务数量上限。
related_redis_key:关联的 Redis 键名。指定一个关联的 Redis 键名,用于在任务补充时进行关联任务的获取。
related_batch_record:关联任务的批处理记录。指定一个关联任务的批处理记录对象,用于在任务补充时进行关联任务的获取。
task_condition:任务查询条件。指定一个查询条件,用于筛选任务表中的任务。
task_order_by:任务排序方式。指定一个排序方式,用于对任务表中的任务进行排序。
redis_key:用于任务调度的 Redis 键名。任务队列中的任务将根据此键名进行调度和分发。
thread_count:爬虫的线程数。指定同时运行的线程数量,用于并发地处理任务。
begin_callback:爬虫开始时调用的回调函数。可以指定一个函数,在爬虫开始时执行特定的操作。
end_callback:爬虫结束时调用的回调函数。可以指定一个函数,在爬虫结束时执行特定的操作。
delete_keys:在爬虫结束时要删除的 Redis 键列表。可以传递一个包含要删除的键名的列表,用于清理任务队列中的任务。
keep_alive:指定是否保持爬虫在后台运行。设置为 True 时,爬虫将保持运行状态,不会自动退出。
auto_start_next_batch:是否自动启动下一批处理。设置为 True 时,当当前批处理完成后,会自动启动下一批处理。
**kwargs:其他自定义参数。可以传递其他自定义参数作为关键字参数,用于配置爬虫的其他行为和属性。
1.基础解析器:from feapder.core.base_parser import BaseParser,用于解析任务或批处理的参数和配置
task_table:任务表的名称或配置。可以是一个字符串,表示任务表的名称,也可以是一个字典,包含任务表的配置信息。
task_state:任务状态的配置。一个字典,包含任务状态的配置信息,用于定义任务的不同状态,如待处理、正在处理、已完成等。
mysqldb:MySQL 数据库连接对象。可选参数,用于指定连接到的 MySQL 数据库。
task_table:任务表的名称或配置。可以是一个字符串,表示任务表的名称,也可以是一个字典,包含任务表的配置信息。
batch_record_table:批处理记录表的名称或配置。可以是一个字符串,表示批处理记录表的名称,也可以是一个字典,包含批处理记录表的配置信息。
task_state:任务状态的配置。一个字典,包含任务状态的配置信息,用于定义任务的不同状态,如待处理、正在处理、已完成等。
date_format:日期格式的配置。一个字符串,表示日期的格式,用于解析和格式化日期。
mysqldb:MySQL 数据库连接对象。可选参数,用于指定连接到的 MySQL 数据库。
collector:用于收集数据的对象或组件。
redis_key:用于标识任务状态的 Redis 键名。
request_buffer:请求缓冲区,用于存储待处理的请求。
item_buffer:数据项缓冲区,用于存储待收集的数据项。
redis_key:用于标识任务状态的 Redis 键名。
redis_key:用于标识任务状态的 Redis 键名。
thread_count:调度器使用的线程数。
begin_callback:在开始调度时调用的回调函数。
end_callback:在结束调度时调用的回调函数。
delete_keys:在结束调度时删除的 Redis 键。
keep_alive:调度器是否保持活动状态。
auto_start_requests:是否自动开始请求。
batch_interval:批量处理请求的间隔时间。
wait_lock:等待锁的时间。
task_table:任务表的名称。
**kwargs:其他参数。
# -*- coding: utf-8 -*-
"""爬虫配置文件"""
# import os
# import sys
#
# # MYSQL
# MYSQL_IP = "localhost"
# MYSQL_PORT = 3306
# MYSQL_DB = ""
# MYSQL_USER_NAME = ""
# MYSQL_USER_PASS = ""
#
# # MONGODB
# MONGO_IP = "localhost"
# MONGO_PORT = 27017
# MONGO_DB = ""
# MONGO_USER_NAME = ""
# MONGO_USER_PASS = ""
#
# # REDIS
# # ip:port 多个可写为列表或者逗号隔开 如 ip1:port1,ip2:port2 或 ["ip1:port1", "ip2:port2"]
# REDISDB_IP_PORTS = "localhost:6379"
# REDISDB_USER_PASS = ""
# REDISDB_DB = 0
# # 适用于redis哨兵模式
# REDISDB_SERVICE_NAME = ""
#
# # 数据入库的pipeline,可自定义,默认MysqlPipeline
# ITEM_PIPELINES = [
# "feapder.pipelines.mysql_pipeline.MysqlPipeline",
# # "feapder.pipelines.mongo_pipeline.MongoPipeline",
# # "feapder.pipelines.console_pipeline.ConsolePipeline",
# ]
# EXPORT_DATA_MAX_FAILED_TIMES = 10 # 导出数据时最大的失败次数,包括保存和更新,超过这个次数报警
# EXPORT_DATA_MAX_RETRY_TIMES = 10 # 导出数据时最大的重试次数,包括保存和更新,超过这个次数则放弃重试
#
# # 爬虫相关
# # COLLECTOR
# COLLECTOR_TASK_COUNT = 32 # 每次获取任务数量,追求速度推荐32
#
# # SPIDER
# SPIDER_THREAD_COUNT = 1 # 爬虫并发数,追求速度推荐32
# # 下载时间间隔 单位秒。 支持随机 如 SPIDER_SLEEP_TIME = [2, 5] 则间隔为 2~5秒之间的随机数,包含2和5
# SPIDER_SLEEP_TIME = 0
# SPIDER_MAX_RETRY_TIMES = 10 # 每个请求最大重试次数
# KEEP_ALIVE = False # 爬虫是否常驻
# 下载
# DOWNLOADER = "feapder.network.downloader.RequestsDownloader"
# SESSION_DOWNLOADER = "feapder.network.downloader.RequestsSessionDownloader"
# RENDER_DOWNLOADER = "feapder.network.downloader.SeleniumDownloader"
# # RENDER_DOWNLOADER="feapder.network.downloader.PlaywrightDownloader",
# MAKE_ABSOLUTE_LINKS = True # 自动转成绝对连接
# # 浏览器渲染
# WEBDRIVER = dict(
# pool_size=1, # 浏览器的数量
# load_images=True, # 是否加载图片
# user_agent=None, # 字符串 或 无参函数,返回值为user_agent
# proxy=None, # xxx.xxx.xxx.xxx:xxxx 或 无参函数,返回值为代理地址
# headless=False, # 是否为无头浏览器
# driver_type="CHROME", # CHROME、EDGE、PHANTOMJS、FIREFOX
# timeout=30, # 请求超时时间
# window_size=(1024, 800), # 窗口大小
# executable_path=None, # 浏览器路径,默认为默认路径
# render_time=0, # 渲染时长,即打开网页等待指定时间后再获取源码
# custom_argument=[
# "--ignore-certificate-errors",
# "--disable-blink-features=AutomationControlled",
# ], # 自定义浏览器渲染参数
# xhr_url_regexes=None, # 拦截xhr接口,支持正则,数组类型
# auto_install_driver=True, # 自动下载浏览器驱动 支持chrome 和 firefox
# download_path=None, # 下载文件的路径
# use_stealth_js=False, # 使用stealth.min.js隐藏浏览器特征
# )
#
# PLAYWRIGHT = dict(
# user_agent=None, # 字符串 或 无参函数,返回值为user_agent
# proxy=None, # xxx.xxx.xxx.xxx:xxxx 或 无参函数,返回值为代理地址
# headless=False, # 是否为无头浏览器
# driver_type="chromium", # chromium、firefox、webkit
# timeout=30, # 请求超时时间
# window_size=(1024, 800), # 窗口大小
# executable_path=None, # 浏览器路径,默认为默认路径
# download_path=None, # 下载文件的路径
# render_time=0, # 渲染时长,即打开网页等待指定时间后再获取源码
# wait_until="networkidle", # 等待页面加载完成的事件,可选值:"commit", "domcontentloaded", "load", "networkidle"
# use_stealth_js=False, # 使用stealth.min.js隐藏浏览器特征
# page_on_event_callback=None, # page.on() 事件的回调 如 page_on_event_callback={"dialog": lambda dialog: dialog.accept()}
# storage_state_path=None, # 保存浏览器状态的路径
# url_regexes=None, # 拦截接口,支持正则,数组类型
# save_all=False, # 是否保存所有拦截的接口, 配合url_regexes使用,为False时只保存最后一次拦截的接口
# )
#
# # 爬虫启动时,重新抓取失败的requests
# RETRY_FAILED_REQUESTS = False
# # 保存失败的request
# SAVE_FAILED_REQUEST = True
# # request防丢机制。(指定的REQUEST_LOST_TIMEOUT时间内request还没做完,会重新下发 重做)
# REQUEST_LOST_TIMEOUT = 600 # 10分钟
# # request网络请求超时时间
# REQUEST_TIMEOUT = 22 # 等待服务器响应的超时时间,浮点数,或(connect timeout, read timeout)元组
# # item在内存队列中最大缓存数量
# ITEM_MAX_CACHED_COUNT = 5000
# # item每批入库的最大数量
# ITEM_UPLOAD_BATCH_MAX_SIZE = 1000
# # item入库时间间隔
# ITEM_UPLOAD_INTERVAL = 1
# # 内存任务队列最大缓存的任务数,默认不限制;仅对AirSpider有效。
# TASK_MAX_CACHED_SIZE = 0
#
# # 下载缓存 利用redis缓存,但由于内存大小限制,所以建议仅供开发调试代码时使用,防止每次debug都需要网络请求
# RESPONSE_CACHED_ENABLE = False # 是否启用下载缓存 成本高的数据或容易变需求的数据,建议设置为True
# RESPONSE_CACHED_EXPIRE_TIME = 3600 # 缓存时间 秒
# RESPONSE_CACHED_USED = False # 是否使用缓存 补采数据时可设置为True
#
# # 设置代理
# PROXY_EXTRACT_API = None # 代理提取API ,返回的代理分割符为\r\n
# PROXY_ENABLE = True
#
# # 随机headers
# RANDOM_HEADERS = True
# # UserAgent类型 支持 'chrome', 'opera', 'firefox', 'internetexplorer', 'safari','mobile' 若不指定则随机类型
# USER_AGENT_TYPE = "chrome"
# # 默认使用的浏览器头
# DEFAULT_USERAGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36"
# # requests 使用session
# USE_SESSION = False
#
# # 去重
# ITEM_FILTER_ENABLE = False # item 去重
# REQUEST_FILTER_ENABLE = False # request 去重
# ITEM_FILTER_SETTING = dict(
# filter_type=1 # 永久去重(BloomFilter) = 1 、内存去重(MemoryFilter) = 2、 临时去重(ExpireFilter)= 3、轻量去重(LiteFilter)= 4
# )
# REQUEST_FILTER_SETTING = dict(
# filter_type=3, # 永久去重(BloomFilter) = 1 、内存去重(MemoryFilter) = 2、 临时去重(ExpireFilter)= 3、 轻量去重(LiteFilter)= 4
# expire_time=2592000, # 过期时间1个月
# )
#
# # 报警 支持钉钉、飞书、企业微信、邮件
# # 钉钉报警
# DINGDING_WARNING_URL = "" # 钉钉机器人api
# DINGDING_WARNING_PHONE = "" # 报警人 支持列表,可指定多个
# DINGDING_WARNING_ALL = False # 是否提示所有人, 默认为False
# # 飞书报警
# # https://open.feishu.cn/document/ukTMukTMukTM/ucTM5YjL3ETO24yNxkjN#e1cdee9f
# FEISHU_WARNING_URL = "" # 飞书机器人api
# FEISHU_WARNING_USER = None # 报警人 {"open_id":"ou_xxxxx", "name":"xxxx"} 或 [{"open_id":"ou_xxxxx", "name":"xxxx"}]
# FEISHU_WARNING_ALL = False # 是否提示所有人, 默认为False
# # 邮件报警
# EMAIL_SENDER = "" # 发件人
# EMAIL_PASSWORD = "" # 授权码
# EMAIL_RECEIVER = "" # 收件人 支持列表,可指定多个
# EMAIL_SMTPSERVER = "smtp.163.com" # 邮件服务器 默认为163邮箱
# # 企业微信报警
# WECHAT_WARNING_URL = "" # 企业微信机器人api
# WECHAT_WARNING_PHONE = "" # 报警人 将会在群内@此人, 支持列表,可指定多人
# WECHAT_WARNING_ALL = False # 是否提示所有人, 默认为False
# # 时间间隔
# WARNING_INTERVAL = 3600 # 相同报警的报警时间间隔,防止刷屏; 0表示不去重
# WARNING_LEVEL = "DEBUG" # 报警级别, DEBUG / INFO / ERROR
# WARNING_FAILED_COUNT = 1000 # 任务失败数 超过WARNING_FAILED_COUNT则报警
#
# LOG_NAME = os.path.basename(os.getcwd())
# LOG_PATH = "log/%s.log" % LOG_NAME # log存储路径
# LOG_LEVEL = "DEBUG"
# LOG_COLOR = True # 是否带有颜色
# LOG_IS_WRITE_TO_CONSOLE = True # 是否打印到控制台
# LOG_IS_WRITE_TO_FILE = False # 是否写文件
# LOG_MODE = "w" # 写文件的模式
# LOG_MAX_BYTES = 10 * 1024 * 1024 # 每个日志文件的最大字节数
# LOG_BACKUP_COUNT = 20 # 日志文件保留数量
# LOG_ENCODING = "utf8" # 日志文件编码
# OTHERS_LOG_LEVAL = "ERROR" # 第三方库的log等级
#
# # 切换工作路径为当前项目路径
# project_path = os.path.abspath(os.path.dirname(__file__))
# os.chdir(project_path) # 切换工作路经
# sys.path.insert(0, project_path)
# print("当前工作路径为 " + os.getcwd())
url: 待抓取url
retry_times: 当前重试次数
priority: 优先级 越小越优先 默认300
parser_name: 回调函数所在的类名 默认为当前类
callback: 回调函数 可以是函数 也可是函数名(如想跨类回调时,parser_name指定那个类名,callback指定那个类想回调的方法名即可)
filter_repeat: 是否需要去重 (True/False) 当setting中的REQUEST_FILTER_ENABLE设置为True时该参数生效 默认True
auto_request: 是否需要自动请求下载网页 默认是。设置为False时返回的response为空,需要自己去请求网页
request_sync: 是否同步请求下载网页,默认异步。如果该请求url过期时间快,可设置为True,相当于yield的reqeust会立即响应,而不是去排队
use_session: 是否使用session方式
random_user_agent: 是否随机User-Agent (True/False) 当setting中的RANDOM_HEADERS设置为True时该参数生效 默认True
download_midware: 下载中间件。默认为parser中的download_midware
is_abandoned: 当发生异常时是否放弃重试 True/False. 默认False
render: 是否用浏览器渲染
render_time: 渲染时长,即打开网页等待指定时间后再获取源码
make_absolute_links: 是否转成绝对连接,默认是
**kwargs: 其他值: 如 Request(item=item) 则item可直接用 request.item 取出
method:请求方式,可以是 POST 或 GET。
params:请求参数,通常是一个字典,包含了发送到服务器的额外参数。
data:请求的主体内容,通常用于 POST 请求。
json:请求的主体内容,以 JSON 字符串形式传递。
headers:请求头,包含了一些额外的信息,如 User-Agent、Content-Type 等。
cookies:用于发送请求的 cookies,可以是一个字典或者 CookieJar 对象。
files:上传文件时使用的参数。
auth:用于 HTTP 基本认证。
timeout:等待服务器响应的超时时间,可以是一个浮点数,也可以是一个元组,表示连接超时和读取超时。
allow_redirects:是否允许跟踪 POST/PUT/DELETE 方法的重定向。
proxies:代理设置,以字典形式传递,如 {"http": "http://xxx", "https": "https://xxx"}。
verify:是否验证 SSL 证书。
stream:如果为 False,将会立即下载响应内容。
cert:SSL 证书的路径。
response:代表接收到的 HTTP 响应。
make_absolute_links:一个布尔值,用于指定是否将相对链接转换为绝对链接。
'''
ItemMetaclass:使Item继承一些默认属性
__name__:类的名称,默认为 None。
__table_name__:类对应的表的名称,默认为 None。
__name_underline__:类名的下划线版本,默认为 None。
__update_key__:用于更新记录的关键字,默认为 None。
__unique_key__:用于唯一标识记录的关键字,默认为 None。
'''
class ItemMetaclass(type):
def __new__(cls, name, bases, attrs):
attrs.setdefault("__name__", None)
attrs.setdefault("__table_name__", None)
attrs.setdefault("__name_underline__", None)
attrs.setdefault("__update_key__", None)
attrs.setdefault("__unique_key__", None)
return type.__new__(cls, name, bases, attrs)
ua_type: ua类型
chrome
opera
firefox
internetexplorer
safari
mobile
proxy_api 是一个用于获取代理IP的API接口,如果不提供的话,可能会使用默认的代理获取方式。
**kwargs 则是用于传递其他可能需要的参数。
redis_key: user存放在redis中的key前缀
page_url: 生产user的url
min_users: 最小user数
must_contained_keys: cookie中必须包含的key,用于校验cookie是否正确
keep_alive: 是否保持常驻,以便user不足时立即补充
kwargs: WebDriver的一些参数
load_images: 是否加载图片
user_agent: 字符串 或 无参函数,返回值为user_agent
proxy: xxx.xxx.xxx.xxx:xxxx 或 无参函数,返回值为代理地址
headless: 是否启用无头模式
driver_type: CHROME,EDGE 或 PHANTOMJS,FIREFOX
timeout: 请求超时时间
window_size: # 窗口大小
executable_path: 浏览器路径,默认为默认路径
user_agent:用户代理字符串,用于模拟浏览器发送请求。
proxies:代理信息,可以是一个代理字典,例如 {"http": "http://proxy.example.com:8080", "https": "https://proxy.example.com:8080"}。
cookies:Cookie 信息,可以是一个 Cookie 字符串,例如 "cookie1=value1; cookie2=value2"
**kwargs:自定义属性
redis_key: 项目名
table_userbase: 用户表名
login_state_key: 登录状态列名
lock_state_key: 封锁状态列名
username_key: 登陆名列名
password_key: 密码列名
login_retry_times: 登陆失败重试次数
keep_alive: 是否保持常驻,以便user不足时立即补充
redis_key: user存放在redis中的key前缀
users: 账号信息
keep_alive: 是否保持常驻,以便user不足时立即补充
max_use_times:@param use_interval: 使用时间间隔。 支持元组 指定间隔的时间范围 如(5,10)即5到10秒;或直接传整数
work_time: 工作时间,默认 7点到23点
login_interval: 登录时间间隔 防止频繁登录 导致账号被封
exclusive_time: 独占时长
ip:MongoDB 服务器的 IP 地址。
port:MongoDB 服务器的端口号。
db:要连接的数据库名称。
user_name:数据库用户的用户名。
user_pass:数据库用户的密码。
urle:数据库的连接 URL。
**kwargs:其他参数。
1.from feapder.utils.log import get_logger:获取log
name: log名
path: log文件存储路径 如 D://xxx.log@param log_level: log等级 CRITICAL/ERROR/WARNING/INFO/DEBUG@param is_write_to_console: 是否输出到控制台
is_write_to_file: 是否写入到文件 默认否
color:是否有颜色
mode:写文件模式
max_bytes: 每个日志文件的最大字节数
backup_count:日志文件保留数量
encoding:日志文件编码
查看运行命令 python main.py --help
prog -- 程序的名称(默认为:os.path.basename(sys.argv[0]))
usage -- 使用说明消息(默认从参数自动生成)
description -- 程序功能的描述
epilog -- 在参数描述之后的文本
parents -- 将其参数复制到此程序中的解析器
formatter_class -- 用于打印帮助信息的 HelpFormatter 类
prefix_chars -- 可选参数前缀字符
fromfile_prefix_chars -- 前缀文件的字符,包含额外的参数
argument_default -- 所有参数的默认值
conflict_handler -- 表示如何处理冲突的字符串
add_help -- 添加一个 -h/-help 选项
allow_abbrev -- 允许对长选项进行无歧义的缩写
exit_on_error -- 确定当发生错误时 ArgumentParser 是否退出并显示错误信息
name or flags: 参数的名称或者选项(可以是一个字符串或一个字符串列表),例如 '--input' 或 '-i'。
action: 参数的动作。通常可以是 store(默认)、store_const、store_true、store_false、append、append_const、count 等。
choices: 允许的参数值的列表。
const: 用于 store_const 和 append_const 动作的常量值。
default: 参数的默认值,如果用户没有提供此参数。
dest: 参数被解析后的存储属性的名称。
help: 参数的帮助信息。
metavar:参数的备用显示名称,如帮助中所示
nargs: 参数的个数,可以是一个具体的数字,也可以是 '+' 表示一个或多个,'*' 表示零个或多个。
required: 是否要求必须提供此参数。
type: 参数的类型,例如 int、float、str 等。
可打印:parser.functions 查看有哪些args
args:通过add_argument添加的命令行参数
values:通过add_argument添加的命令行中function的参数
influxdb_host: InfluxDB 主机的地址。
influxdb_port: InfluxDB 使用的端口。
influxdb_udp_port: InfluxDB 使用的 UDP 端口。
influxdb_database: InfluxDB 数据库的名称。
influxdb_user: InfluxDB 连接所使用的用户名。
influxdb_password: InfluxDB 连接所使用的密码
influxdb_measurement: 存储的表,也可以在打点的时候指定
retention_policy: 保留策略
retention_policy_duration: 保留策略过期时间
emit_interval: 打点最大间隔
batch_size: 打点的批次大小
debug: 是否开启调试
use_udp: 是否使用udp协议打点
timeout: 与influxdb建立连接时的超时时间
ssl: 是否使用https协议
retention_policy_replication: 保留策略的副本数, 确保数据的可靠性和高可用性。如果一个节点发生故障,其他节点可以继续提供服务,从而避免数据丢失和服务不可用的情况
set_retention_policy_default: 是否设置为默认的保留策略,当retention_policy初次创建时有效
**kwargs: 可传递MetricsEmitter类的参数
tags: influxdb的tag的字段和值
fields: influxdb的field的字段和值
classify: 点的类别
measurement: 存储的表
timestamp: 点的时间搓,默认为当前时间
key: 与点绑定的key值
count: 点数
classify: 点的类别
tags: influxdb的tag的字段和值
measurement: 存储的表
timestamp: 点的时间搓,默认为当前时间
key: 与点绑定的key值
duration: 时长
classify: 点的类别
tags: influxdb的tag的字段和值
measurement: 存储的表
timestamp: 点的时间搓,默认为当前时间
key: 与点绑定的key值
value: 点的值
classify: 点的类别
tags: influxdb的tag的字段和值
measurement: 存储的表
timestamp: 点的时间搓,默认为当前时间
influxdb: influxdb instance
batch_size: 打点的批次大小
max_timer_seq: 每个时间间隔内最多收集多少个 timer 类型点, 0 表示不限制
emit_interval: 最多等待多长时间必须打点
retention_policy: 对应的 retention policy
ratio: store 和 timer 类型采样率,比如 0.1 表示只有 10% 的点会留下
debug: 是否打印调试日志
add_hostname: 是否添加 hostname 作为 tag
max_points: 本地 buffer 最多累计多少个点
measurement: 存储的表
fields:一个字典,包含了度量的字段和其对应的值。字段通常包含了实际的测量值
tags: influxdb的tag的字段和值
timestamp: 点的时间搓,默认为当前时间
measurement: 存储的表
key: 与点绑定的key值
duration: 时长
tags: influxdb的tag的字段和值
timestamp: 点的时间搓,默认为当前时间
measurement: 存储的表
key: 与点绑定的key值
value: 点的值
tags: influxdb的tag的字段和值
timestamp: 点的时间搓,默认为当前时间
measurement: 存储的表
key: 与点绑定的key值
count: 点数
tags: influxdb的tag的字段和值
timestamp: 点的时间搓,默认为当前时间
xhr_url_regexes:用于配置 WebDriver 的一些正则表达式,以匹配 XMLHttpRequest(XHR)请求的URL。这样可以在需要的情况下进行特定URL的处理或过滤。
**kwargs:用于传递额外的配置项给 WebDriver 对象
import requests
class Kuaidaili():
request_url = {
# 获取代理ip前面
'getIpSignature': 'https://auth.kdlapi.com/api/get_secret_token',
# 获取代理ip
'getIp': 'https://dps.kdlapi.com/api/getdps?secret_id=oy2q5xu76k4s8olx59et&num=1&signature={}'
}
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36'
}
ip_use = '购买代理的用户名'
ip_password = '购买代理的密码'
def __init__(self):
'''创建request会话对象'''
self.request_session = requests.Session()
self.request_session.headers.update(self.headers)
# 获取代理ip签名
@classmethod
def get_ip_url(cls):
par = {
'secret_id': 'oy2q5xu76k4s8olx59et',
'secret_key': '5xg6gvouc0vszfw0kxs1a8vrw1r6ity7'
}
response = requests.post(cls.request_url['getIpSignature'],data=par)
response_data = response.json()
return cls.request_url['getIp'].format(response_data['data']['secret_token'])
@classmethod
def get_all_ip(cls):
url = cls.get_ip_url()
response = requests.get(url)
return f'http://{cls.ip_use}:{cls.ip_password}@{response.text}'
@classmethod
def get_ip(cls):
url = cls.get_ip_url()
response = requests.get(url)
return f'{cls.ip_use}:{cls.ip_password}@{response.text}'
if __name__ == '__main__':
kuaidaili = Kuaidaili()
import feapder
from proxy.kuaidaili import Kuaidaili
class AirSpiderDouban(feapder.AirSpider):
def __init__(self, thread_count=None):
super().__init__(thread_count)
self.request_url = 'https://movie.douban.com/top250'
# ip代理
self.kuaidaili = Kuaidaili()
proxy_ip = self.kuaidaili.get_all_ip()
self.proxies = {
'http': proxy_ip,
'https': proxy_ip
}
print(f'当前代理{self.proxies}')
def start_requests(self):
yield feapder.Request("https://www.baidu.com")
def download_midware(self, request):
# 这里使用代理使用即可
request.proxies = self.proxies
return request
def parse(self, request, response):
print(response)
def exception_request(self, request, response, e):
prox_err = [ConnectTimeout,ProxyError]
if type(e) in prox_err:
request.del_proxy()
PROXY_EXTRACT_API = None # 代理提取API ,返回的代理分割符为\r\n
PROXY_ENABLE = True
PROXY_MAX_FAILED_TIMES = 5 # 代理最大失败次数,超过则不使用,自动删除
from feapder.network.proxy_pool import BaseProxyPool
from proxy import kuaidaili
from queue import Queue
import feapder.utils.tools as tools
from feapder.utils import metrics
class MyProxyPool(BaseProxyPool):
def __init__(self):
self.kuaidaili = kuaidaili.Kuaidaili()
self.proxy_queue = Queue()
def format_proxy(self, proxy):
return {"http": proxy, "https": proxy}
def get_proxy(self):
try:
if self.proxy_queue.empty():
proxy_ip = self.kuaidaili.get_ip()
self.proxy_queue.put_nowait(proxy_ip)
proxy = self.proxy_queue.get_nowait()
self.proxy_queue.put_nowait(proxy)
metrics.emit_counter("used_times", 1, classify="proxy")
return self.format_proxy(proxy)
except Exception as e:
tools.send_msg("获取代理失败", level="error")
raise Exception("获取代理失败", e)
def del_proxy(self, proxy):
"""
@summary: 删除代理
---------
@param proxy: ip:port
"""
if proxy in self.proxy_queue.queue:
self.proxy_queue.queue.remove(proxy)
metrics.emit_counter("invalid", 1, classify="proxy")
self.get_proxy()
PROXY_EXTRACT_API = True # 代理提取API ,返回的代理分割符为\r\n
PROXY_ENABLE = True
PROXY_MAX_FAILED_TIMES = 5 # 代理最大失败次数,超过则不使用,自动删除
PROXY_POOL = "proxy.proxypool.MyProxyPool" # 代理池
import feapder
class AirSpiderDouban(feapder.AirSpider):
def start_requests(self):
yield feapder.Request("https://www.baidu.com")
def parse(self, request, response):
print(response)
def exception_request(self, request, response):
prox_err = [ConnectTimeout,ProxyError]
if type(e) in prox_err:
request.del_proxy()
# # REDIS
# # ip:port 多个可写为列表或者逗号隔开 如 ip1:port1,ip2:port2 或 ["ip1:port1", "ip2:port2"]
REDISDB_IP_PORTS = "localhost:6379"
REDISDB_USER_PASS = ""
REDISDB_DB = 0
# 连接redis时携带的其他参数,如ssl=True
REDISDB_KWARGS = dict()
# 适用于redis哨兵模式
REDISDB_SERVICE_NAME = ""
# # 去重
ITEM_FILTER_ENABLE = True # item 去重
# REQUEST_FILTER_ENABLE = False # request 去重
ITEM_FILTER_SETTING = dict(
filter_type=1, # 永久去重(BloomFilter) = 1 、内存去重(MemoryFilter) = 2、 临时去重(ExpireFilter)= 3、轻量去重(LiteFilter)= 4
name="douban"
)
# REQUEST_FILTER_SETTING = dict(
# filter_type=3, # 永久去重(BloomFilter) = 1 、内存去重(MemoryFilter) = 2、 临时去重(ExpireFilter)= 3、 轻量去重(LiteFilter)= 4
# expire_time=2592000, # 过期时间1个月
# )
from feapder import Item
class DoubanItem(Item):
"""
This class was generated by feapder
command: feapder create -i douban
"""
__table_name__ = "douban"
__unique_key__ = ["title","quote","rating","title"] # 指定去重的key为 title、quote,最后的指纹为title与quote值联合计算的md5
def __init__(self, *args, **kwargs):
super().__init__(**kwargs)
# self.id = None
self.intro = None
self.quote = None
self.rating = None
self.title = None


EMAIL_SENDER = "123123123@163.com" # 发件人
EMAIL_PASSWORD = "EYNXMBWJKMLZFTKQ" # 授权码
EMAIL_RECEIVER = ["123123123@163.com"] # 收件人 支持列表,可指定多个
EMAIL_SMTPSERVER = "smtp.163.com" # 邮件服务器 默认为163邮箱
import feapder
from feapder.network.user_agent import get as get_ua
from requests.exceptions import ConnectTimeout,ProxyError
from feapder.utils.email_sender import EmailSender
import feapder.setting as setting
class AirSpiderDouban(feapder.AirSpider):
def __init__(self, thread_count=None):
super().__init__(thread_count)
self.request_url = 'https://www.baidu.com'
def start_requests(self):
yield feapder.Request(self.request_url)
def parse(self, request, response):
pass
def end_callback(self):
with EmailSender(setting.EMAIL_SENDER,setting.EMAIL_PASSWORD) as email_sender:
email_sender.send(setting.EMAIL_RECEIVER, title='python',content="爬虫结束")
if __name__ == "__main__":
AirSpiderDouban(thread_count=5).start()
from feapder.pipelines import BasePipeline
class MysqlPipeline(BasePipeline):
def save_items(self, table, items):
print("自定义pipeline, 保存数据 >>>>", table, items)
return True
def update_items(self, table, items, update_keys):
print("自定义pipeline, 更新数据 >>>>", table, items, update_keys)
return True
ITEM_PIPELINES = [
"pipeline.mysql_pipeline.MysqlPipeline",
]
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。