分享一下自己的RSS使用思路

不知道现在还有没有人在折腾 RSS,最近重新搞了一波 RSS,以下是是自用的思路,各位佬友有更好的思路欢迎交流一下:) 我主要使用 FreshRSS 作为 RSS 订阅的聚合,然后在手机上使用支持 FreshRSS 的阅读器使用。

FreshRSS

目前市面上主要的两个 RSS aggregator 主要就是 Tiny Tiny RSS 和 FreshRSS,在这里我选择了 FreshRSS,部署在香港的一台小鸡上,套了 Caddy + Cloudflare。

运行方式也比较方便,直接使用 docker 运行了,挂载了两个目录,方便日后更新和安装插件。

docker run -d --restart unless-stopped --log-opt max-size=10m \
                            -p 127.0.0.1:8082:80 \
                            -e TZ=Asia/Shanghai \
                            -e 'CRON_MIN=1,31' \
                            -v /root/freshrss/freshrss_data/_data:/var/www/FreshRSS/data \
                            -v /root/freshrss/freshrss_extensions/_data:/var/www/FreshRSS/extensions \
                            --name freshrss \
                            freshrss/freshrss

FreshRSS 也安装了比较实用的几个插件,提高一下使用体验。

  1. Image Proxy: 为了不用在手机上挂:ladder:使用,可以装一个这个插件,把需要挂:ladder:的图片代理一下,用的是自建的 https://wsrv.nl/wsrv/image 。同样的前面也是挂了一层 CF 加速一下。
  2. TranslateTitlesCN: 因为有一些国外的订阅,这个插件可以把标题翻译成中文,还是比较方便的,支持 google Translate / DeepLX / LibreTranslate。并且可以自定义哪些订阅源需要翻译。
  3. 自己写的:有一些订阅源用起来不太舒服,也自己写了一点插件,这里就不献丑了。

RSSHub

RSSHUB 可以将很多没有订阅源网页转换为订阅源,如 bilibili、小红书 等。这个服务目前还是用的自建的,挂在另一只小鸡上。官方也提供了 docker-compose.yml 可以直接使用。但是有一些功能还是需要配置的,如一些 cookie 之类的,暂时没有那部分需求,就直接默认配置了。

services:
    rsshub:
        # two ways to enable puppeteer:
        # * comment out marked lines, then use this image instead: diygod/rsshub:chromium-bundled
        # * (consumes more disk space and memory) leave everything unchanged
        image: diygod/rsshub
        restart: always
        ports:
          - "127.0.0.1:1200:1200"
        environment:
            NODE_ENV: production
            CACHE_TYPE: redis
            REDIS_URL: "redis://redis:6379/"
            PUPPETEER_WS_ENDPOINT: "ws://browserless:3000" # marked
        healthcheck:
            test: ["CMD", "curl", "-f", "http://localhost:1200/healthz"]
            interval: 30s
            timeout: 10s
            retries: 3
        depends_on:
            - redis
            - browserless # marked

    browserless: # marked
        image: browserless/chrome # marked
        restart: always # marked
        ulimits: # marked
            core: # marked
                hard: 0 # marked
                soft: 0 # marked
        healthcheck:
            test: ["CMD", "curl", "-f", "http://localhost:3000/pressure"]
            interval: 30s
            timeout: 10s
            retries: 3

    redis:
        image: redis:alpine
        restart: always
        volumes:
            - redis-data:/data
        healthcheck:
            test: ["CMD", "redis-cli", "ping"]
            interval: 30s
            timeout: 10s
            retries: 5
            start_period: 5s

volumes:
    redis-data:

手机客户端

目前试用了一些 Android 上的客户端,只能说各有千秋,目前用的比较舒服的是 Capy ReaderReadrops。这两个都支持 FreshRSS,可以添加账户。以下评价的可能比较片面,轻喷。

Readrops

这个的优点就是同步感觉还是比较快的,分类搞得也比较好。但是我用的时候会遇到 保存图片 直接 crash 掉的情况。不支持多账户。

Capy Reader

这个做的中规中矩,缺点是图片没提供保存,同步速度还是比较快的,同样是不支持多账户。

其他优化

快捷添加 RSS 订阅

日常使用中发现当自己想添加一个 RSS 订阅的时候,非常麻烦,安卓客户端对添加的订阅源的支持又不太好(配合FreshRSS时),所以需要打开 FreshRSS,然后在各种操作直接添加。之后我就想能不能做一个快捷添加的方式。

  1. 实现一个 QQ 的 bot,发给他链接,然后解析直接添加进去。
  2. 套一层 API 做一个转化,向 API 发送 URL 然后直接添加进去。

这里选择了成本比较低的第二种方式,因为第一种还要一个 QQ 账号。让大模型用 flask 随便搓了一个简单的 API,自己改了改就可以用了。然后部署在了一台小鸡上。

from flask import Flask, request, jsonify
from rss import FreshRSSClient
import os
import logging
from datetime import datetime
import sys

# Configure logging
logging.basicConfig(stream=sys.stdout, level=logging.INFO,
                    format='%(asctime)s - %(message)s')

# FreshRSS 配置
FRESHRSS_URL = os.environ.get("FRESHRSS_URL", "http://localhost:8080")
USERNAME = os.environ.get("FRESHRSS_USERNAME", "admin")
PASSWORD = os.environ.get("FRESHRSS_PASSWORD", "admin")

app = Flask(__name__)

@app.before_request
def log_request_info():
    """
    Logs the user agent of every incoming request.
    """
    user_agent = request.headers.get('User-Agent')
    logging.info(f"Request from User-Agent: {user_agent}")

