写了个简易的多个网页连续截图脚本

目前适用于 ngacn 论坛帖子,效果图如下:

启动脚本后,会依次询问你 nga 的帖子 id,总页码数量和帖子名称。脚本会自动检查是否之前已经抓取过该帖子并在上次抓取的最后一页开始继续往下抓取。

每个帖子的抓取结果会放在独立的目录,并以”帖子id”-“自定义名称”的形式储存

注意事项:

  1. 脚本会优先检查是否有 $tid-xxx 形式的目录,只要 $tid 一致,脚本就认为本次会在旧的内容基础上往后抓取截图,xxx 的名称可以是任意的,不检查。假如已经存在一个 『12345-上山打老虎』 的目录,而你第二次输入的是 『12345-钻石王老五』,则实际更新的依然是『12345-上山打老虎』 目录。
  2. 目录名称中间的减号必须保留,否则脚本会忽略已存在的目录,按新目录工作执行。目录内的 1.update.sh 文件也必须保留。
  3. 我的运行环境是 Win10 64 位 1703 版本,不保证在其它机器上能正常运行。在 Win10 下脚本文件可以直接双击打开,在Win7 下可能需要右键点击并选择用 Git Bash 打开。
  4. 需要预先安装该脚本所需要的环境才能正常运行,包括 node、bash 等。

 

安装与准备工作:

  1. 下载并安装 Node for win 使 Windows 获得本截图脚本所需的 node 语言支持: 下载网址: https://nodejs.org/en/download/ ,选择下载 LTS 版本下对应的 32位 或 64  位 Windows Installer。安装一路 next 就行。
  2. 下载并安装 Git for win 使 Windows 也能使用 Bash 脚本。下载网址:https://git-for-windows.github.io/ ,也是一路 next 默认安装就行。
  3. 从开始菜单找到 Git Bash,,点击运行,在黑色窗口内依次输入以下内容:
    效果:
  4. 新建一个目录,起个名,比如叫『nga截图收藏夹』之类的。
  5. 在目录下新建一个文本文件,复制粘贴以下代码:
    随便起个名,并把后缀名改为 .sh。如何修改后缀名请自行百度。

使用:

  1. 双击,依次输入帖子 id,最后一页页码和标题就可以用了。

尾注:

  1. 如果你懂得简单的编程,可以尝试阅读脚本,并自行修改以抓取其它网站的贴子。这个脚本的原理就是利用 nga 帖子很有规律的地址,通过指定帖子 tid、页码 pageid 拼接出需要抓取的指定页面网址,然后反复调用 pageres 去抓取。实际进行抓取的是一个叫 pageres 的 npm 小程序。
  2. 如果你懂得简单的 JS,你可以自行指定 pageres 的抓取参数,甚至包括登录的 cookie 等,以实现『个性化抓取』。
  3. 如果你会完整的 node 开发,希望这个脚本也能为你提供一些参考。

ow.thnuclub.com 更新与计划更新

