FreshRSS实现文章订阅

RSS订阅这个功能,对于想看自己所关注博客的文章,还是非常有必要的,我之前使用Hexo建站使用的是fcircle来搭建,部署上稍显麻烦,涉及到一些环境安装(docker、python),好在官方文档够详细,部署门槛也不是很高,但是后来发现有些问题,一是:不太稳定,二是:感觉有Bug,当然也可能是我自己前端实现的逻辑存在问题导致,所以在我换主题后,果断舍弃了,后来就到处寻找RSS订阅方案。

虹墨空间站给我推荐了Inoreader,并非私有部署,而是将RSS配置好后,将页面通过iframe内嵌进博客,我试了,可以实现,但是样式有些丑,所以舍弃了。

当然中间也尝试了不少其它应用,或多或少有些不如意的地方,所以一直没有采纳,直到看见小宋的rss订阅服务-FreshRSS文章,然后自己去了解了下,界面友好,docker搭建,很方便,就果断采纳了。

我这里就分享下自己搭建的过程,也算是做个记录了,后续迁站等等都用得上

拉取镜像,并运行

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

剩下就是宝塔添加域名解析,然后反代等一系列操作了,配置好RSS订阅源后,几乎就是下面这个样子

搭建FressRSS阅读器,是为了在博客中能直接看到文章,而不是登录后台去看,所以我们还要接入到博客中,我们需要配置几个东西,让其支持API调用

  1. 设置>>认证中,勾选上:允许API访问
  2. 设置>>账户>>账户管理中,设置密码保存;
  3. 宝塔中添加从RSS订阅API获取数据逻辑,并设置定时访问;

如果是PHP的框架,可以参考以下代码来获取RSS数据,这样会把从freshrss的数据存储为json,再用博客去访问解析这个json就可以了,想实现定时获取数据,可以借助宝塔面板的定时任务来实现,具体样式可以按照自己的喜好来调整了。

<?php
/**
 * 获取最新订阅文章并生成JSON文件
 */
function getAllSubscribedArticlesAndSaveToJson($user, $password)
{
    $apiUrl = 'https://你的domain/api/greader.php';
    $loginUrl = $apiUrl . '/accounts/ClientLogin?Email=' . urlencode($user) . '&Passwd=' . urlencode($password);
    $loginResponse = curlRequest($loginUrl);
    if (strpos($loginResponse, 'Auth=') !== false) {
        $authToken = substr($loginResponse, strpos($loginResponse, 'Auth=') + 5);
        $articlesUrl = $apiUrl . '/reader/api/0/stream/contents/reading-list?&n=200';
        $articlesResponse = curlRequest($articlesUrl, $authToken);
        $articles = json_decode($articlesResponse, true);
        if (isset($articles['items'])) {
            usort($articles['items'], function ($a, $b) {
                return $b['published'] - $a['published'];
            });
            $subscriptionsUrl = $apiUrl . '/reader/api/0/subscription/list?output=json';
            $subscriptionsResponse = curlRequest($subscriptionsUrl, $authToken);
            $subscriptions = json_decode($subscriptionsResponse, true);
            if (isset($subscriptions['subscriptions'])) {
                $subscriptionMap = array();
                foreach ($subscriptions['subscriptions'] as $subscription) {
                    $subscriptionMap[$subscription['id']] = $subscription;
                }
                $formattedArticles = array();
                foreach ($articles['items'] as $article) {
                    $desc_length = mb_strlen(strip_tags(html_entity_decode($article['summary']['content'], ENT_QUOTES, 'UTF-8')), 'UTF-8');
                    if ($desc_length > 20) {
                        $short_desc = mb_substr(strip_tags(html_entity_decode($article['summary']['content'], ENT_QUOTES, 'UTF-8')), 0, 99, 'UTF-8') . '...';
                    } else {
                        $short_desc = strip_tags(html_entity_decode($article['summary']['content'], ENT_QUOTES, 'UTF-8'));
                    }
                    
                    $formattedArticle = array(
                        'site_name' => $article['origin']['title'],
                        'title' => $article['title'],
                        'link' => $article['alternate'][0]['href'],
                        'time' => date('Y-m-d H:i', $article['published']),
                        'description' => $short_desc,
                    );

                    $subscriptionId = $article['origin']['streamId'];
                    if (isset($subscriptionMap[$subscriptionId])) {
                        $subscription = $subscriptionMap[$subscriptionId];
                        $iconUrl = $subscription['iconUrl'];
                        $filename = 'https://你的domain/'.substr($iconUrl, strrpos($iconUrl, '/') + 1);
                        $formattedArticle['icon'] = $filename;
                    }

                    $formattedArticles[] = $formattedArticle;
                }

                saveToJsonFile($formattedArticles);
                return $formattedArticles;
            } else {
                echo 'Error retrieving articles.';
            }
        } else {
            echo 'Error retrieving articles.';
        }
    } else {
        echo 'Login failed.';
    }
    return null;
}
function curlRequest($url, $authToken = null)
{
    $ch = curl_init($url);
    if ($authToken) {
        $headers = array(
            'Authorization: GoogleLogin auth=' . $authToken,
        );
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    }
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $response = curl_exec($ch);
    curl_close($ch);
    return $response;
}
/**
 * 将数据保存到JSON文件中
 */
