在提出问题之前,需要一些背景知识。我正在尝试向网站发出HTTP GET
和POST
请求,但有以下警告:
到目前为止,我一直在使用twisted.web.client.Agent
及其子类(例如BrowserLikeRedirectAgent
),但遗憾的是,似乎还没有支持SOCKS代理(并且ProxyAgent
是一个禁止,因为这个类是用于HTTP代理的。)
我偶然发现twisted-socks,这似乎让我做了我想做的事,但我发现它使用HttpClientFactory
代替代理,因此我的问题是:有什么区别HttpClientFactory
和Agent
我应该何时使用每一个?
下面是一些使用twisted-socks的示例代码。我还有两个问题:
如何在此示例中使用Cookie?我尝试将dict
和cookielib.CookieJar
实例传递给HttpClientFactory
的{{1}} kwarg,但是这会引发错误(关于字符串的预期......就在地球上怎么样我将cookie作为字符串发送?)
可以重构此代码以使用cookies
吗?这将是理想的,因为我已经有一个相当大的代码库,其中考虑了Agent
。
```
Agent
```
答案 0 :(得分:3)
我认为你通常不会使用HTTPClientFactory
,因为它似乎只是做HTTP请求而不是更多。这是非常低级别的。
如果您只想触发请求,则有一些函数(twisted.web.client.getPage
和.downloadPage
)可以为您构建工厂,同时处理HTTP和HTTPS。
Agent
是一个为您提供更高级别抽象的东西:它保留连接池,根据URL处理HTTP / HTTPS选择,处理代理等等。对,这是您通常想要的东西使用。
他们似乎没有共享太多代码,而代理人是HTTP11ClientProtocol
(和HTTP11ClientFactory
),因为getPage
是旧的HTTPClientFactory
(及其协议, HTTPPageGetter
)。所以有一个twisted.web.client
vs ._newclient
(Agent
作为其公共API)二元性。我猜,历史原因和向后兼容性。
无论如何,这个库与开箱即用的Agent
混合起来并不好,因为API已被破坏。 twisted-socks的SOCKSWrapper
声明它实现了IStreamClientEndpoint
接口,但是接口要求.connect
方法返回一个将被IProtocol
提供者触发的deffered(参见docs }),而SOCKSWrapper
返回一个用地址(here's the line that does this)触发的。
看起来您可以轻松修复它,将行更改为:
self.handshakeDone.callback(self.transport.protocol)
一旦你这样做,你应该可以使用Agent
的扭曲袜子。以下是一个示例:(使用inlineCallbacks
和新的react
,但您也可以使用带延迟的标准.addCallback和reactor.run()
)
from twisted.internet.endpoints import TCP4ClientEndpoint
from twisted.internet.defer import inlineCallbacks
from twisted.internet.task import react
from twisted.web.client import ProxyAgent, readBody
from socksclient import SOCKSWrapper
@react
@inlineCallbacks
def main(reactor):
target = TCP4ClientEndpoint(reactor, 'example.com', 80)
proxy = SOCKSWrapper(reactor, 'localhost', 9050, target)
agent = ProxyAgent(proxy)
request = yield agent.request('GET', 'http://example.com/')
print (yield readBody(request))
此外,还有一个txsocksx库似乎更好用(并且可以安装pip!)。 API几乎相同,但是您将传递目标端点,在此之前您将通过代理端点:
from twisted.internet.endpoints import TCP4ClientEndpoint
from twisted.internet.defer import inlineCallbacks
from twisted.internet.task import react
from twisted.web.client import ProxyAgent, readBody
from txsocksx.client import SOCKS5ClientEndpoint
@react
@inlineCallbacks
def main(reactor):
proxy = TCP4ClientEndpoint(reactor, 'localhost', 9050)
proxied_endpoint = SOCKS5ClientEndpoint('example.com', 80, proxy)
agent = ProxyAgent(proxied_endpoint)
request = yield agent.request('GET', 'http://example.com/')
print (yield readBody(request))