爬虫【feapder框架】

news2025/4/16 17:26:10

feapder框架

1、简单介绍

简介

  1. feapder上手简单、功能强大的Python爬虫框架,内置AirSpiderSpiderTask、SpiderBatchSpider四种爬虫解决不同场景的需求
  2. 支持断点续爬、监控报警、浏览器渲染、海量数据去重等功能
  3. 更有功能强大的爬虫管理系统feaplat为其提供方便的部署及调度

文档地址与环境配置

官方文档:简介及安装 - feapder官方文档|feapder-document

# 在安装之前建议使用miniconda3创建一个新的虚拟环境
conda create -n feapder_base python=3.9
conda activate feapder_base

执行流程

核心:spider
spider调度
-> start_request(打包request对象) 提交给 
-> request_buffer(请求缓冲区)将request对象提交给
-> 任务队列 
-> collector(控制器) 
-> parser_control(模版解析控制器) 
-> 下载器(封装成response)
-> parser_control(模版解析控制器) 区分对象类型
-> (response) 给 parser(多个解析器) 提取页面数据
-> 清洗完毕
-> parser_control(模版解析控制器)
-> 解析完成
-> item_buffer(数据缓冲区)
-> 数据入库(db)

2、feapder简单使用

命令

# 帮助文档
feapder create -h
常用
-p 创建项目
-s 创建爬虫
-i 创建item 字段校验

创建项目

feapder create -s douban

执行命令后需要手动选择对应的爬虫模版

  • AirSpider轻量爬虫:学习成本低、可快速上手
  • Spider分布式爬虫:支持断点续爬、爬虫报警、数据自动入库等功能
  • TaskSpider分布式爬虫:内部封装了取种子任务的逻辑,内置支持从redis或者mysql获取任务,也可通过自定义实现从其他来源获取任务
  • BatchSpider批次爬虫:可周期性的采集数据,自动将数据按照指定的采集周期划分。(如每7天全量更新一次商品销量的需求)

使用AirSpider

# -*- coding: utf-8 -*-
"""
Created on 2025-02-16 10:10:31
---------
@summary:
---------
@author: hp
"""

import feapder
from feapder import Request


class Douban(feapder.AirSpider):
    def start_requests(self):
        for page in range(10):
            yield feapder.Request(f'https://movie.douban.com/top250?start={page * 25}&filter=')
        # yield feapder.Request("https://movie.douban.com/top250?start=25&filter=")

    # def download_midware(self, request: Request):
    #     if request.url.startswith("https://movie.douban.com/top250"):
    #         request.proxies = {"http": "http://127.0.0.1:7897", "https": "https://127.0.0.1:7897"}
    #     return request

    def parse(self, request, response):
        li_list = response.xpath("//ol/li/div[@class='item']")
        for li in li_list:
            item = dict()
            item['title'] = li.xpath(".//div[@class='hd']/a/span[1]/text()").extract_first()
            item['detail_url'] = li.xpath(".//div[@class='hd']/a/@href").extract_first()
            item['score'] = li.xpath(".//div[@class='star']/span[2]/text()").extract_first()
            yield feapder.Request(item['detail_url'], callback=self.detail_parse, item=item )
    def detail_parse(self, request, response):
        if response.xpath("//div[@class='indent']/span[@class='all hidden']/text()"):
            request.item['detail_text'] = response.xpath("//div[@class='indent']/span[@class='all hidden']/text()").extract_first().strip()
        else:
            request.item['detail_text'] = response.xpath("//div[@class='indent']/span[1]/text()").extract_first().strip()
        print(request.item)

if __name__ == "__main__":
    Douban().start()

数据存入MySQL

feapder create --setting
feapder create -i douban_feapder # 这里的这个item名字要与创建的 表名 一致
# -*- coding: utf-8 -*-
"""
Created on 2025-02-16 10:10:31
---------
@summary:
---------
@author: hp
"""

import feapder
from feapder import Request
from douban_feapder_item import DoubanFeapderItem

class Douban(feapder.AirSpider):
    def start_requests(self):
        for page in range(10):
            yield feapder.Request(f'https://movie.douban.com/top250?start={page * 25}&filter=')
        # yield feapder.Request("https://movie.douban.com/top250?start=25&filter=")
    def parse(self, request, response):
        li_list = response.xpath("//ol/li/div[@class='item']")
        for li in li_list:
            item = DoubanFeapderItem()
            item['title'] = li.xpath(".//div[@class='hd']/a/span[1]/text()").extract_first()
            item['detail_url'] = li.xpath(".//div[@class='hd']/a/@href").extract_first()
            item['score'] = li.xpath(".//div[@class='star']/span[2]/text()").extract_first()
            yield feapder.Request(item['detail_url'], callback=self.detail_parse, item=item )
    def detail_parse(self, request, response):
        if response.xpath("//div[@class='indent']/span[@class='all hidden']/text()"):
            request.item['detail_text'] = response.xpath("//div[@class='indent']/span[@class='all hidden']/text()").extract_first().strip()
        else:
            request.item['detail_text'] = response.xpath("//div[@class='indent']/span[1]/text()").extract_first().strip()
        # 进行数据入库
        yield request.item