小站因为忙停更了一段时间,结果被各种催更。值此国庆佳节加之周末免费,趁势也更新一下,再开些空头支票。

  • Done:更新末日铁拳、地平线月球基地及其它英雄新增语音。(1.13 版客户端拆解)
  • 时间有限,只处理了增量更新部分。旧数据的疏漏错误更新后依然存在。他日有空再逐步更新旧数据。

  • Done:去掉了早期开发的赞与踩功能。
  • 在去年小站刚出来时,曾指望让热心用户通过 vote / devote 功能,把『有内容的音频』也就是台词、音乐等条目上浮到前几页,让意义不大的嘈杂环境音下沉。但事实看来结果不好,一来是用户并没有很好地理解该功能。后台数据显示,被踩得最多的是源氏的龙神拔刀,其次是麦爹的午时已到。想必是冤魂太多,多少发泄一下吧╮( ̄▽ ̄”)╭。二来呢,我看到这个数据以后也就懒病发作,没有继续考虑改进该功能了。后来还短暂地改成『倒放音频』,也就是猎奇一番,甚不实用。今日该功能彻底取消,就当是当年那几千投票,终于修正成果了吧。

  • Done:调整了下界面,加了圆角、阴影,js 代码的报错部分也处理了。
  • 主要新增数据会用黄色标签显示在上方。条目按钮加了细微的圆角和渐变阴影,整体会更柔和一些。同时每页条目数从 200 条减少到 100 条,相应的显然页码数量也加了一倍。因为网页背景本身是守望的全屏截图,故整体风格不会有大的变化,没有前后对比,不仔细看的话应该看不出来。修正 JS 报错这事其实也可做可不做,只要不搞死页面,能正常执行功能,jQuery 也就这样了。

  • Done:加了打赏按钮。
  • 这个没啥说的,目前平均也就每周一罐可乐,但听见叮咚声时的好心情很值钱。摊开算收益的话应该现在就把小站关掉,每年能省千儿块服务器钱。

  • Done:更新 36729 条音频的 MP3,音质略有提升。
  • 音频文件的处理路径是游戏客户端→.wem格式→.ogg格式→.mp3格式,理论上每一步都会有损耗。为了能在网页上直接播放必须使用 MP3,但之前在把 OGG 转为 MP3 时我选的是 LameXP 里的质量等级 2(一共 10 级),现在我想通了,把质量等级改成了最高的 0。当然,质量越高,mp3 的体积也越大,从质量 2 到质量 0 体积平均会增大 50%,也就是大概每个文件 20KB 会增加到 30KB。

    这对视频制作者会有所帮助,下载的音频在嵌入视频后的音效会有略微的提升。对 Lame 编码而言,质量 2 到质量 0,新增的数据主要集中在轻微的、高频的或者低频音域。这些音域的补足会让音频的回声、立体感和通透性更好一点点点点,就当是信则有吧。

    缺点是,对于使用手机流量访问的用户流量的消耗会增加。目前统计的平均每条数据大概是 28KB,请量力而行。至于对网页响应速度则是几乎没影响的,你的主要延迟是来自于与 Github.io 这个网站(我拿来存音频源)之间的通讯延迟,至于下载的数据是 20KB 还是 30KB,差的不过是 0.0x 秒而已。

  • Done:当条目文字很长时改用换行式,取代当前的隐藏式。
  • 这个功能和上一条类似,不难,但是会比较烦。换行以后会涉及到每行高度的变化,于是打开编辑面板时的对齐代码就需要调整。同时变化的高度也意味着右侧的齿轮按钮也要相应变化,现在它的高度是写死的。更麻烦的是 Input 框的高度自适应我没做过,可能要换用 contenteditable 的 div,要调整不少代码。好处当然也是显而易见的,长句子台词可以一次看完整了。

    Input 框暂时先不修改了,太麻烦要查资料,一时搞不定。条目本身现在是换行式的了。

  • Done:编辑条目时按 Ctrl+Enter 直接提交当前条目并自动打开下一条的编辑界面并同时播放音频。
  • 我自己,目前还是小站音频条目听写的第一贡献者,我觉得我在编辑条目时遇到的麻烦,你们肯定也遇到了。这个 Ctrl+Enter 的连续编辑提交功能应该会对热心的贡献者比较有帮助。当然伸手党是永远不会遇到这种麻烦的,但谁管你们那么多呢。

    我还没写过根据键盘组合键执行功能的代码,不过想必 Google 一下很容易就能得到答案。这功能不难,但是会比较烦。

 

  • Todo:编辑界面的标签钩选稍微改进一点。
  • 打算把现在的钩选换成和顶部筛选框类似的变色选中,顺便加上和英雄主题色相同的背景色。估计也挺麻烦的,tag 数据都是根据数据库生成的,现在数据库里没有英雄颜色,于是得改后端代码了。

  • Todo:逐步修正音频标签数据。
  • 这个没啥说的,其实主要依靠的是拆解软件的更新。之所以写在这里,是因为现有拆解结果,在数据处理上还能有少许改进,只是要花不少时间。

