最近需要在某官方网站下载一些GB/T 及 GB 文件,但是该网站很多文件只提供在线预览功能,通过虚拟打印或者浏览器console的方法貌似也不能实现下载,研究了一下预览页面源码,利用Python写了个小工具来下载pdf,希望和论坛的大神交流一下思路。
预览页面源码分析
关键部分是3层结构,第2层即为每个存储每个页面内容的源码,第3层出现了名为bg 的 url 链接。
1.png (164.56 KB, 下载次数: 0)
下载附件
2022-12-23 23:21 上传
打开链接下载的图片,发现疑似将每个pdf页面进行了分割后重新排列。
2.png (167.45 KB, 下载次数: 0)
下载附件
2022-12-23 23:22 上传
只要能找到重排规律即可恢复每一页pdf内容。
3.png (94.13 KB, 下载次数: 0)
下载附件
2022-12-23 23:22 上传
pdfImg-8-0 代表切割后小图在pdf页面中的位置,应该是第0行,8列
background-position:-240px 0px 代表在分割后合成图(下称:底图)中位置。
根据网页元素分析,小图大小为119*168;
4.png (11.32 KB, 下载次数: 0)
下载附件
2022-12-23 23:23 上传
推测知 bg-position 像素Δ增量 应该为120px和169px。
知道上述定位原则后即可对底图进行分割按照重排规律进行组合,最后输出pdf文件即可。
Python代码实现
为避免侵权,只提供图片切割与重排的代码。其余部分可根据思路自行补充。
涉及的库:bs4,pillow,pandas
def ditu_cut(ditu_pic):
# ###
# 将底图切分为119*169的小图片
# :param ditu_pic:pillow.image对象
# :return:
# ###
w, h = ditu_pic.size
col, row = int(w / 120), int(h / 169)
pic_mat = pd.DataFrame(numpy.zeros((row, col)))
for i in range(col):
for j in range(row):
pic_mat.iloc[j, i] = ditu_pic.crop((i * 120, j * 169, i * 120 + 119, j * 169 + 168))
return pic_mat
def page_merge(page_pic, pic_mat, merge_pos, ditu_pos):
# '''
# 将分割的小图合并成每页pdf内容
# :param page_pic: 新建的pdf页面,大小1190*1680
# :param pic_mat: ditu_cut返回的pillow对象组成的dataframe
# :param merge_pos: 小图在pdf每页的位置即col,row
# :param ditu_pos: 小图在底图的位置,即x,y
# :return:
# '''
y, x = int(int(ditu_pos[0]) / 120), int(int(ditu_pos[1]) / 169)
col, row = int(merge_pos[0]) * 119, int(merge_pos[1]) * 168
page_pic.paste(pic_mat.iloc[x, y], (col, row))
5.png (864.67 KB, 下载次数: 0)
下载附件
2022-12-23 23:41 上传
代码怎么弄都不对,可以看图片。
备注
经过测试,该网站提供了在线预览功能的文件,均能通过此方式进行下载。
我也不太专业,如果有Bug,可以集思广益一起优化。