if __name__ == "__main__":
    Douban().start()

3、下载中间件使用

  • 下载中间件用于在请求之前,对请求做一些处理,如添加cookieheader
  • 默认所有的解析函数在请求之前都会经过此下载中间件
    # 默认中间件
    # def download_midware(self, request: Request):
    #     request.headers = {
    #         "User-Agent" : "abc",
    #     }
    #     request.proxies = {
    #         'http' : 'http://127.0.0.1:7897'
    #     }
    #     request.cookies = {
    #         'a' : 'b',
    #     }
    #     return request

    # 自定义中间件 需要写参数 download_midware 该参数可接收列表
    def custom_download_midware(self, request: Request):
        request.headers = {
            "User-Agent" : "abc",
        }
        return request
    def start_requests(self):
    	# request对象支持载入多个自定义中间件,将dwonload_midware的参数设置为一个列表形式即可
        # 但是一般不使用,在一个中间件中配置好所有的参数即可
        yield feapder.Request("https://movie.douban.com/top250?start=0&filter=", download_midware=self.custom_download_midware)

4、校验响应对象

    def validate(self, request, response):
        print('响应状态码:', response.status_code)
        if response.status_code != 200:
            print('响应状态码异常:', response.status_code)
            # return False # 抛弃当前请求
            raise Exception('请求重试') # 重试当前请求

5、浏览器渲染

import feapder
from selenium.webdriver.common.by import By
from feapder.utils.webdriver import WebDriver

class Baidu(feapder.AirSpider):
    def start_requests(self):
        yield feapder.Request("https://www.baidu.com", render=True)

    def parse(self, request, response):
        browser: WebDriver = response.browser
        browser.find_element(By.ID, "kw").send_keys("feapder")
        browser.find_element(By.ID, "su").click()
if __name__ == "__main__":
    Baidu().start()
setting.py中的 浏览器渲染部分 打开

6、使用浏览器渲染动态获取接口

import feapder
from feapder.utils.webdriver import WebDriver

class TestXhrInfo(feapder.AirSpider):
    def start_requests(self):
        yield feapder.Request("https://spidertools.cn", render=True)

    def parse(self, request, response):
        browser : WebDriver = response.browser
        # ad = browser.xhr_text('/ad')
        # print(ad)
        xhr_response = browser.xhr_response("/ad")
        print("请求接口", xhr_response.request.url)
        print("请求头", xhr_response.request.headers)
        print("请求体", xhr_response.request.data)
        print("返回头", xhr_response.headers)
        print("返回地址", xhr_response.url)
        print("返回内容", xhr_response.content)

if __name__ == "__main__":
    TestXhrInfo().start()
setting.py中的浏览器渲染部分打开:
	xhr_url_regexes=['/ad'],  # 拦截xhr接口,支持正则,数组类型

7、使用feapder抓取应届生岗位数据

# -*- coding: utf-8 -*-
"""
Created on 2025-02-16 14:40:06
---------
@summary:
---------
@author: hp
"""
import time
import feapder
from feapder.utils.webdriver import WebDriver

class JobInfo(feapder.AirSpider):
    def start_requests(self):
        yield feapder.Request("https://q.yingjiesheng.com/jobs/search/Python", render=True)

    def parse(self, request, response):
        browser: WebDriver = response.browser
        time.sleep(3)
        json_data = browser.xhr_json('open/noauth/job/search')
        for temp in json_data['resultbody']['searchData']['joblist']['items']:
            item = dict()
            item['jobname'] = temp['jobname']
            item['coname'] = temp['coname']
            item['jobarea'] = temp['jobarea']
            item['issuedate'] = temp['issuedate']
            item['jobtag'] = temp['jobtag']
            item['providesalary'] = temp['providesalary']
            print(item)



if __name__ == "__main__":
    JobInfo().start()
# setting.py
# 浏览器渲染
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=['open/noauth/job/search'],  # 拦截xhr接口,支持正则,数组类型
    auto_install_driver=False,  # 自动下载浏览器驱动 支持chrome 和 firefox
    download_path=None,  # 下载文件的路径
    use_stealth_js=False,  # 使用stealth.min.js隐藏浏览器特征

8、feapder创建完整项目

命令

feapder craete -p wp_spider
# -*- coding: utf-8 -*-
"""
Created on 2025-02-16 15:15:35
---------
@summary:
---------
@author: hp
"""
from random import randint