你看,写完这个,又快天亮了。

Ubuntu 安装 scrapy 及 pip upgrade 时的各种依赖问题

安装 Scrapy 时遇到了依赖问题,使用 pip 时又发现自带的基础 py 包同样依赖不全,后一并 Google 解决,记一笔备忘。

首先安装 PIP,即 python 的包管理器。

由于 ubuntu 官方库提供的 pip 不是最新的,因此需要先 upgrade 自己:

此时如果你直接试图安装 scrapy 是会出错的:

原因是 scrapy 需要抓取网页因而要处理 https,而处理 https 又依赖加解密算法(即 cryptography 包),而 cryptography 又依赖傅立叶变换的算法以及相应的编译环境。Ubuntu 16.04 默认没有安装 libffi-dev 和 libssl-dev,gcc 也不一定安装,而 scrapy 包又没有将相关软件包记到依赖列表里,因此需要先手动安装:

然后再安装 scrapy 即可顺利完成。

 


顺便,由于更新强迫症,一并把 pip 自带的包均更新了一遍。pip 没有 apt 那么好用的 dist-upgrade 命令,需要先手动列出旧包然后逐项更新:

这些 Py 包可以直接升级:

这些 Py 包需要先安装 libssl-dev、libffi-dev、python-dev 以及 build-essential 以后才能升级(其实都是因为要依赖 cryptography):

这些 Py 包需要先安装 python-dev 以及 libjpeg8-dev 以后才能升级:

解决。

 

话说 numpy 的编译时间真是长啊……

HTML5 <audio> 粗考

HTML 5 提供的 <audio> 给了前端相当多的方便,不再需要 js 库和 swf 作为播放器。但是新带来的坑也是坑得我要死要活的。

这是 W3School 提供的一张简表:

Browser MP3 Wav Ogg
Internet Explorer YES NO NO
Chrome YES YES YES
Firefox YES YES YES
Safari YES YES NO
Opera YES YES YES

信了你就掉坑了。

HTML5 的 <audio> 有着比看起来的大得多的坑。主要在于各浏览器的实现上有区别,自带的音频解码器各有不同,导致实际支持的格式各有不一。

并且,在宣称支持的格式里,各浏览器也只支持其中一部分编码格式。例如:

Firefox、Chrome 可以正常播放 Microsoft PCM, 16 bit, mono 8000 Hz 的wav,但是无法播放 GSM 6.10, mono 8000 Hz 的wav

以及来自于 这篇文章 的:

Playing MP3 files in Firefox is actually OS/hardware dependent. That’s right, instead of using a built in, true native support, we have to rely on outside variables that we have no control over. Kind of defeats the purpose of that whole no extensions, native support thing that HTML5 is good for. Yes, this is to avoid patent issues (and so Mozilla doesn’t have to pay licensing fees). If you are serving to a lucky person below, here’s the real MP3 support for Firefox:

  • Windows 7+ (Firefox 21.0)
  • Windows Vista (Firefox 22.0)
  • Android (Firefox 20.0)
  • Firefox OS (Firefox 15.0)
  • OS X 10.7 (Firefox 22.0)

大意是 Firefox  的 MP3 播放支持其实是依赖于系统和硬件的,这样可以免去专利费。相应的,支持列表就变得有点复杂了。

这里有几个测试页, 可以大致用来测试主流浏览器的音频文件支持情况,但是也不完全。就如上文所述,Chrome 对 wav 文件只能说部分支持。

测试页一:http://hpr.dogphilosophy.net/test/

测试页二:https://html5test.com/

所以在实际测试中,某浏览器播放不了指定音频有两种可能性:

  • 音频格式不支持
  • 音频编码格式不支持

对于相关的编码格式,大致查了一下,列表如下:

OGG

