python爬虫下载文件知识点总结

贴代码先:

#!/usr/bin/env python                               #知识点1
# -*- coding: UTF-8 -*-

import requests
import os
import time

#写日志
def write_log(full_path, file_name,status_code):
    if status_code == 1 :
        note = '开始下载文件:' + file_name + '\n保存地址:' + full_path + '\n等待服务器响应,这需要几十秒............\n请求服务器:成功\n正在下载文件,请稍等.......' + '\n文件:' + file_name + ' 已下载完成\n'+'时间:'+time.strftime("%Y/%m/%d/ %H:%M:%S")+'\n========================Done=========================\n'
        open(full_path + 'log.txt', 'a').write(note + '\n')
    else:
        note = '开始下载文件:' + file_name + '\n保存地址:' + full_path + '\n等待服务器响应,这需要几十秒............\n请求服务器:失败\n请确认日期是否在数据库范围' + '\n请在另外一个命令行启动脚本下载 ' + file_name + ' 文件'+'\n时间:'+time.strftime("%Y/%m/%d/ %H:%M:%S")+'\n========================Done=========================\n'
        open(full_path + 'log.txt', 'a').write(note + '\n')



#判断是否继续下一次下载
def whether_start():

    while 1:
        if_continue = input('上一个任务已经完成,是否继续下载  【y/n】')
        if if_continue == 'y':
            if_continue = True
            break
        elif if_continue == 'n':
            if_continue = False
            break
        else:
            print('输入有误请重新确认')
            continue
    return if_continue


#生成目录
def get_dir(start_month):
    son_path = '2018-' + str(start_month).zfill(2) + '\\'       #知识点2  指定长度的字符串前面填充0。
    if not os.path.exists(father_path+son_path):
        os.makedirs(father_path+son_path)                        #知识点3   递归创建目录
    else:
        pass
    return father_path+son_path


#下载文件
def download(url,path,file_name,full_path):
    # url = 'http://pifsc-oceanwatch.irc.noaa.gov/erddap/griddap/OceanWatch_goes-poes_sst_2day.htmlTable?sst[(2018-01-10T00:00:00Z):1:(2018-01-10T00:00:00Z)][(-1):1:(43)][(146):1:(336)]'
    requ = requests.get(url, stream=True)                      #知识点4  网页请求 大文件下载
    if requ.status_code == 200:
        status_code = 1
        note = '请求服务器:成功'
        print(note)
        note = '正在下载文件,请稍等.......'
        print(note)

        f = open(path, "wb")
        for chunk in requ.iter_content(chunk_size=1024):
            if chunk:
                f.write(chunk)
                f.flush()

        # iter_content:一块一块的遍历要下载的内容
        # iter_lines:一行一行的遍历要下载的内容
        # 这两个函数下载大文件可以防止占用过多的内存,因为每次只下载小部分数据
        # end = time.time()
        # print('Finish in :', end - whether_start)
        note = '文件:' + file_name + ' 已下载完成'
        print(note)
        print('时间:' + time.strftime("%Y/%m/%d/ %H:%M:%S"))
    else:
        status_code = 0
        note = '请求服务器:失败\n请确认日期是否在数据库范围\n'+'请求服务器:失败\n请确认日期是否在数据库范围'
        print(note)
        note = '请在另外一个命令行启动脚本下载 '+file_name+'文件'
        print(note)
        print('时间' + time.strftime("%Y/%m/%d/ %H:%M:%S"))
    write_log(full_path, file_name, status_code)

#主功能
def get_file():

    print('=============================开始执行脚本=============================')

    sign = 1
    while sign :
        try:
            start_month = int(input('请输入开始月份:'))
            start_date = int(input('请输入开始日期:'))
            end_date = int(input('请输入结束日期:'))
            if type(start_month) == int and type(start_date) == int and type(end_date) == int:  #知识点5 if的简化
                break

        except ValueError:                                           #知识点6   打印异常信息
            print('输入数值有误,请重新输入,请输入数字\n')




    full_path = get_dir(start_month) #full_path 是不包括文件名的路径

    for page_num in range(start_date, end_date+1):
        url = 'http://pifsc-oceanwatch.irc.noaa.gov/erddap/griddap/OceanWatch_goes-poes_sst_2day.nc?sst[(2018-{}-{}T00:00:00Z):1:(2018-{}-{}T00:00:00Z)][(-90.0):1:(89.95)][(0.0):1:(359.95)]'.format(str(start_month).zfill(2),
            str(start_date ).zfill(2), str(start_month).zfill(2),str(start_date).zfill(2))
        start_date += 1
        file_name = url[-59:-49] + '.nc'
        path = full_path + file_name  # path是包含文件名的路径
        note = '开始下载文件:' + file_name
        print(note)
        note = '保存地址:' + full_path + file_name
        print(note)
        print('下载链接:' + url)
        print('等待服务器响应,这需要几十秒............')


        download(url, path,file_name,full_path)


        note = '========================Done=========================\n'
        print(note)

    return whether_start()