import feapder
from feapder.utils.webdriver import WebDriver
from selenium.webdriver.common.by import By
import time

class WpShopInfo(feapder.AirSpider):
    def start_requests(self):
        yield feapder.Request("https://category.vip.com/suggest.php?keyword=%E7%94%B5%E8%84%91&ff=235|12|1|1&tfs_url=%2F%2Fmapi-pc.vip.com%2Fvips-mobile%2Frest%2Fshopping%2Fpc%2Fsearch%2Fproduct%2Frank", render=True)

    def parse(self, request, response):
        browser: WebDriver = response.browser
        time.sleep(20) # 为了正常测试,手动登录
        # 页面下划加载动态数据
        self.drop_down(browser)
        # 获取页面中所有商品div
        div_list = browser.find_elements(By.XPATH, '//section[@id="J_searchCatList"]/div[@class="c-goods-item  J-goods-item c-goods-item--auto-width"]')
        # print(div_list)
        # 对返回的div_list进行迭代并获取每个商品的信息
        for div in div_list:
            title = div.find_element(By.XPATH, './/div[2]/div[2]').text
            price = div.find_element(By.XPATH, './/div[@class="c-goods-item__sale-price J-goods-item__sale-price"]').text
            print(title, price)

        # 翻页
        self.next_page(browser)
        next_url = browser.current_url # 获取翻页后的网页地址
        print(next_url)
        yield feapder.Request(next_url, render=True, callback=self.parse)

    def drop_down(self, browser):
        for i in range(1, 13):
            js_code = f'document.documentElement.scrollTop={i*1000}'
            browser.execute_script(js_code)
            time.sleep(randint(1, 2))
    def next_page(self, browser):
        # 获取下一页按钮
        try:
            next_page = browser.find_element(By.XPATH, "//a[@class='cat-paging-next']/i")
            if next_page:
                next_page.click()
            else:
                browser.close()
        except Exception as e:
            print('最后一页: ', e)
            browser.close()

if __name__ == "__main__":
    WpShopInfo().start()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2327597.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

LLaMA Factory微调后的大模型在vLLM框架中对齐对话模版

LLaMA Factory微调后的大模型Chat对话效果,与该模型使用vLLM推理架构中的对话效果,可能会出现不一致的情况。 下图是LLaMA Factory中的Chat的对话 下图是vLLM中的对话效果。 模型回答不稳定:有一半是对的,有一半是无关的。 1、未…

群体智能优化算法-鹈鹕优化算法(Pelican Optimization Algorithm, POA,含Matlab源代码)

摘要 鹈鹕优化算法(Pelican Optimization Algorithm, POA)是一种灵感来自自然界鹈鹕觅食行为的元启发式优化算法。POA 模拟鹈鹕捕食的两个主要阶段:探索阶段和开发阶段。通过模拟鹈鹕追捕猎物的动态行为,该算法在全局探索和局部开…

在 Blazor 中使用 Chart.js 快速创建数据可视化图表

前言 BlazorChartjs 是一个在 Blazor 中使用 Chart.js 的库(支持Blazor WebAssembly和Blazor Server两种模式),它提供了简单易用的组件来帮助开发者快速集成数据可视化图表到他们的 Blazor 应用程序中。本文我们将一起来学习一下在 Blazor 中…

SQL server 2022和SSMS的使用案例1

一,案例讲解 二,实战讲解 实战环境 你需要确保你已经安装完成SQL Server 2022 和SSMS 20.2 管理面板。点此跳转至安装教程 SQL Server2022Windows11 专业工作站SSMS20.2 1,连接数据库 打开SSMS,连接数据库。 正常连接示意图&…

GO语言学习(14)GO并发编程

目录 🌈前言 1.goroutine🌟 2.GMP模型🌟 2.1 GMP的由来☀️ 2.2 什么是GMP☀️ 3.channel 🌟 3.1 通道声明与数据传输💥 3.2 通道关闭 💥 3.3 通道遍历 💥 3.4 Select语句 &#x1f4…

【Audio开发二】Android原生音量曲线调整说明

一,客制化需求 客户方对于音量加减键从静音到最大音量十五个档位区域的音量变化趋势有定制化需求。 二,音量曲线调试流程 Android根据不同的音频流类型定义不同的曲线,曲线文件存放在/vendor/etc/audio_policy_volumes.xml或者default_volu…

spring-security原理与应用系列:HttpSecurity.filters

目录 AnyRequestMatcher WebSecurityConfig HttpSecurity AbstractInterceptUrlConfigurer AbstractAuthenticationProcessingFilter 类图 在前面的文章《spring-security原理与应用系列:securityFilterChainBuilders》中,我们遗留了一个问题&…

JVM生产环境问题定位与解决实战(六):总结篇——问题定位思路与工具选择策略

