D3 Note - Interpolate
d3-interpolate
是 D3 的核心模块之一,与比例尺有些类似,interpolate
(插值)所做的也是一些数值映射的工作。区别是,interpolate
的定义域始终是 0 ~ 1,并且始终为线性的。所以,更多时候它用来与 D3 的一些其他模组集成使用(如 transition, scale 等)。
d3-interpolate
是 D3 的核心模块之一,与比例尺有些类似,interpolate
(插值)所做的也是一些数值映射的工作。区别是,interpolate
的定义域始终是 0 ~ 1,并且始终为线性的。所以,更多时候它用来与 D3 的一些其他模组集成使用(如 transition, scale 等)。
之前做的柱状图例子:
let data = [250, 210, 170, 100, 190] |
有一个严重的问题,就是没有比例尺的概念,柱状图的高度完全由数据转换成像素值来模拟。这明显是不科学的:如果数据的值过小或过大,作出来的图就会很奇怪,同时也无法做到非线性的映射。
就跟地图需要比例尺一样,绝大多数的数据图表也需要比例尺。
Scales are a convenient abstraction for a fundamental task in visualization: mapping a dimension of abstract data to a visual representation.
比例尺 - Scale - “将某个维度的抽象数据做可视化映射”
至于可视化映射的具体实现,d3-scale
模块提供了许多方案,大致可以分为两类:
博客再次迁移,这次是从 Wordpress 转向静态博客(自建)。
技术栈:
整站打包后,一次加载所有资源(HTML + CSS + JS + DATA)300K 不到(gzip 后 80K+),秒速渲染,与先前真的是天差地别。
图片资源从本地服务器搬迁到免费云。 写作使用 Markdown,从此 IDE 写博客不是梦。
在 D3 的使用过程中,我们见得最多的应当是类似如下的代码:
let div = d3.select('body') |
将得到:
<body> |
光看代码完全不能理解 D3 到底做了些什么,其实这里关键是 enter
的使用。
Problem solved.
HTTP 是一种无状态协议,服务器与客户端之间储存状态信息主要靠 Session,但是,Session 在浏览器关闭后就会失效,再次开启先前所储存的状态都会丢失,因此还需要借助 Cookie
一般来说,网络爬虫不是浏览器,因此,只能靠手动记住 Cookie 来与服务器“保持联系”。
Cookie 是 HTTP 协议的一部分,处理流程为:
因此,爬虫要做的工作就是模拟浏览器,识别服务端发来的 Cookie 并保存,之后每次请求都带上 Cookie 头。
在 Node.js 中有很多与 Cookie 处理相关的 package,就不再赘述。
Cookie 虽然方便,但是由于保存在客户端,可保存的长度有限,且可以被伪造。因此,为了解决这些问题,就有了 Session
区别:
Cookie 与 Session 储存的都是客户端与服务器之间的会话状态信息,它们之间主要靠一个秘钥来进行匹配,称之为 SESSION_ID
,如 express 中默认为 connect.sid
字段。只要浏览器发出的 SESSION_ID 与服务器储存的字段匹配上,那么服务器就将其认作为一个 Session,只要 SESSION_ID 的长度足够大,几乎是不可能被伪造的。因此,敏感信息储存在 Session 中要比 Cookie 安全得多。
常见的 Session 存放媒介有:
Session 不是爬虫可以接触到的东西。
对于静态页面(服务端渲染),使用爬虫不需要考虑太多,把页面抓取下来解析即可。但对于客户端渲染,尤其是前后端完全分离的网站,一般不能直接获取页面(甚至没有必要获取页面),而是转而分析其实际请求内容。
通过一些请求拦截分析工具(如 Chrome 开发者工具)可以截获网站向服务器发送的所有请求以及相应的回复。
包括(不限于)以下信息:
只要把信息尽数伪造,那么爬虫发出的请求照样可以从服务器取得正确的结果。
一些请求中会带有秘钥(token / sid / secret),可能随除了请求方法外的任一个位置发出,也可能都带有秘钥。更可能不止一个秘钥。
理论上来说,正常客户端取得秘钥有两种方式:
对于服务端提供给客户端的秘钥,只要仔细分析 HTML 或服务端返回的 Cookie Header 就一定能发现。
而对于客户端自行计算的秘钥则比较麻烦了,尤其是在 JS 代码加密、混淆的情况下。这种时候,只能自己去用开发者工具调试原始站点代码,找出加密代码段,并在爬虫中实现。这里面有许多技巧,如各种断点、单步调试等。
表单实际上也是 HTTP 请求,使用 GET / POST 等方法即可模拟表单提交。然而这不是重点。重点是表单常常伴随着验证码而存在。
验证码的识别暂未涉及。
爬虫的下下策才是使用浏览器完全模拟用户操作。实在是属于无奈之举。Nodejs 可以驱动 Chrome 与 Firefox 浏览器,存在相应的 Package,但是,更方便的是使用各种 E2E Testing 工具。
比如 Night Watch JS:
module.exports = { |
在这种模式下,Cookie / Session / 请求等各种细节都不用关心了。只需要按部就班地执行操作即可。模拟浏览器的代价是效率太低,内存开销大,但在某些特定需求情况下,却比一般爬虫要简单得多。
D3 (Data-Driven Documents) 是一个 JavaScript Library,用来做 Web 端的数据可视化实现以及各种绘图。
D3.js is a JavaScript library for manipulating documents based on data. D3 helps you bring data to life using HTML, SVG, and CSS.
学习 D3 需要很多预备知识:
HTML / CSS 不必多说,因为 D3 含有大量链式操作函数以及选择器等,因此如果有 jQuery 基础将轻松很多。此外,由于一般采用 SVG 方式进行绘图,所以 SVG 基础知识也需要掌握。
虽然必须的预备知识如此之多,但 D3 的定位其实是 Web 前端绘图的底层工具,所谓底层,即是操作复杂而功能强大者。
项目地址:https://github.com/wxsms/zhihu-spider
简介:使用 Node.js 实现的一个简单的知乎爬虫,可以以一个用户为入口,爬取其账号下的一些基本信息,关注者,关注话题等。再通过关注者的 ID 继续爬取其他用户,以此循环。
实现功能:登录知乎(因为调用一些知乎 API 需要保存 session),解析页面,访问 AJAX API,保存到数据库。
知乎上有一个黑 JavaScript 的段子,大概是说:
N 年后,外星人截获了 NASA 发射的飞行器并破解其源代码,翻到最后发现好几页的 }}}}}}……
这是因为 NASA 近年发射过使用 JavaScript 编程的飞行器,而 Node.js 环境下的 JavaScript 有个臭名昭著的特色:Callback hell(回调地狱的意思)
JavaScript Promise 是一种用来取代超长回调嵌套编程风格(特指 Node.js)的解决方案。
比如:
getAsync("/api/something", (error, result) => { |
将可以写作:
let promise = getAsyncPromise("/api/something"); |
乍一看好像并没有什么区别,依然是回调。但最近在做的一个东西让我明白,Promise 的目的不是为了干掉回调函数,而是为了干掉嵌套回调函数。