从thinkcentral的swf中提取书籍——旁门邪道

August 19, 2019 · 分享 · python · 63次阅读

操作视频预览如上(不知道能不能看)。
总的来说就是:
python通过selenium库控制Chrome类的浏览器执行打印页面的操作,涉及到的问题如下:

  • swf转pdf,很特定的情况下才有方法。
  • 单页是swf,新版本Chrome无法在headless情况下打开flash。
  • 就算默认打开flash(注册表的方式),然而Chrome会直接下载swf文件,而不是加载。
  • 360极速浏览器可以加载swf并打印页面,但没找到用selenium控制它的方法。
  • 这网站swf链接规律有坑,需最后还是用接口拼接的链接。

...还有很多要写的,但是今天太晚了...

最后发现360安全浏览器可以满足要求。
最终得到的pdf清晰度很好。
暂时写到这里,有空再补充,毕竟踩了很多坑。
————2019/08/19 15:40————
(手机码字ing,有些没记住)

起因

一个朋友截图谷歌搜索Storytown pdf,说想要这个书的电子版,不过谷歌到的只有一点残缺的pdf,没有完整的,当然亚马逊是有卖的←_←
不过呢,最后还是在(rasd)上面找到了,不过这个网站像是套了一层,实际来源是thinkcentral,不过thinkcentral这个网站得有账号,普通用户注册不了。这不重要,反正目前这个网站能在线看书,准确说是一个互动式的学习,但它是基于swf的。

怎么弄下来呢?

F12一看,分页是单独的swf,那可以把swf下载来了然后反编译提取图片即可!
下载了一个swf,用FFDec反编译,有一个frame就是一个单页:
FFDec查看swf文件.png
导出为png,打开一看清晰度还可以(那后面拼图做成pdf就好了,心想……)。
————2019/08/19 16:50————
那快速自动化的流程就是下载swf,反编译,导出图片,按顺序合成……然后我试着用python来做反编译这个事情,幸运的是网络上有一个可参考的例子,通过一个库(pyswf),能解析swf的结构,解压资源。不过我发现对于我来说有点复杂了,等我把swf解压这步理解清楚就不知道何年何月了。。然后又找到一个工具swftools,不过它是各种转为swf,而不是swf转回。不过呢它在某个情况下可以复原pdf,然而!它是基于python2的(???)。遂放弃反编译swf←_←
接着我想找现成工具解压swf内资源,然后我再合成图片,反编译的swf内文字部分其实是可以拿到文本的,不过它是位图,背景是另一个图(其实还是卡在解压资源),提这个是因为我想在pdf能复制到文本。
我还是图样图森破。
另外在打开单个swf的时候,通过放大可以发现很清晰,所以位图没错了。
接着,就是在放大的时候,右键的打印选项提醒了我,于是打印了单页的swf,发现质量非常好,清晰度也棒!终于到正题了,那我可以打印得到单页pdf,最后合成。
话不多说开始做,通过搜索,可以知道打印这个操作是可以用python通过selenium库办到的(面向google写代码)。
这里引出了几个问题:

  • 一是单个swf打开会缺少一些东西,比如播放音频的按钮,部分单词选中颜色效果以及一些动画效果,因为这些是外部嵌套的swf完成的,好在需要的是书,这些部分可有可无(不过呢,音频的位置好像在一个接口里面有,有精力的话倒是可以试试把音频内容也添加到pdf里面,pdf应该是支持音频的)。
  • 二是谷歌浏览器对swf不友好,链接以swf结尾会背直接下载文件,而我需要的是网页加载完毕的效果后打印,解决方法是写一个HTML文件,里面引用swf的链接,打开HTML文件后会加载。不过得手动允许flash才能加载,好在网上说能修改注册表让chrome默认允许flash,但我尝试用selenium控制chrome,没有成功,最终放弃。

我打开flash链接看加载效果是用的360极速浏览器,360极速内核还是基于chrome(的开源版本?)然后想应该也能用selenium操作,搜了下貌似真的可以。不过在我N次尝试后,发现并不能,遂改用网络教程中的360安全浏览器,果然成了!关键的打印swf一步解决了。

最开始看了下swf的链接还是有规律组成的,就手动跳到最后几页观察了一下,然后就开始跑代码了,最开始一切正常。
后来出现chapter首字母在第一章后变成大写……
后来出现数字四位补0……
后来出现新章节处有a/b这样的附加字符……
后来发现自己的代码逻辑有问题……
于是乎,改用从接口获取拼接的后部分,这才稳定了下来!

打印的时候有个小插曲,就是selenium控制不能自定义打印保存目录(下载目录可以),不能自定义打印文件名,只好通过浏览器自动保存的名字匹配,然后重命名,移动到保存目录。。

最终,完成(pdf合并过程略……)。

————2019/08/19 23:10————
部分相关代码:

  • 多个pdf合并为一个pdf文件,正则是匹配页数,按页数排序添加,避免顺序错误。另外merger增加的时候,似乎有数量限制,具体多少不知道,大概在300-450之间吧,所以待合并的pdf文件数量太多则需要多次合并。
import os
import re
from PyPDF2 import PdfFileReader, PdfFileMerger
main_text = [f for f in os.listdir() if 'pdf' in f]
fl=sorted(main_text,key=lambda x:int(re.findall(".*?Page(\d+).pdf",x)[0]))
all_files = list()
all_files.extend(fl)
merger = PdfFileMerger()
_ = [merger.append(PdfFileReader(f), 'rb') for f in all_files]
merger.write('output.pdf')
  • 从pages.xml接口中提取swf待拼接的第二部分,其中89是swf_l长度除以10向上取整的值,为啥有这个呢,因为用的vscode,当时直接想着把这个写在py文件里面,然后拼链接,然而vscode不能一行直接粘贴太长的内容。然后换行打印一下swf_ten即可。
import re
import requests
u = "https://www-k6.thinkcentral.com/content/hsp/reading/storytown/na/gr6/esen_9780153597787_/assets/xml-bin/chapter{}/pages.xml"
swf_l = []
for c in range(31):
    r = requests.get(u.format(c)).content.decode("latin-1")
    swf_l += re.findall("<url>(.+?\.swf)</url>",r)
swf_ten = []
for i in range(89):
    swf_ten.append(swf_l[i*10:(i+1)*10])

其他细节就不再贴出来了(太渣渣)。
最后来两张成品效果图吧!
缩小.png
放大.png

标签:none

最后编辑于:2019/08/19 15:39

添加新评论