同样后缀名为 .ogg 的音频文件,可能有以下几种编码格式: Vorbis, speex, OggPCM, FLAC,其中,Vorbis 是被建议的。

WAV

.wav 文件通常被理解为原始采样,未经压缩。但其实并不一定如此。最广泛标准的 .wav 文件是指微软 PCM 编码的音频文件(其实也已经编码过了,毕竟从模拟信号转数字信号无论如何都会有一个采样过程。)PCM 细分又可分为定长(16bit、32bit 等)和浮点两类。另外.wav 还可能是 GSM 编码格式,这种格式广泛使用于通讯网络,但在互联网上并不常用,最有可能的来源是电话录音导入电脑。

MP3

MP3 规范并没有详细规定如何编码,但却有细致的解码定义。也就是说『符合这一类规范的才叫 MP3』。因此,MP3 的格式反而才是最一致的,除了采样率、变长/定长和声道数量外,不存在其它变化。

Opus

Opus 是设计为同时包含音频和视频的编码格式。* 可以取代复杂的编码后封装方案。但实际上普及率很低,支持也不好。

AAC

AAC (Advanced Audio Coding)主要是得到了苹果的支持。但除此以外,在互联网的使用并不广泛。

Mozilla 提供了另一张更为详细的表格:(注意这个表还是只能作为参考)

Feature Chrome Firefox (Gecko) Internet Explorer Opera Safari
Basic support 3.0 3.5 (1.9.1) 9.0 10.50 3.1
<audio>: PCM in WAVE (Yes) 3.5 (1.9.1) Not supported 10.50 3.1
<audio>: Vorbis in WebM (Yes) 4.0 (2.0) Not supported 10.60 3.1
<audio>: Streaming Vorbis in WebM via MSE ? 36.0 (36.0) ? ? ?
<audio>: Vorbis in Ogg (Yes) 3.5 (1.9.1) Not supported 10.50 Not supported
<audio>: MP3 (Yes) (Yes) 9.0 (Yes) 3.1
<audio>: MP3 in MP4 ? ? ? ? (Yes)
<audio>: AAC in MP4 (Yes) (Yes) 9.0 (Yes) 3.1
<audio>: Opus in Ogg 27.0 15.0 (15.0) ? ? ?
<video>: VP8 and Vorbis in WebM 6.0 4.0 (2.0) 9.0 10.60 3.1
<video>: VP9 and Opus in WebM 29.0 28.0 (28.0) ? (Yes) ?
<video>: Streaming VP9 and Opus/VP8 and Opus in WebM via MSE ? 36.0 (36.0) ? ? ?
<video>: Theora and Vorbis in Ogg (Yes) 3.5 (1.9.1) Not supported 10.50 Not supported
<video>: H.264 and MP3 in MP4 (Yes) (Yes) 9.0 (Yes) (Yes)
<video>: H.264 and AAC in MP4 (Yes) (Yes) 9.0 (Yes) 3.1
any other format Not supported Not supported Not supported Not supported 3.1

 

所以解决方案大概就是先通过测试确定一两种被绝大部分浏览器支持的音频编码格式,然后服务器后端将音频文件转码为这一到两种适用的音频格式再传递给前端。

看起来最通用的是 MP3?简单地说,是的。但要注意的是不是任意一种 mp3 编码格式都支持,最优化编码的 VBR 支持性就存疑。同时,由于 Firefox 的 MP3 支持是基于系统的,所以假如 Ubuntu 没有安装 ubuntu-restricted-extra 包也可能出现支持性问题。

 

* 附:

更复杂的是 <video> 标签,由于视频通常是包含声音和图像两部分的,因此实际上视频文件数据是由已经编码的视频数据和已经编码的音频数据,再次进行数据交错编制而成的。因此除 编码格式 外,又衍伸出 封装格式 的概念。深受大家喜爱的 .avi 格式,即 Audio Video Interleave 的简写,就是一种封装格式。当你使用 avi 封装器折开文件后,就会见到一个无声的视频文件和一个无图像的音频文件。至于各自的编码格式又五花八门了。因此对于 <video> 标签的支持更加混乱,几乎必然需要通过服务器转码才能确保在尽可能多的浏览器上前端一致,这也是各视频网站为什么会有大量集群转码处理用户上传的视频的原因。

