关于ftp的文件批量下载(包括文件夹和文件)的多种方法

博主纯手工打字,转载请注明出处!各位大佬不喜勿喷!

先笼统说一下本文针对ftp协议下的文件夹和文件递归下载方法:

(I)使用FileZilla工具进行下载;

(II)使用脚本爬取;

(III)使用命令直接下载;

(IV)python脚本直接下载。

       最近需要下载一批新的固件,本来是准备写脚本爬取的,但是使用scrapy框架爬取的时候,发现并不能有效地支持ftp协议的情况,貌似很好地支持http和https协议的网址。

需要研究和处理内容的网址为:ftp://ftp2.dlink.com/

(1)通过向大佬同学东神咨询和学习后,得知存在一些下载工具或者使用命令准们针对ftp协议的文件传输下载会更好。

在windows和linux或者os系统下,一个很好的图形界面工具是FileZilla,能够很好地支持文件夹和文件的递归下载:

必要的时候需要输入用户名和密码。对于这个ftp服务器,暂时还是不需要的。

关于ftp的文件批量下载(包括文件夹和文件)的多种方法_第1张图片

(2)然而使用scrapy框架爬取,只是针对网页内容的爬取比较好。当然也存在一些扩展插件,支持ftp的爬取。如下面这个博客里面就提供了一个很好的使用案例和方法。

参考链接:https://www.xuebuyuan.com/322048.html

#! -*- encoding:utf-8 -*-
#file is 'ftp.py', sys.path:'src.middleware.ftp.FtpDownloadHandler'

__author__ = 'C.L.TANG'
import urllib2
from scrapy.http import Response


class FtpDownloadHandler(object):

    def download_request(self, request, spider):
        """Return a deferred for the HTTP download"""
        handler = urllib2.FTPHandler()
        req = urllib2.Request(url = request.url)
        opener = urllib2.build_opener(handler)
        f = opener.open(req)
        b = f.read()
        print len(b)
        respcls = Response(url = request.url, body=b, request = request)
        return respcls

##然后在自己项目的settings.py文件中指定:

DOWNLOAD_HANDLERS = {'ftp' :  'src.middleware.ftp.FtpDownloadHandler'}
##在爬虫类中有:

#! -*- encoding:utf-8 -*-
from scrapy.selector import HtmlXPathSelector
from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor
from scrapy.contrib.spiders import CrawlSpider, Rule
from scrapy.http import Request


class ShopSpider(CrawlSpider):
    name = '958shop'
    allowed_domains = ['958shop.com']

    def start_requests(self):
        request = Request(url = 'ftp://b9:[email protected]/2011/11/15/52076863815926.jar')
        request.callback = self.down_debug_html
        return [request,]

    def down_debug_html(self, response):
        #在这里调用存入下载链接地址的方法.
        #file_name =  response.meta['file_name']
        print response.url
        filename = 'debug.html'
        open(filename, 'wb').write(response.body)

针对上面的这个方法,本博主还没有着手实现。有志者可以着手试试!顺便写个留言博客地址让我膜拜一下。

(3)关于使用命令于是就各种百度查找,使用命令都需要知道ftp服务器的用户名和密码,但是我一脸懵逼,因为我现在只知道对应的ftp地址,哪里知道什么用户名和密码。这就很气了!

于是就使用wireshark进行抓包分析和观望,得到了用户名和密码:

username = anonymous, [email protected]

但是第二次我再次抓包的时候,发现登录的密码已经变成了mozilla@example,我尝试把密码改为这个进行测试的时候,结果显示也是能够直接获取数据的。然后我就猜测匿名登录的时候密码为空的时候,于是我就测试一下发现的确密码为空的时候是可以登录,所以验证密码为任意。

关于ftp的文件批量下载(包括文件夹和文件)的多种方法_第2张图片

于是我又大胆地猜测如果用户名也为空的话,是不是能通过?于是我就把用户名和密码都置为空,但是好像无法登陆!

关于ftp的文件批量下载(包括文件夹和文件)的多种方法_第3张图片

于是我又猜测,是不是只用用户名不为空就可以呢?我就把用户名改为不是anonymous这个内容,结果报错了:

关于ftp的文件批量下载(包括文件夹和文件)的多种方法_第4张图片

在得知这些用户明和密码之后就能够很好地使用命令了。参考链接https://blog.csdn.net/junqing124/article/details/51558197

就构造了下面这条链接,但是并非那么地好用,因为下载速度很是慢啊。

wget -r -nH -P ./ ftp://ftp2.dlink.com/PRODUCTS/* --f --ftp-user=anonymous [email protected]

在接下来本博主准备写一个脚本处理问价,下载文件内容,猜测应该会好用很多。

(4)python脚本下载

本博主写的python下载内容是参考这个的,由于项目内容,暂时不便放出来。需要的同学参考这个自己写一个吧。

