今天到图书馆找本电机与控制系统的书,刚好图书馆提供了这本书的电子版。华工的馆藏电子书提供全文浏览、截图以及最多4页的打印(pdf)。你想一下子下载整本pdf电子书那是没门的。要想离线查看整本电子书,要么每4页下载一次,要么每页另存jpg,都是糟心的事。所以可以写个小程序,把整本书‘下载’下来。


方案选择

华工图书馆不需要登录,就可以查询书籍,在书籍介绍页可以点进去相应的馆藏电子书。电子书是逐页jpg的方式展示的,静态资源,替换url最后的页码数就可以跳转到相应页。所以,不需要考虑header、cookies等问题,直接访问对应jpg链接就可以下载到图片了。

程序清单

urllib标准库

# -*- coding: utf-8 -*-
import urllib
import urllib.request

class BookSpider:
    def __init__(self, bookURL, maxPage):
        self.bookURL = bookURL
        self.maxPage = maxPage
       
    def saveImg(self, pageNum,):
        imageURL = self.bookURL + r'&jid=/' + pageNum + r'.jpg&uf=ssr&zoom=0'
        u = urllib.request.urlopen(imageURL)
        data = u.read()
        f = open(pageNum + r'.jpg', 'wb')
        f.write(data)
        f.close()

    def loopSave(self):
        for n in range(1, self.maxPage+1):
            page = str(n).zfill(6)
            self.saveImg(page)
            #print(u'downloaded page %s' %page)

ec = BookSpider(r'http://202.38.232.20:8082/ss2jpg/ss2jpg.dll?did=a174&pid=2DF5922217715AAA7194BE7264BDED42059E8618EA5CFD1A7E4BD18652C0391E7B18FFFD83E68133094731F6088194B1DF33DC977271054AA7FB7926820C31E75214D342ADA63F5B95DA71EC3C6ED99A5B889ED2BCF72DE703653FB223A79E602284CC952E7C2806AE7612D2907FB552030D', 358)
ec.loopSave()

程序比较简单,注释就懒得写了。创建BookSpider类的时候提供两个参数,string类型的馆藏电子书的内容页链接的倒数第一个&号前面部分链接和int类型的页码数,然后执行loopSave()就可以了。
经测试,下载360页(80+M)的jpg,花了两分多钟(校园网网速还行)。

程序改进

上面程序执行是没问题,但是上面只是下载正文页jpg的。但是华工馆藏电子书是分封面页、书名页、版权页、前言页、目录页、正文页、附录页分别编页码的,对应链接也是分别编码。所以构造一个字典,储存不同类型页的链接。而且用条件打断配合while循环来判断是否到最后一页,不用自己输入页码数。What's more, 你可以自定义命名前缀。

# -*- coding: utf-8 -*-
# BookSpider_all.py
import urllib
import urllib.request

class BookSpider:
    #书籍图片类型,包括封面页、书名页、版权页、前言页、目录页、正文页、附录页
    #字典的value为[匹配链接,jpg命名前缀,页码位数]
    imageType = {'cover':[r'&jid=/', 'cov', 3],
                 'bookname':[r'&jid=/bok', 'bok', 3],
                 'copyright':[r'&jid=/leg', 'leg', 3],
                 'foreword':[r'&jid=/fow', 'fow', 3],
                 'content':[r'&jid=/!', '!', 5],
                 'text':[r'&jid=/','', 6],
                 'appendix':[r'&jid=/att', 'att', 3]}
  
    def __init__(self, bookURL):
        self.bookURL = bookURL
       
    def saveImg(self, img):
        #循环访问图片链接
        n = 1;
        while True:
            pageNum = str(n).zfill(int(img[2]))
            imageURL = self.bookURL + img[0] + pageNum + r'.jpg&uf=ssr&zoom=0'
            u = urllib.request.urlopen(imageURL)
            data = u.read()
            #当访问到一个空链接时依旧返回142字节的数据,通过判断byte大小来判断是否到页码尽头
            if len(data) <= 142:
                break
            f = open(img[1] + pageNum + r'.jpg', 'wb')
            f.write(data)
            f.close()
            print(u'downloaded page %s' %pageNum)
            n += 1

    def loopSave(self):
        for item in self.imageType:
            self.saveImg(self.imageType[item])

#你可以在下面括号内的''里面填入馆藏电子书的内容页的链接的倒数第一个&号前面部分链接
ec = BookSpider(r'http://202.38.232.20:8082/ss2jpg/ss2jpg.dll?did=a174&pid=2DF5922217715AAA7194BE7264BDED42059E8618EA5CFD1A7E4BD18652C0391E7B18FFFD83E68133094731F6088194B1DF33DC977271054AA7FB7926820C31E75214D342ADA63F5B95DA71EC3C6ED99A5B889ED2BCF72DE703653FB223A79E602284CC952E7C2806AE7612D2907FB552030D')
ec.loopSave()

jpg2pdf

下回来都是按照页码顺序命名的jpg,要转成pdf电子书可以用pdf编辑器。我用的是Nitro 9 Pro(强烈推荐,超级好用pdf阅读编辑器)。

注:.jpg文件存储在.py文件的相同文件下,所以不要把.py放在桌面上执行。