上次写了一篇《爬取 CT 云影像的 DICOM 原始文件》,本以为是个小众需求,毕竟相关教程很少,但没想到很快就收到了些回复,其中就有人问我怎么爬另一个网站。
这回的网站长这样
粗略一看该网站界面比上次的好些,至少布局是对齐了,域名是 medicalimagecloud.com,能搜到叫海纳医信。
不管怎样,这种小网站一般都没什么反爬措施,弄起来都挺简单的——我一开始也是这么想,但后来发现这回的网站还要真费点功夫。
本文记录下爬取该网站的思路,具体的代码见 cloud-dicom-downloader。
爬虫思路 #
第一次进去就立刻点开 F12,在网络一栏里找可能是影像文件的请求,这个网站倒是没整 WebSocket 之类的东西,很容易定位关键请求:
Network
响应体保存到文件,打开看了下不是 DICOM 的文件:
文件头
但是一眼瞅到个ftypjp2,说明下载的是 JPEG 2000 格式的图片。再回去把网页上的按钮都摸一遍,发现菜单里能选格式:
菜单
看到熟悉的 Dicom 字样,我以为这次的爬虫就已经搞定了,只要写个脚本批量下载即可,于是便安心地睡去。直到第二天阅片软件打不开时我才发现下载的并不是 DICOM 文件。
这个下载下来的文件内容比较稀疏,大部分是 0x00,隔一段有一些其它的值,很明显没有压缩,看上去也不像是加密后的数据;同时它无法解码为字符串,大概率还是二进制的格式。另外文件的大小也引起了我的注意,都是 524288 字节,这个数正好等于 512 x 512 x 2,而片子的尺寸也是 512 像素的正方形,有没有可能它是图片的像素数据呢?
为了验证,直接读取文件画成灰度图,结果正好就是 CT 影像,只不过暗了些,这可能跟查看器有关,但它一定是图片内容没得跑了。
我们知道 DCM 文件是由主体的图像加上附加信息(标签)组成的,从响应头中也能找到一个X-ImageFrame包含了额外的信息,这说明该网站把 DCM 文件给拆开了,分别发送标签和图像,于是一种可行的方案就是下载完它们之后重新合成。
做逆向工程,包括爬虫,一定要对数据有敏感性。文件大小、头尾的内容、分布特征都是重要的线索,通过它们有时能快速判断对方的设计方案,这也是很需要积累的地方。
有其他方案吗? #
当然如果能直接下载原始的文件是最好不过的,所以我还是又去网页里找了找,在源码里发现一个似乎是下载的 API:
Common-min.js
可惜参数storageNode和请求体studyDirectory无法确定,试了下不填它们结果返回 500。在/ImageViewer/GetPatientStudies请求的响应中还发现storageNode都是null,我觉得这条路是走不通了。
另外 DICOM 标准包括了一套通信机制,但那是给医院内部用的,比如 CT 机扫完使用C-Store命令上传结果,然后让科室里的电脑能查询到。这套系统是否包含认证功能,以及在外部能否访问也都不知道,我也没发现该网站有这样的 API。
所以最终还是采用爬取后重组的方案。
登录流程 #
那就开爬,首先是过认证。模拟登录是爬虫的基础,不多讲,这个网站的跳转还挺多:
首先入口是一个https://
发送 POST 到跳转的登录页,请求体为id=
从报告页中搜索查看影像链接元素,其href即为查看器页面的链接。
请求查看器链接,返回一个跳转页并设置了一些 Cookies,在该页面中可以找到个window.location.href= 'xxxxx'代码,看来是用 JS 来做自动跳转的。
继续跟过去,又 TM 是一个跳转页,还是同样的配方,在页面代码里找到var TARGET_PATH = "xxxxx",xxxxx即为最终的查看器页面。
最后在查看器页面的源码里能够找到一些关键信息,都在一个