2016-01-20 23 views
0

我想写一个简单的爬网程序。但尝试从服务器读取响应仅在第一次时返回答案。然后阅读器停止读取字节并返回b“。 我试图写超时并在写入后使用drain()。它没有产生结果。 Wireshark显示答案来自服务器,但我的程序没有看到它们。Asyncio套接字读取器返回空字节

import asyncio 

HOST = '93.184.216.34' 
PORT = 80 
CONCURRENT_CONNECTIONS = 3 

request = 'GET/HTTP/1.1\r\n' \ 
      'Host: example.com\r\n' \ 
      'Content-Type: application/x-www-form-urlencoded\r\n' \ 
      '\r\n'.encode() 


async def smart_read(reader): 
    buffer = b'' 
    while True: 
     response = await reader.read(1024) 
     if not response: 
      break 
     buffer += response 
    return buffer 


async def work(host, port, request): 
    reader, writer = await asyncio.open_connection(host, port) 
    while True: 
     writer.write(request) 
     resp = await smart_read(reader) 
     print(resp) 


tasks = [] 
for _ in range(CONCURRENT_CONNECTIONS): 
    tasks.append(asyncio.ensure_future(work(HOST, PORT, request))) 

loop = asyncio.get_event_loop() 
loop.run_until_complete(asyncio.wait(tasks)) 
loop.close() 
+0

是什么''work'而TRUE'循环的目的是什么?删除它并测试 – kwarunek

+0

爬网程序将在单个连接中发送多个请求。这是例如完成的。在原始代码中,我使用Queue进行链接传输。 – CthUlhUzzz

+0

考虑使用['aiohttp'](http://aiohttp.readthedocs.org/)来抓取网页。 –

回答

0

一旦StreamReader达到EOF,你总是会得到b'',您可以在阅读器清除_eof标志,但它的哈克。子类化StreamReader来处理很多请求,似乎是合理的解决方案。

快速 'N' 脏(真的不使用它)

async def work(host, port, request): 
    reader, writer = await asyncio.open_connection(host, port) 
    while True: 
     reader._eof = False # force to read 
     writer.write(request) 
     resp = await smart_read(reader) 
     print(resp)