友情链接模块发布
新增友情链接页面,入口在电脑端的侧边栏或手机端的搜索页的“友链”。
1. 前言
建站七年了,一直没有做友情链接的模块。诚然,博客这种古典互联网产品,友链是最典型的应用,缺失有点遗憾。期间也反复想过要做,但是有两方面问题没有找到满意的方案。
1.1 没有满意的友链样式
网上常见的友链有这些样式:
- 网站名称文字链接
- 头像加网址、网站描述
- 网站链接加最新 feed
头像、网站描述都是静态的,我觉得无趣。于是我尝试过抓取 feed,然后就有两个问题:
- rss 地址发现,需要匹配各种未知规则,除非手动填写地址;
- 有些网站没有 rss,如果直接爬取页面,匹配内容又很麻烦。
所有长期以来,友情链接的表现样式就把我卡住了。
1.2 没有满意的友链规则
相比样式,友链的规则逻辑是让我更想不好的。典型的交换友链方式是,博友之间直接联系,互相提供文字、链接、头像、截图等。我很不喜欢这样的流程,因为有恼人的几个因素:
- 友链需要手动维护,这很不酷;
- 友链如何排序?按评论数排序可以方便回访最亲密的博友,但常规来说应该按加入时间排序;
- 如何监控网站有效性?失效的友链如何处理?手动删除不免令人感伤。
2. 契机
上面两方面问题困扰了我,直到最近遇到两个契机,让我下决心开发了友链模块。
2.1 开发友链的必要性
obaby 在 9 月 14 号《魔咒》的文章中提到给我加了友链。我挺不好意思。但是也重新考虑开发友链这件事。
2.2 找到满意的参考样式
正好Teacher Du在 9 月 20 号发表了文章《关于友情链接的一些事》,我认真看了杜老师的友情链接页面,惊喜地发现这就是我喜欢的样式:
这给我很大启发,网站截图比 feed 更加生动形象!
3. 实现
有了思路之后,实现起来倒不是难事。
3.1 抓取网站截图
借助 puppeteer 完成网站截图。该项目依赖 Chromium,安装时需要科学上网,或者用国内源:
sudo npm install -g cnpm --registry=https://registry.npm.taobao.org
sudo cnpm install puppeteer
关键 js 代码如下:
const
puppeteer = require('puppeteer');
let
args = process.argv.slice(2),
isMobile = 'mobile' === args[0],
waitUntil = 'strict' === args[1] ? 'networkidle0' : 'domcontentloaded',
fetchUrl = args[2],
putFile = args[3];
(async () => {
const browser = await puppeteer.launch({
args: [
'--disable-gpu',
'--disable-dev-shm-usage',
'--disable-setuid-sandbox',
'--no-first-run',
'--no-sandbox',
'--no-zygote',
'--single-process'
]
});
const page = await browser.newPage();
if (isMobile) {
await page.setViewport({"width": 390, "height": 844, "isMobile": true});
} else {
await page.setViewport({"width": 1440, "height": 900, "isMobile": false});
}
await page.goto(fetchUrl, {'timeout': 60000, 'waitUntil': waitUntil});
await page.content();
await page.screenshot({path: putFile, fullPage: true, quality: 100});
await browser.close();
})();
调用示例:
node /node/puppeteer.js mobile strict https://dujun.io /tmp/1.jpg
其中,waitUntil
是个关键参数。networkidle0
代表在 500ms 内没有任何网络连接,domcontentloaded
代表 domcontentloaded 事件触发。要做这个等待是因为有些网站是缓加载的,如果不等待,截图会是一个空白框架。networkidle0
是一个更严格的检查,像瀑布流加载的网站有可能超时,造成抓取失败,所以用 domcontentloaded
做二次抓取。
我需要生成电脑端、手机端两套截图,对应不同设备访问。
3.2 自动维护友链
我让友链的维护自动化,避免任何人工干预。
- 发表过评论并填写了网址的,加入抓取列表;
- 网址有效(header 200 OK)并能被 Chrome Headless 解析,否则过滤;
- puppeteer 能够成功保存截图,否则过滤;
- 按对应评论数从高到低排序;
- 每天重建友链列表。
这就解决了网站有效性检查、删除无效网站,以及添加和排序的所有问题。