Chrome 44 拼写检查的浏览器性能 bug

Chrome 在更新到 44.0.2403.125 m 后,存在一个由拼写检查导致的性能低下 bug,该 bug 只在 win 版 Chrome 下呈现,同时影响 32 位和 64 位版本。

chrome-44-about

就是这货

具体表现
将上面这段代码另存为 html 网页,在 Chrome 44 (win) 版本下打开。

用文本编辑器制造 10000 行会被触发单词拼写识别的文本,比如使用 Excel 连续生成 10000 行『AKB0048』。复制粘贴到橙色 Textarea 框中,然后用鼠标点击灰色 Input 框……

你会发现,非常的卡,光标在三个输入框中切换,每次切换都需要花费很长时间,对于性能不佳的电脑,和彻底进入死循环没区别了。

刷新页面重置数据后,再将这 10000 行粘贴到 Contenteditable DIV 的蓝色框里,第一次粘贴也略有卡顿,毕竟数据量比较大。但等卡顿过后,鼠标再在三个框中反复切换,就非常顺畅毫无迟滞感了。

10000linta10000lindiv

这就是这个 bug 的真身了:

在 Textarea 有大量会触发拼写检查的内容时,Chrome 44 的 Spellcheck 功能会极大消耗计算机资源,使得整台电脑近乎死机。

解决办法

由于这是浏览器 bug,前端程序员对此几乎无能为力,只能绕过这个 bug。

通常来说,HTML5 已经提出了 Textarea 的一些标准属性,比如 spellcheck=”false” 可以强制浏览器不检查内容,webkit 内核支持这一属性。正常来说,这似乎是很容易解决的一个兼容性问题。

但偏偏 Chrome 却强制忽略了这一设置,就像它强制忽略 font-size < 10 时那样。禁用拼写检查只在用户手动输入时有效,而对于 Ctrl+V 进来的内容,拼写检查依然正常运行,搞死你机。

即使你把相关属性全部列全:

也是然并卵,在别的浏览器一切正常,而 Chrome 下依然故我。并没有解决问题。

解决方法一:

你可以通过 JS 检查当前浏览器是否是 Chrome,在需要粘贴大量内容的 textarea 上提示用户去关闭 SpellCheck 功能,具体位置为:

Chrome 菜单 → 设置 → (最下方)显示高级设置 → 语言和输入设置 → 启用拼写检查。

但这并不是一个好方法,尤其是需要用户主动去对 Chrome 进行设置。

解决方法二:

使用 JS,将一次的粘贴行为,模拟为连续字符添加的行为。比如当用户 Paste 后得到 Text 值,立刻删除该 Textarea 元素再重建一个。然后根据 text.length 使用 JQuery 插件 Jquery.Caret 不断循环插入字符。

这一方法缺点更多,首先是作为 walkaround 的方案,引入了太多并非用户参与的互动。其次,这一 bug 本来就是在大文本量 paste 下才会出现,如果再使用额外的一重循环,并不会使得体验有太多改善。最后,假如 Chrome 的再次升级把 JS 插入字符也纳入拼写检查的话,就会导致页面更 n 倍重的卡顿,到时候大概是再高性能的电脑都扛不住了。

解决方法三:

使用带 contenteditable=’true’ 属性的 DIV 元素代替 Textarea,并使用 innerText 或者 $.text() 来获取用户填写的文本内容。

