當前位置:首頁 » 文件傳輸 » python爬ftp
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

python爬ftp

發布時間: 2022-06-08 21:52:41

A. 如何用Python做爬蟲

在我們日常上網瀏覽網頁的時候,經常會看到一些好看的圖片,我們就希望把這些圖片保存下載,或者用戶用來做桌面壁紙,或者用來做設計的素材。

我們最常規的做法就是通過滑鼠右鍵,選擇另存為。但有些圖片滑鼠右鍵的時候並沒有另存為選項,還有辦法就通過就是通過截圖工具截取下來,但這樣就降低圖片的清晰度。好吧其實你很厲害的,右鍵查看頁面源代碼。

我們可以通過python來實現這樣一個簡單的爬蟲功能,把我們想要的代碼爬取到本地。下面就看看如何使用python來實現這樣一個功能。

B. 如何用Python做爬蟲

1)首先你要明白爬蟲怎樣工作。

想像你是一隻蜘蛛,現在你被放到了互聯「網」上。那麼,你需要把所有的網頁都看一遍。怎麼辦呢?沒問題呀,你就隨便從某個地方開始,比如說人民日報的首頁,這個叫initial pages,用$表示吧。

在人民日報的首頁,你看到那個頁面引向的各種鏈接。於是你很開心地從爬到了「國內新聞」那個頁面。太好了,這樣你就已經爬完了倆頁面(首頁和國內新聞)!暫且不用管爬下來的頁面怎麼處理的,你就想像你把這個頁面完完整整抄成了個html放到了你身上。

突然你發現, 在國內新聞這個頁面上,有一個鏈接鏈回「首頁」。作為一隻聰明的蜘蛛,你肯定知道你不用爬回去的吧,因為你已經看過了啊。所以,你需要用你的腦子,存下你已經看過的頁面地址。這樣,每次看到一個可能需要爬的新鏈接,你就先查查你腦子里是不是已經去過這個頁面地址。如果去過,那就別去了。

好的,理論上如果所有的頁面可以從initial page達到的話,那麼可以證明你一定可以爬完所有的網頁。

那麼在python里怎麼實現呢?
很簡單

import Queue

initial_page = "初始化頁"

url_queue = Queue.Queue()
seen = set()

seen.insert(initial_page)
url_queue.put(initial_page)

while(True): #一直進行直到海枯石爛
if url_queue.size()>0:
current_url = url_queue.get() #拿出隊例中第一個的url
store(current_url) #把這個url代表的網頁存儲
for next_url in extract_urls(current_url): #提取把這個url里鏈向的url
if next_url not in seen:
seen.put(next_url)
url_queue.put(next_url)
else:
break

寫得已經很偽代碼了。

所有的爬蟲的backbone都在這里,下面分析一下為什麼爬蟲事實上是個非常復雜的東西——搜索引擎公司通常有一整個團隊來維護和開發。

2)效率
如果你直接加工一下上面的代碼直接運行的話,你需要一整年才能爬下整個豆瓣的內容。更別說Google這樣的搜索引擎需要爬下全網的內容了。

問題出在哪呢?需要爬的網頁實在太多太多了,而上面的代碼太慢太慢了。設想全網有N個網站,那麼分析一下判重的復雜度就是N*log(N),因為所有網頁要遍歷一次,而每次判重用set的話需要log(N)的復雜度。OK,OK,我知道python的set實現是hash——不過這樣還是太慢了,至少內存使用效率不高。

通常的判重做法是怎樣呢?Bloom Filter. 簡單講它仍然是一種hash的方法,但是它的特點是,它可以使用固定的內存(不隨url的數量而增長)以O(1)的效率判定url是否已經在set中。可惜天下沒有白吃的午餐,它的唯一問題在於,如果這個url不在set中,BF可以100%確定這個url沒有看過。但是如果這個url在set中,它會告訴你:這個url應該已經出現過,不過我有2%的不確定性。注意這里的不確定性在你分配的內存足夠大的時候,可以變得很小很少。一個簡單的教程:Bloom Filters by Example

注意到這個特點,url如果被看過,那麼可能以小概率重復看一看(沒關系,多看看不會累死)。但是如果沒被看過,一定會被看一下(這個很重要,不然我們就要漏掉一些網頁了!)。 [IMPORTANT: 此段有問題,請暫時略過]

好,現在已經接近處理判重最快的方法了。另外一個瓶頸——你只有一台機器。不管你的帶寬有多大,只要你的機器下載網頁的速度是瓶頸的話,那麼你只有加快這個速度。用一台機子不夠的話——用很多台吧!當然,我們假設每台機子都已經進了最大的效率——使用多線程(python的話,多進程吧)。