本文已收录于《JVM生产环境问题定位与解决实战》专栏,完整系列见文末目录 引言 在前五篇文章中,我们深入探讨了JVM生产环境问题定位与解决的实战技巧,从基础的jps、jmap、jstat、jstack、jcmd等工具,到JConsole、VisualVM、MAT的…

并行治理机制对比:Polkadot、Ethereum 与 NEAR

治理是任何去中心化网络的基础。它塑造了社区如何发展、如何为创新提供资金、如何应对挑战以及如何随着时间的推移建立信任。随着 Web3 的不断发展,决定这些生态系统如何做出决策的治理模型也在不断发展。 在最近的一集的【The Decentralized Mic】中, Polkadot 汇…

TDengine tar.gz和docker两种方式安装和卸载

下载地址 3.1.1.0 Linux版本 安装包 下载地址 3.1.1.0 docker 镜像 下载地址 3.1.1.0 Window客户端 1. 将文件上传至服务器后解压 tar -zxvf TDengine-server-3.1.1.0-Linux-x64.tar.gz 2. tar.gz安装 解压文件后,进入相应子目录,执行其中的 install.…

【STM32设计】基于STM32的智能门禁管理系统(指纹+密码+刷卡+蜂鸣器报警)(代码+资料+论文)

本课题为基于单片机的智能门禁系统,整个系统由AS608指纹识别模块,矩阵键盘,STM32F103单片机,OLED液晶,RFID识别模块,继电器,蜂鸣器等构成,在使用时,用户可以录入新的指纹…

java知识梳理(二)

一.lambda表达式 作用:Lambda 表达式在 Java 8 引入,主要用于简化匿名内部类的写法,特别是在函数式编程场景中,比如 函数式接口、流式 API(Streams)、并发编程等。它让 Java 代码更简洁、可读性更强&#x…

鸿蒙Flutter实战:20. Flutter集成高德地图,同层渲染

本文以同层渲染为例,介绍如何集成高德地图 完整代码见 Flutter 鸿蒙版 Demo 概述 Dart 侧 核心代码如下,通过 OhosView 来承载原生视图 OhosView(viewType: com.shaohushuo.app/customView,onPlatformViewCreated: _onPlatformViewCreated,creation…

AI辅助下基于ArcGIS Pro的SWAT模型全流程高效建模实践与深度进阶应用

目前,流域水资源和水生态问题逐渐成为制约社会经济和环境可持续发展的重要因素。SWAT模型是一种基于物理机制的分布式流域水文与生态模拟模型,能够对流域的水循环过程、污染物迁移等过程进行精细模拟和量化分析。SWAT模型目前广泛应用于流域水文过程研究…

尚语翻译图册翻译|专业图册翻译|北京专业翻译公司推荐|专业文件翻译报价

内容概要 尚语翻译公司聚焦多语种产品图册翻译的竞价推广服务,通过行业垂直化运营构建差异化竞争力。其核心服务覆盖机械制造、医疗器械、电子元件三大领域,依托ISO 17100认证的翻译流程和Trados术语管理系统,实现技术文档的精准转化。为提升…

LeetCode 解题思路 30(Hot 100)

解题思路: 递归参数: 生成括号的对数 n、结果集 result、当前路径 path、左括号数 open、右括号数 close。递归过程: 当当前路径 path 的长度等于 n * 2 时,说明已经生成有效括号,加入结果集。若左括号数小于 n&…

Java EE(18)——网络原理——应用层HTTP协议

一.初识HTTP协议 HTTP(HyperText Transfer Protocol,超文本传输协议)是用于在客户端(如浏览器)和服务器之间传输超媒体文档(如HTML)的应用层协议。 HTTP协议发展至今发布了多个版本,其中1.0,1.…

强大而易用的JSON在线处理工具

强大而易用的JSON在线处理工具:程序员的得力助手 在当今的软件开发世界中,JSON(JavaScript Object Notation)已经成为了数据交换的通用语言。无论是前端还是后端开发,我们都经常需要处理、验证和转换JSON数据。今天&a…

Qt笔记----》不同环境程序打包

文章目录 概要1、windows环境下打包qt程序2、linux环境下打包qt程序2.1、程序目录2.2、创建一个空文件夹2.3、添加依赖脚本2.4、打包过程2.4.1、添加程序依赖库2.4.2、添加Qt相关依赖库 概要 qt不同运行环境下打包方式:windows/linux 1、windows环境下打包qt程序 …

企业服务器备份软件,企业服务器备份的方法有哪些?

企业服务器备份需综合考虑数据量、业务连续性要求(RTO/RPO)、合规性及成本等因素。以下是分场景的工具和方法指南: 一、备份软件推荐 1. 80KM备份软件 80KM备份软件可以进行很复杂的备份方式,也可以内网对内网备份、还能内网的…