这也是这篇博客所写的内容,这样的方法是最合法且绕过 Chrome 44 拼写检查 Bug 的方法。完全相当于是『有两种实现方法选择了另一种』。contenteditable = ‘true’ 属性的 DIV 往往也是很多 JS 版所见即所得编辑器的常用办法。比如 WordPress。这一方法不需要用户操作,也只需要少量 JS 代码。最后,即使这个 BUG 的影响范围继续蔓延,也不过是和现有的情况一样,不会更坏。

关于 MAC 版 Chrome:

Mac 下无此 bug,是因为暂时还没有拼写检查功能。

Javascript 的时间格式问题

先上代码:
再说结论:

在 Javascript 中,当为某个变量只赋值日期时,会默认使用该日期的 0 点 0 分 0 秒作为完整的值。而根据表现格式的不同,在具体赋值时会使用不同的时区时间赋值。

当使用『-』作为年月日的分隔,即 YYYY-MM-DD 的格式时,赋值会根据 GMT/UTC 时间的当日 0 点赋值,再根据浏览器提供的系统时间,折算为当地时间。也就是说,如果你在北京,并且电脑时区正常。那么当你为某变量赋值『今天』时,实际上赋的值是 0 时区的 0 点 0 分 0 秒,换算成北京时间为早上 8 点。如果在东京,则是早上 9 点。

也就是说,无论是在哪个时区,相同的一套代码在不同的电脑上,会得到相同的值。

 

而当使用『/』作为年月日的分隔,即 YYYY/MM/DD 的格式时,赋值则根据电脑时间,取到本地时间该日的 0 点 0 分 0 秒。由于各时区都差一个小时整,实际上会导致 JS 代码在不同时区电脑上执行相同代码时,得到的时间值在绝对值上并不相等。即在北京时区时,会取到北京时区的 0 点 0 分 0 秒,同一时刻在东京则已经是当日 1 点 0 分 0 秒了。

换句话说,不同客户端执行相同代码会取得不同的值。

 

但即使如此,两者也有表现相同的时候。只要在赋值时就明确指定时区,则两者的值可以是相同的。例如:

同时,无论是哪种情况,当通过 JS 转换成时间戳时,其值都是相同的。原因在于时间戳本身的定义,就是指当前时间距 0 时区的 1970 年 1 月 1 号 0 点 0 分 0 秒的秒数。所以在执行环境中,函数会根据电脑的时区设置来加减相应的小时数,先转换为 0 时区,然后再进行时间距离的计算。

参考:

http://www.w3schools.com/js/js_date_formats.asp

今天学习了 DOM 事件流三阶段

起了个小学生式标题。

这东西又是浏览器历史的一桩恩怨……当最初的 HTML 标记式的语言结构逐步成形后,人们开始对网页内的互动有了要求。当然,这事本来并不难,所有的用户互动归根结底就是『触发事件 – 判断当前状态 – 执行相应命令』的逻辑,而 HTML 本身就已经通过开标签和闭标签组对的形式,很好地形成了后来被称之为『DOM 元素』的数据结构,理论上只要把触发事件分别加到一个个的元素上,或者按需加到某些特定的元素上,就可以执行命令了。

然后问题就来了。

由于 HTML 的表现是盒式结构,都是一些大框框包含小框框的情况。比如如下代码:

形成的 DOM 盒式包含结构大约就是这样:

无命名

当用户点击红块时,实际上浏览器是无法判断这次点击的意图的,也就是说,到底应该是点在红块上,红块对这次点击作出反应,还是点在绿块上,亦或是蓝块上。即使是三者都算作被点到了,三者都有反应,那怎么也得有个先后顺序吧。

有两种顺序都可以,一种是先子后父,先里后外,红绿蓝顺序;第二种是先父后子,先外后里,蓝绿红顺序。

两者都可以,两者都有理,然后老 IE 用的是前者,老 Netscape 用的是后者……结的梁子够多了,也不差这一个了。

