我们正在尝试开发一个Python模块,该模块将访问FTP服务器并将文件下载到我的本地机器。当我们尝试运行模块的FTP部分时,它会超时。
我们有一个代理服务器(我们称之为"officeproxy.com:8080"(来处理这个问题,当使用FileZilla或Windows资源管理器等FTP客户端访问FTP站点时,我们成功了。
让我们称 ftp 站点为"ftp.cal.com"。 用户名是"爸爸"。 密码是"tango123"。
到目前为止,我们有:
Proxy = officeproxy.com:8080
FTP = ftp.cal.com
User = papa
PW = tango123
以上不是真实的实体,所以如果你想把它们换成真实的实体,请做我的客人。
我需要一个模块来首先加载代理服务,然后运行FTP部分。
我正在运行Python 2.7。
到目前为止,我已经搜索并拥有此代码。 OP表示,它只是一个简短的模块,用于测试与FTP的连接并读取一个文件。
(注:我故意把#
放在很多地方,在不知道填写的时候显示,或者其他原因(:
import urllib2
# I have filled in the proxy info
proxy_host = 'officeproxy.com:8080'
# I don't think this needs any modification, right?
proxy_handler = urllib2.ProxyHandler({'ftp': proxy_host})
# ditto here
proxy_auth_handler = urllib2.ProxyBasicAuthHandler()
# now here is where I am unsure what to put;
# also, I really need FTP user and FTP password, and NOT Proxy...
# so what do I need to change here?
proxy_auth_handler.add_password(None, proxy_host, proxy_user, proxy_passwd)
opener_thru_proxy = urllib2.build_opener(proxy_handler, proxy_auth_handler)
# I filled in this part
conn = opener_thru_proxy.open('ftp://ftp.cal.com/hello.txt')
# I don't believe I need to change this, right?
print conn.read()
添加此内容,因为它是最重要的结果之一,并且努力寻找解决方案。
如果您的代理是HTTP 代理,并且您需要对其进行身份验证,则方法如下:
import socks
import socket
socks.set_default_proxy(socks.HTTP,
proxy_host,
proxy_port,
username=proxy_username,
password=proxy_password
)
socket.socket = socks.socksocket
ftp = FTP(ftp_host)
ftp.set_debuglevel(1)
ftp.login(
user=ftp_user,
passwd=ftp_password
)
否则,对于FTP代理,马丁的答案有效。您也可以在FileZilla中看到FTP代理的行为,这将有助于根据您的要求进行编码。
希望这对某人有所帮助!
请注意,我在 SO 上发现了一些类似的问题,但由于 OP 要求提供详细的初学者级答案,我决定发布这个。
澄清一下,以下是我对您想要完成的任务的理解:
- 您在代理后面有一个 FTP 服务器。
- FTP 服务器需要用户/密码凭据,但代理本身不需要。
一种选择是使用ftplib
包。像Python这样的流行语言的一大优势是广泛的包选择,这些包提供了特定功能的良好实现。在本例中,ftp 客户端:
import ftplib # 1
ftp = ftplib.FTP("officeproxy.com:8080") # 2
ftp.set_debuglevel(1) # 3
ftp.login("papa", "tango123") # 4
filename = "hello.txt"
f = open(filename, 'wb') # 5
ftp.retrbinary("RETR " + filename , f.write) # 6
f.close() # cleanup file handle
ftp.quit() # cleanup ftp client
以下是代码正在执行的操作:
- 导入
ftplib
包。 - 通过代理连接到 FTP 服务器。我编写它的方式假设代理设置为在指定的端口(示例中为 8080(上转发 FTP 协议。如果不是这种情况,这将不起作用。
- 启用调试日志记录。从 ftplib 文档中:
FTP.set_debuglevel(level)
:0
,不产生调试输出...1
产生适量的调试输出...2
或更高,可生成最大数量的调试输出
- 使用 user="papa", passwd="tango123" 登录到 FTP 服务器。同样,这是来自 login(( 的 ftplib 文档
- 打开一个本地文件,用于写入要从FTP服务器检索的文件的内容。第一个参数是您要保存到的文件的文件名(它可以是任何内容,我决定使用与FTP服务器上的文件名相同的文件名(。第二个参数是您要打开文件的模式,它是一串标志:w = '写入模式',b = '二进制模式',因为我们要将文件检索为二进制并将其写入为二进制。
- 我建议您阅读 ftplib 文档以获取 retrbinary。起初这有点难以理解。第一个参数
"RETR" + filename
是发送到 FTP 服务器的命令,在本例中为RETR hello.txt
。第二个参数f.write
是您希望ftp.retrbinary
函数在具有来自服务器的数据块时调用的回调函数。在其实现中,只要retrbinary
有数据,它就会调用f.write(data)
其中data
是它拥有的最新数据块。要详细了解回调在 Python 中的工作原理,请参阅 Python 中的异步 API 简介
我希望这对你有用,我希望答案足够详细,让你了解它是如何工作的。如果它不起作用,请发布您收到的错误的堆栈跟踪输出。
这个问题有点过时了,但我自己没有找到任何最近的解决方案,所以我想我会提供我找到的解决方案。就我而言,办公室代理需要凭据,因此这些凭据包含在解决方案中。我假设您可以删除proxy_user并proxy_passwd如果您的代理不需要凭据。我在Python 3.6中得到的代码是:
from ftplib import FTP
ftp = FTP("officeproxy.com")
ftp.set_debuglevel(1)
ftp.login(user='ftp_user@ftp_host proxy_user', passwd='ftp_passwd', acct='proxy_passwd')
# Do whatever you need on the FTP server here
ftp.quit()
我希望这有所帮助。