3)集群化抓取
爬取豆瓣的時候,我總共用了100多台機器晝夜不停地運行了一個月。想像如果只用一台機子你就得運行100個月了...

那麼,假設你現在有100台機器可以用,怎麼用python實現一個分布式的爬取演算法呢?

我們把這100台中的99台運算能力較小的機器叫作slave,另外一台較大的機器叫作master,那麼回顧上面代碼中的url_queue,如果我們能把這個queue放到這台master機器上,所有的slave都可以通過網路跟master聯通,每當一個slave完成下載一個網頁,就向master請求一個新的網頁來抓取。而每次slave新抓到一個網頁,就把這個網頁上所有的鏈接送到master的queue里去。同樣,bloom filter也放到master上,但是現在master只發送確定沒有被訪問過的url給slave。Bloom Filter放到master的內存里,而被訪問過的url放到運行在master上的Redis里,這樣保證所有操作都是O(1)。(至少平攤是O(1),Redis的訪問效率見:LINSERT – Redis)

考慮如何用python實現:
在各台slave上裝好scrapy,那麼各台機子就變成了一台有抓取能力的slave,在master上裝好Redis和rq用作分布式隊列。

代碼於是寫成

#slave.py

current_url = request_from_master()
to_send = []
for next_url in extract_urls(current_url):
to_send.append(next_url)

store(current_url);
send_to_master(to_send)

#master.py
distributed_queue = DistributedQueue()
bf = BloomFilter()

initial_pages = "www.renmingribao.com"

while(True):
if request == 'GET':
if distributed_queue.size()>0:
send(distributed_queue.get())
else:
break
elif request == 'POST':
bf.put(request.url)

好的,其實你能想到,有人已經給你寫好了你需要的:darkrho/scrapy-redis · GitHub

4)展望及後處理
雖然上面用很多「簡單」,但是真正要實現一個商業規模可用的爬蟲並不是一件容易的事。上面的代碼用來爬一個整體的網站幾乎沒有太大的問題。

但是如果附加上你需要這些後續處理,比如

有效地存儲(資料庫應該怎樣安排)

有效地判重(這里指網頁判重,咱可不想把人民日報和抄襲它的大民日報都爬一遍)

有效地信息抽取(比如怎麼樣抽取出網頁上所有的地址抽取出來,「朝陽區奮進路中華道」),搜索引擎通常不需要存儲所有的信息,比如圖片我存來幹嘛...

及時更新(預測這個網頁多久會更新一次)

如你所想,這里每一個點都可以供很多研究者十數年的研究。雖然如此,
「路漫漫其修遠兮,吾將上下而求索」。

所以,不要問怎麼入門,直接上路就好了:)

C. Python中如何獲取FTP伺服器上的文件大小

這要看你下載用了哪個ftp庫
搜到的代碼

files = ftp.nlst()
for f in files:
print f

D. 用python寫測試腳本,從本地傳文件至ftp遠程路徑

轉自:http://news.tuxi.com.cn/kf/article/jhtdj.htm

本文實例講述了python實現支持目錄FTP上傳下載文件的方法。分享給大家供大家參考。具體如下:

該程序支持ftp上傳下載文件和目錄、適用於windows和linux平台。