于是新的协议为了兼容,提出了 DOM 事件流的三个阶段的设计,即……首先,都别争了,顺序就按『蓝绿红绿蓝』这么来吧……然后,这一顺序又分成三个阶段,第一阶段我称之为『下沉』,顺序为蓝绿;第二阶段『触底』,系统发现红色已经是最底层 DOM 元素了,第三阶段『上浮』,顺序变成了红绿蓝。

这三个阶段是有标准的命名的,分别是『捕获阶段』、『目标阶段』、『冒泡阶段』。并且严格来说,捕获阶段不包括最底层元素,而冒泡阶段包括目标阶段。盗图一张:

001108_Ry8q_214423

尽管规范上来说,要求捕获阶段只注册事件,而在冒泡阶段执行相应阶段。但事实上各浏览器在实现时,都允许在捕获阶段也执行相应的事件。结果就是,对于一个目标,有两次执行事件的机会。这在为 DOM 元素添加事件的 JS 函数里就写得很明白:

其中第三参数就是决定这个事件是否在捕获阶段就开始执行的。

当我们使用 jQuery 等第三方库时,这一特性被 jQuery 很好地隐藏封装起来了,并良好地处理了各浏览器不一致的特性,使得我们可以通过 .click() 函数方便地添加点击事件,并不用考虑三个阶段的问题。

将图片信息写入 HTML 和 CSS

通常来说 HTML 和 CSS 中引用图片都用的是 <img src=”…”> 和 url(…) 的引用办法。有时为了节约连接数,在诸如图标库等特殊用途 css 中,也会使用一张大图片通过 position 定位到不同位置的办法,来把所有图标放在同一张图片上。

不过还有一种办法是直接把图片通过 base64 编码以后写到文本中。对于非常静态化的需求,比如电子书、自制在线简历、email 投递、网络隐私安全病患者等等,或者各种原因在输入端只支持文本的场合,有时也是一种不错的选择。

这种办法其实很简单,就是把原来写 url 的位置替换成图片 base64 编码以后的文本。

比如我有一张图片,,把它用 base64 编码以后就成了一长串文本:(编译工具用百度一搜就行,在线的,本地的多得去了,在 Github 上还能搜到完全基于 JS 的。)

这串文本很长,不过相比于图片本身的体积,其实并没有大多少。这种体积的变化详细涉及到信息论和压缩原理,这篇文章先不写了。

然后我们在长串文本前再添加一些说明文字,供浏览器识别:

然后就可以直接替换原 url 了,就像这样:

编码头的标准格式是

理论上方括号是可以省略的,同时也可以看到还有其它编码形式,比如base85、base16 等,尽管没有什么实际意义甚至有反效果。(比如有浏览器兼容性、超出合法字符区间等情况)。

好处与坏处:

  • 更新:保证网页上的重要图片不会加载失败。当 HTML 加载完毕或 CSS 加载完毕时,图片一定可以正常显示。不会出现 HTML+CSS 加载成功,但图片没有显示的问题。特别适合于类似评分星级、打标等功能。
  • 节约连接数:http 协议下,每个单独资源在客户端都呈现为一个独立文件(在服务器端部分是),都需要握手协议开销和传输开销,而使用 base64 以后,就变成了 “文件内部” 数据,不需要额外开销。而在呈现上没有变化。这在某网页有大量小文件的静态资源时尤其有用。但随着 cdn 的发展,这种情况又少下去了。
  • 图片过滤无效:有时候用户因为某些原因会屏蔽网页上的图片呈现,这些屏蔽方式通常都是通过匹配 html/css/js 中的资源路径实现的,但在 base64 编码下这种方式会无效。但相应的,基于服务器代理转码的浏览器(UC 之类通常是手机端浏览器),以前也无法转换,现在应该改进了吧。是好是坏看具体场景了。
  • 不方便编辑:这个主要出现在常用的文本编辑器里,在成熟的 IDE 环境中则不存在这种问题,鼠标移到 base64 图片上同样会有预览。有些文件编辑器也通过插件来解决类似问题。
  • 其它:呃…… 少量增加整个网页体积,等。