@app.route('/rss/add', methods=['POST', 'GET'])
def add_rss_feed():
    """
    添加订阅源的路由。
    支持从 GET 请求的查询参数或 POST 请求的请求体中读取订阅源 URL。
    """
    auth = request.args.get('token')
    if auth != os.environ.get("AUTH_TOKEN", None):
        return jsonify({"error": "Invalid token"}), 401
    rss_client = FreshRSSClient(FRESHRSS_URL, USERNAME, PASSWORD)

    feed_url = request.args.get('url')

    if not feed_url and request.method == 'POST':
        data = request.get_json()  # 获取 JSON 格式的请求体
        if data and 'url' in data:
            feed_url = data['url']

    if not feed_url:
        return jsonify({"error": "Missing 'url' parameter"}), 400

    success = rss_client.add_feed(feed_url)
    if success:
        return jsonify({"message": "Feed added successfully!", "url": feed_url}), 200
    else:
        return jsonify({"error": "Failed to add feed", "url": feed_url}), 500

if __name__ == "__main__":
    app.run(debug=True)
import requests
import re

class FreshRSSClient:
    def __init__(self, base_url, username, password):
        """
        初始化 FreshRSS 客户端。
        :param base_url: FreshRSS 的基础 URL(例如:https://rss.example.com/api/greader.php)。
        :param username: FreshRSS 用户名。
        :param password: FreshRSS 密码。
        """
        self.base_url = base_url
        self.username = username
        self.password = password
        self.auth_token = None
        self.sid = None

        # 登录并获取认证信息
        self.login()

    def login(self):
        """
        使用 Google Reader 兼容 API 登录 FreshRSS,获取 SID 和 Auth Token。
        """
        login_url = f"{self.base_url}/accounts/ClientLogin"
        params = {
            "Email": self.username,
            "Passwd": self.password,
        }
        response = requests.post(login_url, params=params)

        if response.status_code != 200:
            raise Exception(f"Login failed with status code {response.status_code}: {response.text}")

        # 从响应中提取 SID 和 Auth Token
        self.sid = re.search(r"SID=(.*)", response.text).group(1)
        self.auth_token = re.search(r"Auth=(.*)", response.text).group(1)
        print(f"Login successful. SID: {self.sid}, Auth: {self.auth_token}")

    def add_feed(self, feed_url):
        """
        使用 Google Reader 兼容 API 添加订阅源。
        :param feed_url: 要添加的订阅源 URL。
        :return: 是否添加成功。
        """
        if not self.auth_token:
            raise Exception("Not logged in. Please call login() first.")

        quickadd_url = f"{self.base_url}/reader/api/0/subscription/quickadd"
        headers = {
            "Authorization": f"GoogleLogin auth={self.auth_token}",
        }
        params = {
            "quickadd": feed_url
        }

        response = requests.post(quickadd_url, headers=headers, params=params)

        if response.status_code == 200:
            print("Feed added successfully!")
            print("Response:", response.json())
            return True
        else:
            print(f"Failed to add feed. Status code: {response.status_code}")
            print("Error:", response.text)
            return False

可以向这个 API 直接 发送一个 GET 请求,就会直接添加进 FreshRSS 的订阅里面,需要提供自己的 用户名和 API 的密码,为了安全指定了一个 token 可以防止被别人调用,都是从环境变量里面读取的。API 地址: https://example.com/rss/add?token=<token>&url=<url>

方便从手机上调用

为了方便在手机上调用,最好是能够直接通过调用系统的分享功能,然后直接添加到 FreshRSS,这里想起了之前使用的 HTTP Request Shortcut,这个 app 可以发送 http request。

配置流程

  1. 创建一个 共享的变量,用于接收从别的app传过来的url。

  2. 创建一个快捷方式。创建一个 GET 请求,把部署的 api 地址写上去。

  3. 之后就可以在别的应用调用这个快捷方式,例如从 rssaid直接订阅。

整体使用流程:

  1. 当我在手机上看到一个博主,想关注他,如 bilibili 的某个up主,复制他主页的 URL,然后使用rssaid ,解析出来,选择希望使用的 订阅。
  2. 发送到 HTTP Request Shortcut 就可以直接添加了。
17 个赞

想起了我落灰的ttrss :joy:

2 个赞

讓我理解一下
Fol.low之類的 是用來管理訂閱 和 訊息的工具
Rsshub或者網站自帶的就是所謂的源頭

1 个赞

对的 :clap:

由于专门的rss阅读器太麻烦,所以直接用rsstt在telegram看

1 个赞

可以呀!感谢大佬思路

1 个赞

佬友太强了

相当于自建的客户端和服务端

1 个赞

rss这方面我已经摆烂了 直接opml导入就不管了 :lark_015:

1 个赞

我目前rss最主要的使用方式就是rsshub+n8n

每日自动推送感兴趣的新闻到邮箱

1 个赞

好强 学习一下

看起来freshrss插件挺实用

学习学习 也在用rss和capy reader

google reader之后rss就死掉了

我用freshrss,因为rsshub 有些错误订阅更新慢,所以要么使用freshrss的xpath直接抓,要么使用自己的fastapi抓。手机上用feedme,感觉速度一般。
imgproxy没用过,赶紧去试试

1 个赞

我用的是自己用php搓的一个代理获取rss内容解决跨域问题的脚本,受你这个启发,我觉得除了ip频次,rss白名单限制外,确实可以加一个token或者key验证,如果传入了token或者key可以不受白名单限制

1 个赞