#!/usr/bin/envpython
#-*-coding:utf-8-*-
importftplib
importos
importsys
classFTPSync(object):
conn=ftplib.FTP()
def__init__(self,host,port=21):
self.conn.connect(host,port)
deflogin(self,username,password):
self.conn.login(username,password)
self.conn.set_pasv(False)
printself.conn.welcome
deftest(self,ftp_path):
printftp_path
printself._is_ftp_dir(ftp_path)
#printself.conn.nlst(ftp_path)
#self.conn.retrlines('LIST./a/b')
#ftp_parent_path=os.path.dirname(ftp_path)
#ftp_dir_name=os.path.basename(ftp_path)
#printftp_parent_path
#printftp_dir_name
def_is_ftp_file(self,ftp_path):
try:
ifftp_pathinself.conn.nlst(os.path.dirname(ftp_path)):
returnTrue
else:
returnFalse
exceptftplib.error_perm,e:
returnFalse
def_ftp_list(self,line):
list=line.split('')
ifself.ftp_dir_name==list[-1]andlist[0].startswith('d'):
self._is_dir=True
def_is_ftp_dir(self,ftp_path):
ftp_path=ftp_path.rstrip('/')
ftp_parent_path=os.path.dirname(ftp_path)
self.ftp_dir_name=os.path.basename(ftp_path)
self._is_dir=False
ifftp_path=='.'orftp_path=='./'orftp_path=='':
self._is_dir=True
else:
#thisuescallbackfunction,thatwillchange_is_dirvalue
try:
self.conn.retrlines('LIST%s'%ftp_parent_path,self._ftp_list)
exceptftplib.error_perm,e:
returnself._is_dir
returnself._is_dir
defget_file(self,ftp_path,local_path='.'):
ftp_path=ftp_path.rstrip('/')
ifself._is_ftp_file(ftp_path):
file_name=os.path.basename(ftp_path)
#如果本地路徑是目錄,下載文件到該目錄
ifos.path.isdir(local_path):
file_handler=open(os.path.join(local_path,file_name),'wb')
self.conn.retrbinary("RETR%s"%(ftp_path),file_handler.write)
file_handler.close()
#如果本地路徑不是目錄,但上層目錄存在,則按照本地路徑的文件名作為下載的文件名稱
elifos.path.isdir(os.path.dirname(local_path)):
file_handler=open(local_path,'wb')
self.conn.retrbinary("RETR%s"%(ftp_path),file_handler.write)
file_handler.close()
#如果本地路徑不是目錄,且上層目錄不存在,則退出
else:
print'EROOR:Thedir:%sisnotexist'%os.path.dirname(local_path)
else:
print'EROOR:Theftpfile:%sisnotexist'%ftp_path
defput_file(self,local_path,ftp_path='.'):
ftp_path=ftp_path.rstrip('/')
ifos.path.isfile(local_path):
file_handler=open(local_path,"r")
local_file_name=os.path.basename(local_path)
#如果遠程路徑是個目錄,則上傳文件到這個目錄,文件名不變
ifself._is_ftp_dir(ftp_path):
self.conn.storbinary('STOR%s'%os.path.join(ftp_path,local_file_name),file_handler)
#如果遠程路徑的上層是個目錄,則上傳文件,文件名按照給定命名
elifself._is_ftp_dir(os.path.dirname(ftp_path)):
print'STOR%s'%ftp_path
self.conn.storbinary('STOR%s'%ftp_path,file_handler)
#如果遠程路徑不是目錄,且上一層的目錄也不存在,則提示給定遠程路徑錯誤
else:
print'EROOR:Theftppath:%siserror'%ftp_path
file_handler.close()
else:
print'ERROR:Thefile:%sisnotexist'%local_path
defget_dir(self,ftp_path,local_path='.',begin=True):
ftp_path=ftp_path.rstrip('/')
#當ftp目錄存在時下載
ifself._is_ftp_dir(ftp_path):
#如果下載到本地當前目錄下,並創建目錄
#下載初始化:如果給定的本地路徑不存在需要創建,同時將ftp的目錄存放在給定的本地目錄下。
#ftp目錄下文件存放的路徑為local_path=local_path+os.path.basename(ftp_path)
#例如:將ftp文件夾a下載到本地的a/b目錄下,則ftp的a目錄下的文件將下載到本地的a/b/a目錄下
ifbegin:
ifnotos.path.isdir(local_path):
os.makedirs(local_path)
local_path=os.path.join(local_path,os.path.basename(ftp_path))
#如果本地目錄不存在,則創建目錄
ifnotos.path.isdir(local_path):
os.makedirs(local_path)
#進入ftp目錄,開始遞歸查詢
self.conn.cwd(ftp_path)
ftp_files=self.conn.nlst()
forfileinftp_files:
local_file=os.path.join(local_path,file)
#如果fileftp路徑是目錄則遞歸上傳目錄(不需要再進行初始化begin的標志修改為False)
#如果fileftp路徑是文件則直接上傳文件
ifself._is_ftp_dir(file):
self.get_dir(file,local_file,False)
else:
self.get_file(file,local_file)
#如果當前ftp目錄文件已經遍歷完畢返回上一層目錄
self.conn.cwd("..")
return
else:
print'ERROR:Thedir:%sisnotexist'%ftp_path
return

