从 chinadaily 下载 chinadail 的 pdf papger,chinadailpapger,之前刚开始用 apach


之前刚开始用 apache http 包的时候弄了个 java 版的,用来下载下来后复习一下 e文,后来丢了。最近在学python,就趁机弄了个python版本的,用来练练手。注意:需要python3.2.3(最前最新)或以上的版本,主要是3.2.3以下对 post 后的 redirect 会出现异常,FancyURLopener 倒没有这个问题,但python文档说,FancyURLopener 是遗留资产,将来可能会废弃,所以这里也没有用。

程序代码

# -*- coding: utf-8 -*-'''因为涉及到post的redirect问题,需要python 3.2.3及以上版本'''import configparser;from urllib import request;from urllib import parse;from datetime import date;from datetime import timedelta;from datetime import datetime;import struct;import os;from os import path;def readConfig(confName = 'chinadaily.ini'):    '''    读取配置文件 chinadaily.ini,获取用户名,密码等    @param confName 配置文件的默认文件名    '''    conf = configparser.ConfigParser();    conf.read(confName);    return conf['DEFAULT'];def login(conf):    '''    登录chinadaily    @param conf 配置文件    @return 登录是否成功,不成功时抛出异常    '''    # 登录用户名和密码    loginData = parse.urlencode({'email': conf.get('username'), 'password':conf.get('password')}).encode(conf.get('encoding'));    loginReq = request.Request(conf.get('loginPost'), loginData);    loginedPage = request.urlopen(loginReq);    # TODO:判断是否登录成功    return True;def downADay(conf, targetDate):    '''    下载指定日期的chinadaily pdf 文件    @param conf 配置信息    @param targetDate 要下载的日期    '''    weekday = targetDate.isoweekday();    if weekday == 6 or weekday == 7 :        print('跳过周末');        return;    # 初始化下载目录    saveDir = conf.get('saveDir') + '/' + str(targetDate.year) + str(targetDate.month).zfill(2) + '/';    if not path.exists(saveDir) :        os.makedirs(saveDir, exist_ok = True);    # 生成特定日期的提交数据    postData = parse.urlencode({'year': str(targetDate.year), 'mon': str(targetDate.month).zfill(2), 'day': str(targetDate.day)}).encode(conf.get('encoding'));    # 请求特定日期的下载页面    page = request.urlopen(conf.get('indexUrl'), postData);    pageStr = page.read().decode(conf.get('encoding'));    start = 0     # 查找下载地址并开始下载    downIdx = findDownUrlIdx(pageStr, start);    while downIdx != None :        start = downIdx[0];        urlIdx = downIdx[1];        downIdx = findDownUrlIdx(pageStr, start);        pdf = request.urlopen(conf.get('downUrl') + urlIdx);        fileName = saveDir + '/' + str(targetDate.day).zfill(2) + '-' + urlIdx + '.pdf';        # 检查文件是否已经存在,并且大小相同        if path.exists(fileName) and path.getsize(fileName) == int(pdf.info().get('Accept-Length')) :            print('跳过已经存在的相同大小的文件', fileName);            continue;        print('开始下载', urlIdx, '保存到', fileName);        pdfFile = open(saveDir + '/' + str(targetDate.day).zfill(2) + '-' + urlIdx + '.pdf', 'bw');        pdfFile.write(pdf.read());        pdfFile.close();        # print(pdf.info());def findDownUrlIdx(source, start=0):    '''    从指定的源码中找到下载地址    @param source 页面源码    @param start 开始位置 默认为 0    @return 找到时返回 (结束位置, 下载地址URL ID)的tuple,找不到时返回 None     '''    downStr = '<a href="./download.shtml?c=';    idx = source.find(downStr, start);    if idx >=0 :        end = source.find('"', idx + len(downStr));        return end, source[idx + len(downStr) : end];    return None;def down(startDate = None, endDate = None):    '''    @param startDate 开始日期(包括)    @param endDate 结束日期(不包括)    '''    conf = readConfig();    if(not login(conf)):        print('login failed');    # 获取最后的下载日期,并开始下载最后下载日期到昨天的 chinadaily pdf    saveDir = conf.get('saveDir');    if not path.exists(saveDir) :        os.makedirs(saveDir, exist_ok = True);    logFile = saveDir + '/lastdown';    # 默认下载日期为当月第一天    lastdate = date.today() - timedelta(date.today().day - 1);    if path.exists(logFile) :        # 已经下载过,读取最后的下载日期        log = open(logFile, 'a+');        log.seek(0);        lastdateStr = str(log.read(10));        if len(lastdateStr) >= 10 :            lastdate = datetime.strptime(lastdateStr, '%Y-%m-%d').date();        log.truncate(0);    else:        # 建立新的下载日志文件        log = open(logFile, 'w');    if startDate != None :        lastdate = startDate;    # 依次下载从最后下载日期到结束日期的chinadaily pdf 文件    try:        while lastdate < date.today() if endDate == None else endDate:            downADay(conf, lastdate);            lastdate = lastdate + timedelta(1);    finally:        log.write(lastdate.strftime('%Y-%m-%d'));        log.flush();        log.close();if __name__ == "__main__":    import argparse;    import sys;    parser = argparse.ArgumentParser(description='下载chinadaily的PDF Paper');    parser.add_argument('-s', '--start', metavar='', help='开始日期(包括)');    parser.add_argument('-e', '--end', metavar='', help='结束日期(不包括),默认为今天');    args = parser.parse_args();    startDate = datetime.strptime(args.start, '%Y-%m-%d').date() if args.start != None else None;    endDate = datetime.strptime(args.end, '%Y-%m-%d').date() if args.end != None else None;    down(startDate, endDate);

程序的配置文件

[DEFAULT]loginUrl = http://pub1.chinadaily.com.cn/cdpdf/cndy/login.shtmlindexUrl = http://pub1.chinadaily.com.cn/cdpdf/cndy/index.shtmldownUrl = http://pub1.chinadaily.com.cn/cdpdf/cndy/download.shtml?c=encoding = utf-8loginPost = http://pub1.chinadaily.com.cn/cdpdf/cndy/login.shtml?do=loginsaveDir = d:/data/chinadailyusername = 这里更改为自己的用户名password = 这里更改为自己的密码

评论关闭