海纳医信的 DICOM 云影像下载

发布时间:

最后更新:

上次写了一篇《爬取 CT 云影像的 DICOM 原始文件》,本以为是个小众需求,毕竟相关教程很少,但没想到很快就收到了些回复,其中就有人问我怎么爬另一个网站。

这回的网站长这样这回的网站长这样

粗略一看该网站界面比上次的好些,至少布局是对齐了,它的域名是 medicalimagecloud.com,能搜到叫海纳医信

不管怎样,这种小网站一般都没什么反爬措施,弄起来都挺简单的——我一开始也是这么想,但后来发现这回的网站还要真费点功夫。

本文记录下爬取该网站的思路,具体的代码见 cloud-dicom-downloader

爬虫思路 #

第一次进去就立刻点开 F12,在网络一栏里找可能是影像文件的请求,这个网站倒是没整 WebSocket 之类的东西,很容易找出关键请求:

NetworkNetwork

响应体保存到文件,打开看了下不是 DICOM 的文件:

文件头文件头

但是一眼瞅到个ftypjp2,说明下载的是 JPEG 2000 格式的图片。再回去把网页上的按钮都摸一遍,发现菜单里能选格式:

菜单菜单

看到熟悉的 Dicom 字样,我以为这次的爬虫就已经搞定了,只要写个脚本批量下载即可,于是便安心地睡去。直到第二天阅片软件打不开时我才发现下载的并不是 DICOM 文件。

这个下载下来的文件内容比较稀疏,大部分是 0x00,隔一段有一些其它的值,很明显没有压缩,看上去页不像是加密后的数据,同时它无法解码为字符串,大概率还是二进制的格式。另外文件的大小也引起了我的注意,都是 524288 字节,这个数正好等于 512 x 512 x 2,而片子的尺寸也是 512 像素的正方形,有没有可能它是图片的像素数据呢?

为了验证,直接读取该文件作为像素数据画成灰度图,结果正好就是 CT 影像,只不过暗了些,但这可能跟查看器有关,但它一定是图片内容没得跑了。

我们知道 DICOM 文件是由主体的图像加上附加信息(标签)组成的,从响应头中也能找到一个X-ImageFrame包含了额外的信息,这说明该网站把 DICOM 文件给拆开了,分别发送标签和图像,于是一种可行的方案就是下载完它们之后重新合成。

做逆向工程,包括爬虫,一定要对数据有敏感性。文件大小、头尾的内容、分布特征都是重要的线索,通过它们有时能快速判断对方的设计方案,这也是很需要积累的地方。

有其他方案吗? #

当然如果能直接下载原始的文件是最好不过的,所以我还是又去网页里找了找,在源码里发现一个似乎是下载的 API:

Common-min.jsCommon-min.js

可惜参数storageNode和请求体studyDirectory无法确定,试了下不填它们结果返回 500。在/ImageViewer/GetPatientStudies请求的响应中还发现storageNode都是null,我觉得这条路是走不通了。

另外 DICOM 标准包括了一套通信机制,但那是给医院内部用的,比如 CT 机扫完使用C-Store命令上传结果,然后让科室里的电脑能查询到。这套系统是否包含认证功能,以及在外部能否访问也都不知道,我也没发现该网站有这样的 API。

所以最终还是决定使用爬取后重组的方案。

登录流程 #

那就开爬,首先是过认证。模拟登录是爬虫的基础,不多讲,这个网站的跳转还挺多:

查看器页面查看器页面

下载流程 #

回到 F12 控制台的网络部分,把所有 JSON 响应都看一遍就能知道:

下载的话就是先拿基本信息,然后遍历所有序列(在它的响应里是displaySets),每个序列再挨个下载所有图像和标签,最后合成。

其他事项 #

DICOM 是一个历史悠久的格式,各个语言都有库可以用,生成 DCM 文件不是什么问题,库的用法见源码吧。

但这个网站有一个问题,就是获取不到标签的类型。

上面提到的/ImageViewer/GetImageDicomTags拿到的数据只有tagnamevalue三个字段,缺乏VR,对于标准中已有定义的标签倒是好说,但还有一些私有的标签,比如 CT 机的电压等等,我这只能把它们视为字符串了。这个问题应该影响不大,因为非标准标签本来用到的就少。

最后还有个担心的问题图像会不会给有损压缩了,毕竟界面上只有高低质量的切换功能,没有“无损”或是“原图”等词语。这个可以从 F12 工具里网络请求的 Stack Trace 面板跳转到发请求的代码:

FetchFromServerFetchFromServer

可以看出 URL Path 的最后一个部分是pi,而pi计算得来,i在上面的setResolutionLevel中作为唯一参数,故它就是 Resolution Level,然后在另一处代码能找到这一行字:

ResolutionLevelResolutionLevel

此处有“lossless”这个词,说明还下载到的图像无论 J2K 还是像素格式,都是无损的原片。

评论加载中