defput_dir(self,local_path,ftp_path='.',begin=True):
ftp_path=ftp_path.rstrip('/')
#當本地目錄存在時上傳
ifos.path.isdir(local_path):
#上傳初始化:如果給定的ftp路徑不存在需要創建,同時將本地的目錄存放在給定的ftp目錄下。
#本地目錄下文件存放的路徑為ftp_path=ftp_path+os.path.basename(local_path)
#例如:將本地文件夾a上傳到ftp的a/b目錄下,則本地a目錄下的文件將上傳的ftp的a/b/a目錄下
ifbegin:
ifnotself._is_ftp_dir(ftp_path):
self.conn.mkd(ftp_path)
ftp_path=os.path.join(ftp_path,os.path.basename(local_path))
#如果ftp路徑不是目錄,則創建目錄
ifnotself._is_ftp_dir(ftp_path):
self.conn.mkd(ftp_path)

#進入本地目錄,開始遞歸查詢
os.chdir(local_path)
local_files=os.listdir('.')
forfileinlocal_files:
#如果file本地路徑是目錄則遞歸上傳目錄(不需要再進行初始化begin的標志修改為False)
#如果file本地路徑是文件則直接上傳文件
ifos.path.isdir(file):
ftp_path=os.path.join(ftp_path,file)
self.put_dir(file,ftp_path,False)
else:
self.put_file(file,ftp_path)
#如果當前本地目錄文件已經遍歷完畢返回上一層目錄
os.chdir("..")
else:
print'ERROR:Thedir:%sisnotexist'%local_path
return
if__name__=='__main__':
ftp=FTPSync('192.168.1.110')
ftp.login('test','test')
#上傳文件,不重命名
#ftp.put_file('111.txt','a/b')
#上傳文件,重命名
#ftp.put_file('111.txt','a/112.txt')
#下載文件,不重命名
#ftp.get_file('/a/111.txt',r'D:\')
#下載文件,重命名
#ftp.get_file('/a/111.txt',r'D:112.txt')
#下載到已經存在的文件夾
#ftp.get_dir('a/b/c',r'D:\a')
#下載到不存在的文件夾
#ftp.get_dir('a/b/c',r'D:\aa')
#上傳到已經存在的文件夾
ftp.put_dir('b','a')
#上傳到不存在的文件夾
ftp.put_dir('b','aa/B/')

希望本文所述對大家的Python程序設計有所幫助。

以下轉自:http://blog.csdn.net/linda1000/article/details/8255771

Python中的ftplib模塊

Python中默認安裝的ftplib模塊定義了FTP類,其中函數有限,可用來實現簡單的ftp客戶端,用於上傳或下載文件

FTP的工作流程及基本操作可參考協議RFC959

ftp登陸連接

from ftplib import FTP #載入ftp模塊

ftp=FTP() #設置變數
ftp.set_debuglevel(2) #打開調試級別2,顯示詳細信息
ftp.connect("IP","port") #連接的ftp sever和埠
ftp.login("user","password")#連接的用戶名,密碼
print ftp.getwelcome() #列印出歡迎信息
ftp.cmd("xxx/xxx") #更改遠程目錄
bufsize=1024 #設置的緩沖區大小
filename="filename.txt" #需要下載的文件
file_handle=open(filename,"wb").write #以寫模式在本地打開文件
ftp.retrbinaly("RETR filename.txt",file_handle,bufsize) #接收伺服器上文件並寫入本地文件
ftp.set_debuglevel(0) #關閉調試模式
ftp.quit #退出ftp

ftp相關命令操作

ftp.cwd(pathname) #設置FTP當前操作的路徑
ftp.dir() #顯示目錄下文件信息
ftp.nlst() #獲取目錄下的文件
ftp.mkd(pathname) #新建遠程目錄
ftp.pwd() #返回當前所在位置
ftp.rmd(dirname) #刪除遠程目錄
ftp.delete(filename) #刪除遠程文件
ftp.rename(fromname, toname)#將fromname修改名稱為toname。
ftp.storbinaly("STOR filename.txt",file_handel,bufsize) #上傳目標文件
ftp.retrbinary("RETR filename.txt",file_handel,bufsize)#下載FTP文件

網上找到一個具體的例子:

#例:FTP編程
fromftplibimportFTP

ftp=FTP()
timeout=30
port=21
ftp.connect('192.168.1.188',port,timeout)#連接FTP伺服器
ftp.login('UserName','888888')#登錄
printftp.getwelcome()#獲得歡迎信息
ftp.cwd('file/test')#設置FTP路徑
list=ftp.nlst()#獲得目錄列表
fornameinlist:
print(name)#列印文件名字
path='d:/data/'+name#文件保存路徑
f=open(path,'wb')#打開要保存文件
filename='RETR'+name#保存FTP文件
ftp.retrbinary(filename,f.write)#保存FTP上的文件
ftp.delete(name)#刪除FTP文件
ftp.storbinary('STOR'+filename,open(path,'rb'))#上傳FTP文件
ftp.quit()#退出FTP伺服器