function saveToJsonFile($data)
{
    $json = json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
    file_put_contents('output.json', $json);
    echo '数据已保存到JSON文件中';
}

// 调用函数并提供用户名和密码
getAllSubscribedArticlesAndSaveToJson('demo', '123456');

这样就可以非常方便实现RSS订阅器功能了,使用上没什么问题,很稳定。

当然也有人会选择PHP源码部署,如果你也遇到了RSS不刷新的问题,可以试试以下方案!

我发现基于源码部署后,出现了RSS未定时刷新的问题,因为docker中配置了CRON_MIN=1,31参数,其实就是设定自动刷新的,而源码中并没有,虽然在归档中设置 最小自动刷新间隔 ,实测发现并没什么用,所以决定还是通过url来实现自动刷新。

其实也就是如下两步:

  1. FreshRSS - 设置 - 认证中的"允许匿名刷新文章打开";
  2. 宝塔面板中创建定时任务,填入https://domain/i/?c=feed&a=actualize即可;

当然你如果没有使用运维面板的话,也可以借助cron来实现自动刷新

0 * * * * curl 'https://domain/i/?c=feed&a=actualize'

评论区

😃
提交

全部评论 (35)

  1. 头像
    耳朵的主人 Lv1 回复
    最近用上了博客圈大火的 follow.is,挺好用。
    · 福建 · Windows 10 / Google Chrome
    1. 头像
      满心 博主 回复
      @耳朵的主人 我也看到了,目前还是先用我这个吧,懒得折腾
      · 湖北 · Windows 10 / Google Chrome
  2. 头像
    PeterJXL Lv1 回复
    我最近写了七八篇关于 RSS 的博客🙃 可以来看看
    · 广东 · Windows 10 / Google Chrome
    1. 头像
      满心 博主 回复
      @PeterJXL 是嘛,那我得看看,有没有更好的方案啦
      · 湖北 · Windows 10 / Google Chrome
  3. 头像
    白熊阿丸 Lv3 回复
    这一套部署下来挺好的
    · 北京 · Mac OS X 10.15.7 / Google Chrome
  4. 头像
    万有引力 Lv1 回复
    freshrss好部署一些。ttrss不太好部署了。四个容器。 最少2个。
    不过我还是继续用ttrss
    · 山东 · Windows 10 / Google Chrome
    1. 头像
      满心 博主 回复
      @万有引力 我就是怕麻烦,不过一个东西用时间长了,也不会轻易换的
      · 湖北 · Windows 10 / Google Chrome
  5. 头像
    三十海河 Lv1 回复
    想要请教下 文章页图片点击放大的插件叫什么名字呢,很久就想折腾了,不知道怎么配置。
    · 山东 · Windows 10 / Google Chrome
    1. 头像
      满心 博主 回复
      @三十海河 我用的是fancybox,挺好用的
      · 湖北 · Windows 10 / Google Chrome
  6. 头像
    肌电技术博客 Lv1 回复
    这个就有点厉害了~
    · 北京 · Windows 10 / 手机微信
  7. 头像
    三毛笔记 Lv1 回复
    这个确实可以试一下
    · 福建 · Windows 10 / Google Chrome
  8. 头像
    2broear Lv4 回复
    这个就专业了
    · 北京 · Windows 10 / Microsoft Edge
    1. 头像
      满心 博主 回复
      @2broear 玩博客必备呀
      · 北京 · iOS 17.3 / 手机微信