cd /usr/share/fonts/default/
# 把STHeiTi放到stheiti目录下
# mkfontscale
# mkfontdir
fc-cache -fv
# 查看所有字体
fc-list
# 查看匹配字体
fc-match "sans-serif"
网页截图服务的实现
背景目标
这个需求来源于码农文库,码农文库是一个可以在线分享好文章的地方,但是部分文章的网址在分享之后一段时间之后就失效了, 那这个时候再想看到文章的内容就会比较困难,所以得想个办法对网页做个快照。
功能分析
功能 | 描述 |
---|---|
截图工具选择 |
选择支持好,更新活跃的截图工具 |
中文乱码问题 |
解决Linux下缺少中文字体,造成的网页中文无法正常显示的问题 |
加载超时处理 |
对于网页加载时间比较长的网页,可以放弃截图 |
Socks5代理 |
由于特殊的国情,有些网页需要翻墙才能访问,要截图首先得能访问这个网页 |
被墙域名白名单 |
只有被墙的域名才需要走代理,正常的url正常访问就可以了 |
危险网址域名黑名单 |
如果这个截图服务是对外提供的,难免会有一些黑客想要通过我们的程序去访问一些有问题的网页,以便发现一些漏洞,进而侵入我们的网站 |
禁止文件下载 |
如果这个截图服务是对外提供的,如果有人恶意的输入一些大文件的url地址,而这些文件的下载可以打满服务的网卡,造成服务的不可用 |
详细设计
流程图
linux下安装中文字体
通常情况下,服务器版的linux默认都没有安装中文字体,对网页进行截图的话,会发现中文都是一个个的方块
截图工具的选择
特性 | PhantomJS | Chrome headless |
---|---|---|
webkit内核更新 |
x |
√ |
更新活跃度 |
x |
√ |
由于 Chrome headless 出来的比较晚,之前我选择了 Phantomjs;不过下面两个都会讲一下
安装 Phantomjs
# 安装Phantomjs相对比较简单,只要下载已经编译好的文件,解压就可以了
wget https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-2.1.1-linux-x86_64.tar.bz2
tar jxf phantomjs-2.1.1-linux-x86_64.tar.bz2
mv phantomjs-2.1.1-linux-x86_64 /usr/local/phantomjs
使用 Phantomjs 截图
这里我们借助 casperjs 来调用
var fs = require('fs');
var casper = require('casper').create({
verbose: true,
logLevel: "debug",
stepTimeout: 1 * 60 * 1000,
pageSettings: {
userAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.94 Safari/537.36" // 1280x800
}
});
var url = casper.cli.get('url');
url = url || 'http://tool.lu/';
var device = casper.cli.get('device');
var target = casper.cli.get('target');
var viewport = {width: 1280, height: 800};
switch (device) {
case 'weibo':
viewport = {width: 440, height: 10};
break;
case 'iphone':
viewport = {width: 640, height: 960};
break;
}
casper.start().viewport(viewport.width, viewport.height).thenOpen(url, function () {
this.capture(target);
this.echo(JSON.stringify({url: this.getCurrentUrl(), target : target}));
});
casper.run();
安装 Chrome headless
npm i puppeteer --save
# 如果不出意外的话,是安装不成功的;root用户也会提示权限不足; 执行下面的命令就可以了,然后再安装
npm i puppeteer --unsafe-perm --save
使用 Chrome headless 截图
这里我们使用官方提供的puppeteer来调用
const puppeteer = require('puppeteer');
async function run() {
// {args:['--proxy-server=socks5://127.0.0.1:9050','--no-sandbox','--disable-setuid-sandbox']}
const browser = await puppeteer.launch({args: ['--no-sandbox']});
const page = await browser.newPage();
// await page.setViewport({width: 1280,height: 800});
await page.setViewport({width: 1440,height: 900});
await page.goto('https://tool.lu/', {waitUntil: 'load'});
await page.screenshot({path: 'screenshot.png', fullPage: true});
browser.close();
}
run();
搭建代理
PhantomJS 和 Chrome headless 都支持Socks5代理, 所以这里就直接搭建 ShadowSocks 来实现部分需要翻墙网址的截图
pip install shadowsocks
国外服务器上执行
{
"server" : "0.0.0.0",
"server_port" : 11712,
"password" : "你的密码",
"timeout" : 60,
"method" : "aes-256-cfb"
}
sserver -c server.json
截图服务器上执行
{
"server":"你的国外服务器地址",
"server_port":11712,
"local_address":"127.0.0.1",
"local_port":8016,
"password":"你的密码",
"timeout":60,
"method":"aes-256-cfb"
}
sslocal -c jp.json
Phantomjs 使用代理
LC_CTYPE=en_US.UTF-8 PATH=/usr/local/phantomjs/bin:/usr/bin /usr/local/node/lib/node_modules/casperjs/bin/casperjs --proxy=127.0.0.1:8016 --proxy-type=socks5 --ssl-protocol=any --ignore-ssl-errors=true /data/jobs/webshot/webshot.js
Chrome headless 使用代理
const browser = await puppeteer.launch({
args: ['--proxy-server=socks5://127.0.0.1:8016']
});
翻墙域名白名单
代理搭建好了,也能用了;但是不是所有的url都需要通过代理来访问,这个时候就需要一个域名白名单来决定哪些域名走代理
危险域名网址黑名单
可以直接使用这个开源项目,netxfly/xsec-ip-database
其他
网页截图是个相对比较耗时的操作,如果有大量的恶意请求过来,机器的CPU占用会很高;可以采用放入MQ的方式,让机器自己的消费能力来决定机器的负载
2019-12-14 更新
浏览 24710 次