完整的模板:

#!/usr/bin/python
#-*-coding:utf-8-*-
importftplib
importos
importsocket

HOST='ftp.mozilla.org'
DIRN='pub/mozilla.org/webtools'
FILE='bugzilla-3.6.7.tar.gz'
defmain():
try:
f=ftplib.FTP(HOST)
except(socket.error,socket.gaierror):
print'ERROR:cannotreach"%s"'%HOST
return
print'***Connectedtohost"%s"'%HOST

try:
f.login()
exceptftplib.error_perm:
print'ERROR:cannotloginanonymously'
f.quit()
return
print'***Loggedinas"anonymously"'
try:
f.cwd(DIRN)
exceptftplib.error_perm:
print'ERRORLcannotCDto"%s"'%DIRN
f.quit()
return
print'***Changedto"%s"folder'%DIRN
try:
#傳一個回調函數給retrbinary()它在每接收一個二進制數據時都會被調用
f.retrbinary('RETR%s'%FILE,open(FILE,'wb').write)
exceptftplib.error_perm:
print'ERROR:cannotreadfile"%s"'%FILE
os.unlink(FILE)
else:
print'***Downloaded"%s"toCWD'%FILE
f.quit()
return

if__name__=='__main__':
main()

E. python 操作ftp 都有哪些庫

Python提供了一個內置的操作ftp的模塊ftplib,
能夠完成ftp登錄、查看目錄、修改目錄、上傳文件等功能。
一般需求應該足夠了。

F. python,如何下載FTP上指定時間段內的文件

importftplib
path='c:/user/pcwuyu/desktop/1c0/'
l=[]
defls_filter(line):
ll=line.split()
ifll[5]=='Jan'andll[6]=='9'andll[7]>'14:30'andll[7]<'15:30':
ifll[8]!='.'andll[8]!='..':
l.append(ll[8])
returnll[8]
ftp=ftplib.FTP('127.0.0.1')
ftp.login('root','password')
ftp.cwd('/mnt/1c0')
ftp.set_pasv(False)
fs=ftp.retrlines('LIST',ls_filter)
foriinl:
ftp.retrbinary('RETR'+i,open(path+i,'wb').write)
ftp.quit()

一個簡單的例子,下載1月9日14:30~15:30的文件

G. 如何在Python中使用FTP

from
ftplip
import
FTP
#
首先要引入
ftplib
這個庫
#
接著,這是我自定義的幾個用於操作
ftp
的函數,def
後面跟的是自定義函數名,函數體內FTP
相關的語句和函數來自上面
import
那個包,你自己體會吧:
#
初始化
FTP
連接
def
ftp_open(HOST,PORT,USERNAME,PASSWORD):
ftp=FTP()
ftp.set_debuglevel(2)
ftp.connect(host=HOST,port=PORT)
ftp.login(USERNAME,PASSWORD)
return
ftp
#
關閉
FTP
連接
def
ftp_close(ftp):
ftp.set_debuglevel(0)
ftp.quit()
#
文件上傳函數,filename
可以是windows
格式包含全路徑的文件
def
ftp_up(ftp,filename):
#print(ftp.getwelcome())
#ftp.cwd('xxx/www')
file_handler=open(filename,'rb')
ftp.storbinary('STOR
%s'
%
os.path.basename(filename),file_handler)
file_handler.close()
print('FTP
up
OK.')
#
文件下載函數,filename
可以是windows
格式包含全路徑的文件
def
ftp_down(ftp,filename):
#print(ftp.getwelcome())
#ftp.cwd('xxx/www')
file_handler=open(filename,'wb')
ftp.retrbinary('RETR
%s'
%
os.path.basename(filename),file_handler)
file_handler.close()
print('FTP
down
OK.')

H. 我現在有一套在網站上爬取數據的程序(用python寫的)如何在伺服器運行

用xshell之類的軟體連接到伺服器上,然後用其帶的比如xftp工具將代碼傳上去,在伺服器上安裝python之後再去跑代碼就行了

I. 如何用python獲得ftp中某文件夾下的'文件夾列表'

使用dir()取回來後,
再處理一下,把目錄挑出來:
drw-rw-rw-
1
user
group
0
Oct
31
21:40
dir1
drw-rw-rw-
1
user
group
0
Oct
31
21:42
dir2
-rw-rw-rw-
1
user
group
10752
Oct
31
21:41
file1.doc
-rw-rw-rw-
1
user
group
10752
Oct
31
21:41
file2.doc