=> Znalazłem tę stronę podczas googlowania, aby sprawdzić, czy plik istnieje za pomocą ftplib w pythonie. Oto, co wymyśliłem (mam nadzieję, że komuś pomaga):
=> Podczas próby wyświetlenia nieistniejących plików/katalogów, ftplib zgłasza wyjątek. Mimo że Dodanie bloku try/except jest standardową praktyką i dobrym pomysłem, wolałbym, aby moje skrypty FTP pobierały plik (y) tylko po upewnieniu się, że istnieją. Pomaga to w uproszczeniu moich skryptów - przynajmniej wtedy, gdy możliwe jest umieszczenie katalogu na serwerze FTP.
Na przykład serwer FTP Edgar ma wiele plików przechowywanych w katalogu/edgar/daily-index /. Każdy plik ma nazwę "master.YYYYMMDD.idx". Nie ma gwarancji, że plik będzie istniał dla każdej daty (RRRRMMDD) - nie ma pliku z dnia 24 listopada 2013 r., Ale jest plik z dnia: 22 listopada 2013 r. Jak działa listing w tych dwóch przypadkach?
# Code
from __future__ import print_function
import ftplib
ftp_client = ftplib.FTP("ftp.sec.gov", "anonymous", "[email protected]")
resp = ftp_client.sendcmd("MLST /edgar/daily-index/master.20131122.idx")
print(resp)
resp = ftp_client.sendcmd("MLST /edgar/daily-index/master.20131124.idx")
print(resp)
# Output
250-Start of list for /edgar/daily-index/master.20131122.idx
modify=20131123030124;perm=adfr;size=301580;type=file;unique=11UAEAA398;
UNIX.group=1;UNIX.mode=0644;UNIX.owner=1019;
/edgar/daily-index/master.20131122.idx
250 End of list
Traceback (most recent call last):
File "", line 10, in <module>
resp = ftp_client.sendcmd("MLST /edgar/daily-index/master.20131124.idx")
File "lib/python2.7/ftplib.py", line 244, in sendcmd
return self.getresp()
File "lib/python2.7/ftplib.py", line 219, in getresp
raise error_perm, resp
ftplib.error_perm: 550 '/edgar/daily-index/master.20131124.idx' cannot be listed
Zgodnie z oczekiwaniami lista nieistniejącego pliku generuje wyjątek.
=> Ponieważ wiem, że serwer Edgar FTP będą mogli cieszyć się katalog/Edgar/dobę-index /, mój skrypt można wykonać następujące czynności, aby uniknąć podnoszenia wyjątki powodu nieistniejących plików:
a) Wykaz ten informator.
b) pobierz wymagane pliki, jeśli są one obecne na tej liście - Aby sprawdzić wykaz, zwykle wykonuję wyszukiwanie wyrażenia regularnego, na liście ciągów, które zwraca operacja aukcji.
Na przykład ten skrypt próbuje pobrać pliki z ostatnich trzech dni. Jeśli plik zostanie znaleziony dla określonej daty, zostanie pobrany, w przeciwnym razie nic się nie stanie.
import ftplib
import re
from datetime import date, timedelta
ftp_client = ftplib.FTP("ftp.sec.gov", "anonymous", "[email protected]")
listing = []
# List the directory and store each directory entry as a string in an array
ftp_client.retrlines("LIST /edgar/daily-index", listing.append)
# go back 1,2 and 3 days
for diff in [1,2,3]:
today = (date.today() - timedelta(days=diff)).strftime("%Y%m%d")
month = (date.today() - timedelta(days=diff)).strftime("%Y_%m")
# the absolute path of the file we want to download - if it indeed exists
file_path = "/edgar/daily-index/master.%(date)s.idx" % { "date": today }
# create a regex to match the file's name
pattern = re.compile("master.%(date)s.idx" % { "date": today })
# filter out elements from the listing that match the pattern
found = filter(lambda x: re.search(pattern, x) != None, listing)
if(len(found) > 0):
ftp_client.retrbinary(
"RETR %(file_path)s" % { "file_path": file_path },
open(
'./edgar/daily-index/%(month)s/master.%(date)s.idx' % {
"date": today
}, 'wb'
).write
)
=> Interesujące są sytuacje, w których nie można wyświetlić katalogu na serwerze FTP. Na przykład edgarowy serwer FTP nie zezwala na edycję/edgar/data, ponieważ zawiera zbyt wiele podkatalogów. W takich przypadkach nie byłbym w stanie zastosować opisanej tutaj metody "Lista i sprawdzanie istnienia" - w takich przypadkach musiałbym użyć obsługi wyjątków w moim skrypcie downloadera, aby odzyskać nieistniejące próby dostępu do plików/katalogów.
To nie powie Ci, czy istnieje plik * (zamiast katalogu) o nazwie 'public_html'. –
jeśli nie każdy ("public_html" w F f in listy plików): druku "No public_html" else: # coś zrobić czyli public = [f do f in listy plików jeśli "public_html" w F] jeśli nie publiczny: print „nie public_html” else: dla f publicznie: # Zrób coś – hughdbrown
Zamiast polecenia wysyłając „list”, która zwraca linię pełnej informacji na temat każdego pliku, a następnie testowanie „, jeśli nazwa pliku in f ', możesz wysłać polecenie "NLST", które po prostu zwraca nazwę pliku dla każdego pliku. Zobacz http://docs.python.org/library/ftplib.html#ftplib.FTP.retrlines –