python:如何获取网址? (使用不正确的响应标头)

时间:2012-04-11 14:22:29

标签: url python-3.x

我想在python中构建一个需要获取url的小脚本。虽然服务器是一种蹩脚的回复纯粹的ASCII,没有任何标题。

当我尝试:

import urllib.request
response = urllib.request.urlopen(url)
print(response.read())

我收到http.client.BadStatusLine: 100错误,因为这不是格式正确的HTTP响应。

是否有其他方法可以获取网址并获取原始内容,而无需尝试解析响应?

由于

3 个答案:

答案 0 :(得分:1)

在这种情况下,您需要做的是send a raw HTTP request using sockets 在这种情况下,您需要使用socket python模块进行一些低级网络编程。 (网络套接字实际上会返回服务器as it as发送的所有信息,因此您可以根据需要解释响应。例如,HTTP协议根据标准HTTP头解释响应 - GET,POST, HEAD等。高级模块urllib隐藏了您的头信息,只返回数据。)

您还需要了解有关HTTP标头的一些基本信息。对于您的情况,您只需要了解GET HTTP请求。在此处查看其定义 - http://djce.org.uk/dumprequest,请在此处查看示例 - http://en.wikipedia.org/wiki/HTTP#Example_session。 (如果您希望捕获从浏览器发送的HTTP请求的实时跟踪,则需要使用像wireshark这样的数据包嗅探软件。)

了解了socket模块和HTTP headers的基础知识后,您可以通过此示例 - http://coding.debuntu.org/python-socket-simple-tcp-client告诉您如何通过套接字向服务器发送HTTP请求并阅读它回复了。您也可以参考此unclear question on SO

(您可以通过Google python socket http获取更多示例。)

(提示:我不是Java粉丝,但是如果你在python下找不到关于这个主题的足够令人信服的例子,试着在Java下找到它,然后相应地将它翻译成python。)

答案 1 :(得分:1)

如果没有更多信息,很难回答你的直接问题;不知道有问题的(网络)服务器是如何被破坏的。

也就是说,您可以尝试使用较低级别的内容,例如socket。这是一种方式(python2.x样式,未经测试):

#!/usr/bin/env python
import socket                                                                  
from urlparse import urlparse                                                  

def geturl(url, timeout=10, receive_buffer=4096):                              
    parsed = urlparse(url)                                                     
    try:                                                                       
        host, port = parsed.netloc.split(':')                                  
    except ValueError:                                                         
        host, port = parsed.netloc, 80                                         

    sock = socket.create_connection((host, port), timeout)                     
    sock.sendall('GET %s HTTP/1.0\n\n' % parsed.path)                          

    response = [sock.recv(receive_buffer)]                                     
    while response[-1]:                                                        
        response.append(sock.recv(receive_buffer))                             

    return ''.join(response)  

print geturl('http://www.example.com/') #<- the trailing / is needed if no 
                                            other path element is present

这里有一个python3.2转换(如果将响应写入文件,你可能不需要从字节解码):

#!/usr/bin/env python
import socket                                                                  
from urllib.parse import urlparse                                                  

ENCODING = 'ascii'

def geturl(url, timeout=10, receive_buffer=4096):                              
    parsed = urlparse(url)                                                     
    try:                                                                       
        host, port = parsed.netloc.split(':')                                  
    except ValueError:                                                         
        host, port = parsed.netloc, 80                                         

    sock = socket.create_connection((host, port), timeout)                     

    method  = 'GET %s HTTP/1.0\n\n' % parsed.path
    sock.sendall(bytes(method, ENCODING))

    response = [sock.recv(receive_buffer)]                                     
    while response[-1]:                                                        
        response.append(sock.recv(receive_buffer))                             

    return ''.join(r.decode(ENCODING) for r in response)

print(geturl('http://www.example.com/'))

HTH!

修改:您可能需要根据相关的网络服务器调整您在请求中添加的内容。 Guanidene的优秀答案提供了一些资源来指导您走上这条道路。

答案 2 :(得分:0)

urllib.urlretrieve('http://google.com/abc.jpg', 'abc.jpg')