最后是 php 版的 base64 图片生成:

用的也是现成库,别的代码版本就不写了。

水平且垂直居中 CSS 详解

自适应的水平垂直居中

旅行商人罗伦斯在马车货台上的麦束堆里,发现沉睡中的少女——自称是丰收之神赫萝的美丽少女,有着狼的耳朵及尾巴。

「虽然奴家长久以来被尊为神,不过,奴家就是奴家,奴家是赫萝。」

 

相比于水平居中用 margin:auto; 的简便,CSS 没有直接的垂直居中属性,必须通过各种诡异的技巧去实现,确实让人很头疼。以上算是一种实现方式,核心的代码如下:

 
这段代码中,最重要的是 .outer:before 这个伪元素。它起到了连接内外元素以及垂直对齐的作用。
 
需要明白的是,对一个 div 而言,它的伪元素会放在这个 div 包含的任何内容元素的前面,默认为 inline-block 元素(即“行内元素”或者“内联元素”)。示例:

执行结果:

元素内容

 
当元素内容为其它元素,尤其是块级元素时,则有内容的 :before 会在最顶上。

<p>元素块级内容</p>

 
再强调一遍,:before 其实是一个元素的子元素,永远排在其它实际子元素的前面,比如:

的实际执行效果如下:

是特殊的子元素

可以看到,对于 p 元素添加的 border,连 :before 这段文字也被包含在内。
 
现在再回头来看原始代码,如果把 :before 的部分修改一下,给 :before 元素加个边框,修改内容,使得识别更简单:

垂直居中

这样这段代码的原理就非常清楚了。首先,:before 伪元素和内部元素(通过 display:inline-block 设置为行内元素)共同构成了“一行文字”。其次,所有的行内元素都利用 vertical-align:middle 进行了垂直居中对齐。最后,再设置 :before 的高度使得它上下都顶到父元素的边框。这样,同一”行”内的其它元素在视觉就都相对父元素垂直居中了。其实它们在逻辑上真正对齐的对象是 :before。而 :before 自己,则被“卡”到了正中间的位置。
 
最后,由于 :before 在没有实际内容(通常用 ” ” 空格填充 content 属性)时其实也有宽度,所以在父元素上使用针对文本的 text-align: center; 虽然可以把左右居中也一起做掉。不过还是用常规的 margin:auto 更精确一点。解决办法是对 :after 伪元素也设置 content:” “。

PS:因为 ie6 不支持伪元素,所以……要不还是用 table 吧。

新浪微博图片缩略图规则

 新浪微博在用户上传图片后,会对图片进行处理,生成不同版本的缩小图,以适应各种客户端的需求。图片分为 large、bmiddle、small、thumbnail、square 五种尺寸,在需要相应大小图片时,只需要对图片 url 的该段进行替换即可:

/large/:

原图。

/bmiddle/:

当原图宽度>440 像素时,则按比例缩小图片使得宽度=440 像素。当原图宽小于440像素时,则直接原图。高度无关。

/small/:

规则类似 thumbnail,尺寸为 200 像素。最小断点未测试,猜测为 60 像素。

/thumbnail/:

1. 当长宽比例< 120:35.5 时,比例缩小到长和宽均不大于 120 像素,即:竖长图缩为高120像素,横长图缩为宽120像素;

2. 当比例≥ 120:35.5 时,即当按比例缩放时,一边满足 120 像素另一边尺寸小于 36 像素,则进行特殊处理;

2.1 竖向图片,缩放为宽 36 像素,然后从顶部往下截取 120 像素的部分作为 thumbnail 图;

2.2横向图片,则重新缩放,以120像素为高度,截取左边的120像素作为宽度,形成一个 120×120 的正方形 thumbnail 图。

3. 当原图片长宽均小于 120 像素,不处理。

/square/:

按比例缩小到长宽中的较小值等于 80 像素,然后再对另一边进行居中裁切,使得两边都等于 80 像素。

sinapic-size