zoukankan      html  css  js  c++  java
  • twisted学习笔记No.3 Web Clients

    原创博文,转载请注明出处

     这一章我们学习利用twisted建立web 客户端。

    twisted.web.client.getPage用来异步下载一个页面,并且返回一个deferred
    from twisted.internet import reactor
    from twisted.web.client import getPage
    import sys
    
    def printPage(result):
        print result
    
    def printError(failure):
        print >>sys.stderr,failure
    
    def stop(result):
        reactor.stop()
    
    if len(sys.argv)!=2:
        print >>sys.stderr,"Usage: python 5-1.py<URL>"
        exit(1)
    
    d=getPage(sys.argv[1])
    d.addCallbacks(printPage,printError)
    d.addBoth(stop)
    
    reactor.run()

    在控制台下我们执行 python 5-1.py http://www.baidu.com/ 就会把整个页面下载下来并以字符串形式输出。

    twisted.web.client.downloadPage用来异步下载一个页面并保存为文件,
    from twisted.internet import reactor
    from twisted.web.client import downloadPage
    import sys
    
    def printError(failure):
        print >>sys.stderr,failure
    
    def stop(result):
        reactor.stop()
    
    if len(sys.argv)!=3:
        print >>sys.stderr,"Usage: python 5-2.py<URL><output file>"
        exit(1)
    
    d=downloadPage(sys.argv[1],sys.argv[2])
    d.addErrback(printError)
    d.addBoth(stop)
    
    reactor.run()

    测试: 执行python 5-2.py http://www.baidu.com/ baidu.html ,数据保存在与5-2.py 同目录下的baidu.html文件中

    getPage() 和 downloadPage() 在应付一些小工作时还可以,但是我们Twisted 主要的HTTP  Client API 还是Agent 接下来我们学习Agent的用法

    from twisted.internet import reactor
    from twisted.internet.defer import Deferred
    from twisted.internet.protocol import Protocol
    from twisted.web.client import Agent
    import sys
    
    class ResourcePrinter(Protocol):
        def __init__(self,finished):
            self.finished=finished
    
        def dataReceived(self,data):
            print data
    
        def connectionLost(self,reason):
            self.finished.callback(None)
    
    def printResource(response):
        finished=Deferred()
        response.deliverBody(ResourcePrinter(finished))
        return finished
    
    def printError(failure):
        print >>sys.stderr, failure
    
    def stop(result):
        reactor.stop()
    
    if len(sys.argv)!=2:
        print >>sys.stderr,"Usage: python 5-3.py URL"
        exit(1)
    
    agent=Agent(reactor)
    d=agent.request('GET',sys.argv[1])
    d.addCallbacks(printResource,printError)
    d.addBoth(stop)
    
    reactor.run()

          Agent的初始化需要参数reactor,agent.request(self,method,url,headers=None,bodyProducer=None)headers是请求头,bodyProducer是一个用来生成请求body的对象,本函数用来产生一个请求,返回一个由该请求引发的deferred。

          然后我们注册一个callback和errorback去处理请求,response.deliverBody 注册一个 IProtocol provider 来接收 response body.因为响应在网络中是以信息块的形式,所以我们构造一个Protocol来处理数据。为了能够在ResourcePrinter之外还能够处理事件,我们在ResourcePrinter初始化的时候构造了一个deferred,它在连接停止以后触发,并且通过printResource返回。

          最后结果和5-1.py(笔记第一个程序)一样。

     恢复响应元数据:

         Agent支持所有的HTTP 方法和任意HTTP头。由agent.request返回的deferred包含很多有用的HTTP元数据,比如HTTP status code, HTTP version, and headers。

    import sys
    from twisted.internet import reactor
    from twisted.web.client import Agent
    from twisted.web.http_headers import Headers
    
    def printHeaders(response):
        print 'HTTP version',response.version
        print 'Status code',response.code
        print 'Status phrase',response.phrase
        print 'Response headers:'
        for header, value in response.headers.getAllRawHeaders():
            print header,value
    
    def printError(failure):
        print >>sys.stderr, failure
    
    def stop(result):
        reactor.stop()
    
    if len(sys.argv)!=2:
        print >>sys.stderr, "Usage: python 5-4.py URL"
        exit(1)
    
    agent=Agent(reactor)
    headers=Headers({'User-Agent':['Twisted WebBot'],
                     'Content-Type':['text/x-greeting']})#为什么是列表?
    
    d=agent.request('HEAD',sys.argv[1],headers=headers)
    d.addCallbacks(printHeaders,printError)
    d.addBoth(stop)
    
    reactor.run()

    测试: 执行python 5-4.py http://www.baidu.com/ baidu.html  我们可以得到来自百度服务器端的响应信息。

    利用Agent 发生HTTP数据:

        首先我们介绍Producer和Consumer:高效大数据流 (下面解释的不是很清楚,因为我自己也是属于半懂阶段)

       Push Producers 如果没有外界的制止,它会一直产生数据,API通过IPushProducer接口定义。有三个方法 pauseProducing()  resumeProducing() stopProducing()

      Pull Producers 对于一个明确的请求的响应中产生一系列的数据,其API通过IPullProducer接口定义,有两个方法 resumeProducing() stopProducing(),只有resumeProducing() 被调用,一个Pull Producer 才产生数据。

      Consumer 就是数据的去处,也就是接收数据的地方,它由两个接口IConsumer和IFinishableConsumer定义。其中IConsumer有三个方法:registerProducer(producer,streaming), unregisterProducer(),write(data), IFinishableConsumer则增加了finish()

      在下面的例子中 ,我们用到了IBodyProducer(IPushProducer),其作用是把数据写进一个用write方法的IConsumer中,在初始化过程中我们必须定义length属性即数据的长度,在startProducing() 方法中如果所有数据写入完毕或者生成的数据有问题将会返回一个由None引发的Deferred。本例中我们用succeed(None)实现。

    import sys
    from twisted.internet import reactor
    from twisted.internet.defer import Deferred,succeed
    from twisted.internet.protocol import Protocol
    from twisted.web.client import Agent
    from twisted.web.iweb import IBodyProducer
    
    from zope.interface import implements
    
    class StringProducer(object):
        implements(IBodyProducer)
    
        def __init__(self,body):
            self.body=body
            self.length=len(body)
    
        def startProducing(self,consumer):
            consumer.write(self.body)
            return succeed(None)
    
        def pauseProducing(self):
            pass
    
        def stopProducing(self):
            pass
        
    class ResourcePrinter(Protocol):
        def __init__(self,finished):
            self.finished=finished
    
        def dataReceived(self,data):
            print data
    
        def connectionLost(self,reason):
            self.finished.callback(None)
    
    def printResource(response):
        finished=Deferred()
        response.deliverBody(ResourcePrinter(finished))
        return finished
    
    def printError(failure):
        print >>sys.stderr, failure
    
    def stop(result):
        reactor.stop()
    
    if len(sys.argv)!=3:
        print >>sys.stderr,"Usage: python 5-5.py URL 'POST DATA'"
        exit(1)
    
    agent=Agent(reactor)
    body=StringProducer(sys.argv[2])
    d=agent.request('POST',sys.argv[1],bodyProducer=body)
    d.addCallbacks(printResource,printError)
    d.addBoth(stop)
    
    reactor.run()

    我们再构造一个服务器端,其作用是把客户端推送过来的数据进行反转处理。

    from twisted.internet import reactor
    from twisted.web.resource import Resource
    from twisted.web.server import Site
    
    class TestPage(Resource):
        isLeaf=True
        def render_POST(self,request):
            return request.content.read()[::-1]
    
    resource=TestPage()
    factory=Site(resource)
    reactor.listenTCP(8000,factory)
    
    reactor.run()

    我们分别在两个控制台下输入命令

    python 5-6.py 这是服务器端

    python 5-5.py http://127.0.0.1:8000 nihao 

    我们会得到 oahin的输出。

  • 相关阅读:
    码云安装SSH私钥步骤
    关于在Python3中:字典在迭代过程中,字典的长度是不允许改变的
    Selenium ChromeDriver与Chrome版本映射表(更新到v78)
    web driver下载地址(selenium-3.141_浏览器版本对应)
    Python报错pip超时
    LoginRequiredMixin类
    pycharm断点调试django
    js克隆
    索引
    java8date
  • 原文地址:https://www.cnblogs.com/tracylining/p/3353808.html
Copyright © 2011-2022 走看看