# -*- encoding: utf8 -*-
import os
import sys
import ftplib 
sys.setdefaultencoding('gbk')
XFER_FILE = 'FILE'  
_XFER_DIR = 'DIR'  
class FTPSync(object):
    def __init__(self):
        self.conn = ftplib.FTP('192.168.8.5', 'tools', 'tools')
        self.conn.cwd('/meteor')        # 远端FTP目录
        os.chdir('./aa')        # 本地下载目录
    def get_dirs_files(self):
        u''' 得到当前目录和文件, 放入dir_res列表 '''
        dir_res = []
        self.conn.dir('.', dir_res.append)
        files = [f.split(None, 8)[-1] for f in dir_res if f.startswith('-')]
        dirs = [f.split(None, 8)[-1] for f in dir_res if f.startswith('d')]
        return (files, dirs)
    def walk(self, next_dir):
        print 'Walking to', next_dir
        self.conn.cwd(next_dir)
        try:
            os.mkdir(next_dir)
        except OSError:
            pass
        os.chdir(next_dir)
        ftp_curr_dir = self.conn.pwd()
        local_curr_dir = os.getcwd()
        files, dirs = self.get_dirs_files()
        print "FILES: ", files
        print "DIRS: ", dirs
        for f in files:
            print next_dir, ':', f
            outf = open(f, 'wb')
            try:
                self.conn.retrbinary('RETR %s' % f, outf.write)
            finally:
                outf.close()
        for d in dirs:
            os.chdir(local_curr_dir)
            self.conn.cwd(ftp_curr_dir)
            self.walk(d)
    def run(self):
        self.walk('.')
def main():
    f = FTPSync()
    # f.run()
if __name__ == '__main__':
    main()
 
 
class Xfer(object):  
    ''''' 
    @note: upload local file or dirs recursively to ftp server 
    '''  
    def __init__(self):  
        self.ftp = None  
      
    def __del__(self):  
        pass  
      
    def setFtpParams(self, ip, uname, pwd, port = 21, timeout = 60):          
        self.ip = ip  
        self.uname = uname  
        self.pwd = pwd  
        self.port = port  
        self.timeout = timeout  
      
    def initEnv(self):  
        if self.ftp is None:  
            self.ftp = ftplib.FTP()  
            print '### connect ftp server: %s ...'%self.ip  
            self.ftp.connect(self.ip, self.port, self.timeout)  
            self.ftp.login(self.uname, self.pwd)   
            print self.ftp.getwelcome()  
      
    def clearEnv(self):  
        if self.ftp:  
            self.ftp.close()  
            print '### disconnect ftp server: %s!'%self.ip   
            self.ftp = None  
      
    def uploadDir(self, localdir='./', remotedir='./'):  
        if not os.path.isdir(localdir):    
            return  
        self.ftp.cwd(remotedir)   
        for file in os.listdir(localdir):  
            src = os.path.join(localdir, file)  
            if os.path.isfile(src):  
                self.uploadFile(src, file)  
            elif os.path.isdir(src):  
                try:    
                    self.ftp.mkd(file)    
                except:    
                    sys.stderr.write('the dir is exists %s'%file)  
                self.uploadDir(src, file)  
        self.ftp.cwd('..')  
      
    def uploadFile(self, localpath, remotepath='~/test'):  
        if not os.path.isfile(localpath):    
            return  
        print '+++ upload %s to %s:%s'%(localpath, self.ip, remotepath)  
        self.ftp.storbinary('STOR ' + remotepath, open(localpath, 'rb'))  
      
    def __filetype(self, src):  
        if os.path.isfile(src):  
            index = src.rfind('\\')  
            if index == -1:  
                index = src.rfind('/')                  
            return _XFER_FILE, src[index+1:]  
        elif os.path.isdir(src):  
            return _XFER_DIR, ''          
      
    def upload(self, src):  
        filetype, filename = self.__filetype(src)  
          
        self.initEnv()  
        if filetype == _XFER_DIR:  
            self.srcDir = src              
            self.uploadDir(self.srcDir)  
        elif filetype == _XFER_FILE:  
            self.uploadFile(src, filename)  
        self.clearEnv()   
                 
  
if __name__ == '__main__':  
    srcDir = r"/Users/meteor/Desktop/gitlab/aa"  
# srcFile = r'C:\sytst\sar.c'  
    xfer = Xfer()  
    xfer.setFtpParams('192.168.8.5', 'tools', 'tools')  
    xfer.upload(srcDir)      
    xfer.upload(srcFile)  

参考链接:

https://blog.csdn.net/osmeteor/article/details/53812057

https://blog.csdn.net/u010412833/article/details/73649274?locationNum=7&fps=1

http://blog.chinaunix.net/uid-21516619-id-1825037.html

你可能感兴趣的:(爬虫开发学习,python学习)