if __name__ == '__main__':
    father_path = 'E:\\Panoply_data\\'
    if_continue = 1
    while if_continue:
        if_continue = get_file()


#知识点1

 #!/usr/bin/env python

这个在unix类的操作系统才有意义。
#!/usr/bin/python是告诉操作系统执行这个脚本的时候,调用/usr/bin下的python解释器;
#!/usr/bin/env python这种用法是为了防止操作系统用户没有将python装在默认的/usr/bin路径里。当系统看到这一行的时候,首先会到env设置里查找python的安装路径,再调用对应路径下的解释器程序完成操作。


#知识点2   

 str(start_month).zfill(2)  中  zfill()方法

Python zfill() 方法返回指定长度的字符串,原字符串右对齐,前面填充0。

str.zfill(width)

width -- 指定字符串的长度。原字符串右对齐,前面填充0。

#!/usr/bin/python

str = "this is string example....wow!!!";

print str.zfill(40);
print str.zfill(50);

结果

00000000this is string example....wow!!!
000000000000000000this is string example....wow!!!

 #知识点3   

os.makedirs(father_path+son_path)   

1.mkdir( path [,mode] )
      作用:创建一个目录,可以是相对或者绝对路径,mode的默认模式是0777。

      如果目录有多级,则创建最后一级。如果最后一级目录的上级目录有不存在的,则会抛出一个OSError。

2.makedirs( path [,mode] )
      作用: 创建递归的目录树,可以是相对或者绝对路径,mode的默认模式也是0777。

      如果子目录创建失败或者已经存在,会抛出一个OSError的异常,Windows上Error 183即为目录已经存在的异常错误。如果path只有一级,与mkdir一样。所以使用时用判断语句判断下目录是否存在,如果存在就pass

if not os.path.exists(father_path+son_path):
        os.makedirs(father_path+son_path)                        #知识点3
    else:
        pass


 #知识点4    

requ = requests.get(url, stream=True)

这个是网络请求的常用模块,如果是网页爬虫,那里面常用可能是

 wb_data  = requests.get(full_url,proxies=proxies,headers=headers)

proxies=proxies里面是代理ip的信息,防止你爬虫的时候人家封你ip

headers=headers里面的是用户代理信息,模仿人家点击访问的操作


在下载大文件的过程中,用到的是stream=Tru参数,当把get函数的stream参数设置成False时,它会立即开始下载文件并放到内存中,如果文件过大,有可能导致内存不足,下载下来的文件会不完整。

iter_content:一块一块的遍历要下载的内容
iter_lines:一行一行的遍历要下载的内容
使用上面两个函数下载大文件可以防止占用过多的内存,因为每次只下载小部分数据。

示例代码:

r = requests.get(url_file, stream=True)
f = open("file_path", "wb")
for chunk in r.iter_content(chunk_size=512):
    if chunk:
        f.write(chunk)
        f.flush()  刷新缓存

#知识点5  

if 结构简化

如果你需要检查几个数值你可以用以下方法:

if n in [1,4,5,6]:
来替代下面这个方式:
if n==1 or n==4 or n==5 or n==6:

所以原文知识点5那个

 if type(start_month) == int and type(start_date) == int and type(end_date) == int:

可以替换成这个

if type(start_month)==type(start_date)==type(end_date):  #知识点5


#知识点6

打印异常信息

异常信息的获取对于程序的调试非常重要,可以有助于快速定位有错误程序语句的位置。
下面介绍几种python中获取异常信息的方法,这里获取异常(Exception)信息采用try...except...程序结构。如下所示

try:
   ...
except Exception as e:

    print(str(e))

1、str(e)
 

返回字符串类型,只给出异常信息,不包括异常信息的类型,如1/0的异常信息

2、repr(e)
 

给出较全的异常信息,包括异常信息的类型,如1/0的异常信息

3 或者except到了后,自定义处理









你可能感兴趣的:(python,爬虫)