windows环境下的Python HTTP请求模块

来源:互联网 发布:被芯哪个牌子好 知乎 编辑:程序博客网 时间:2024/05/16 23:50

windows环境下的Python HTTP请求模块

网络上关于Python的HTTP请求大部分都是利用了urllib,httplib,pycurl,但是经过我试用之后,都没有对cookie以及ssl良好的支持,所以本模块主要使用了wininet API来发送HTTP请求,经过测试之后,wininet库很好的封装了ssl,cookie的支持,因此将wininet库在Python中的调用方式公开。

因为wininet是windows对Internet的封装,所以只支持windows系统。

在Linux下,我们可以选择curl库来执行http请求。 PS : chrome的网络请求就是使用了curl。

Python中对curl的封装有pycurl,但是pycurl的作者封装的curl是不带ssl版本,所以无法发起https请求,在这里就不提了,有兴趣的朋友可以访问pycurl的下载地址来试用。

上代码:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#coding:utf-8
importctypes
fromurlparse importurlparse
importthreading
 
INTERNET_OPEN_TYPE_PRECONFIG =0
INTERNET_OPEN_TYPE_PROXY =3
INTERNET_OPEN_TYPE_DIRECT =1
INTERNET_OPEN_TYPE_PRECONFIG_WITH_NO_AUTOPROXY =4
 
INTERNET_SERVICE_HTTP =3
INTERNET_FLAG_RELOAD =2147483648
HTTP_ADDREQ_FLAG_REPLACE =2147483648
HTTP_ADDREQ_FLAG_ADD=536870912
INTERNET_OPEN_TYPE_DIRECT =1
INTERNET_FLAG_SECURE =8388608
HTTP_QUERY_STATUS_CODE =19
 
wininet =ctypes.windll.LoadLibrary('wininet.dll')
 
classwininetHttp():
 
    defhttpRequest(self,url,method="GET",proxy="",username="",password="",headers="",data="",timeout=20):
        """
        发出一个HTTP请求
        参数:
        url: 完整网址
        method: 请求方法,可以是GET或POST
        proxy: 代理地址
        username: 用户名
        password: 密码
        headers: 协议头
        data: 提交数据
        timeout: 请求超时值
        返回值:
        元组(header,html)
        """
        requestThread =_httprequest(url,method,proxy,username,password,headers,data)
        requestThread.daemon =True #线程随主线程一起退出
        requestThread.start()
        requestThread.join(timeout)
        ret =requestThread.getResponse()
        returnret
 
class_httprequest(threading.Thread):
 
    response =(0,'')
 
    def__init__(self,url,method,proxy,username,password,headers,data):
        threading.Thread.__init__(self)
        self.url =url
        self.url_info =urlparse(url)
        self.method =method
        self.proxy =proxy
        self.username =username
        self.password =password
        self.headers =headers
        self.data =data
 
    defrun(self):
        dwAccessType =self.proxy andINTERNET_OPEN_TYPE_PROXY orINTERNET_OPEN_TYPE_DIRECT
        lpszProxyName =self.proxy and'http=' + self.proxy orNone
        lpszAgent ='Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.72 Safari/537.36'
        hOpen =wininet.InternetOpenA(lpszAgent,dwAccessType,lpszProxyName,None,0)
        ifnot hOpen:
            return
        nServerPort =(self.url_info.scheme =='https'and443 or 80
        hConn =wininet.InternetConnectA(hOpen,self.url_info.netloc.lower(),nServerPort,self.username,self.password,INTERNET_SERVICE_HTTP,0,0)
        ifnot hConn:
            wininet.InternetCloseHandle(hOpen)
            return
        dwFlags =(self.url_info.scheme =='https'andINTERNET_FLAG_SECURE orINTERNET_FLAG_RELOAD
        hRequest =wininet.HttpOpenRequestA(hConn,self.method,self.url_info.path,'HTTP/1.1',None,0,dwFlags,0)
        ifnot hRequest:
            wininet.InternetCloseHandle(hConn)
            wininet.InternetCloseHandle(hOpen)
            return
        ifnot 'Accept: ' in self.headers:
            self.headers +='Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\n'
        ifnot 'Referer: ' in self.headers:
            self.headers +='Referer: %s\r\n' % self.url
        ifnot 'Accept-Language: ' in self.headers:
            self.headers +='Accept-Language: zh-CN,zh;q=0.8\r\n'
        ifself.method.upper() =='GET':
            wininet.HttpSendRequestA(hRequest, self.headers,len(self.headers),None0)
        elifself.method.upper() =='POST':
            ifself.data !='':
                ifnot 'Content-Type: ' in self.headers:
                    self.headers =self.headers +"Content-Type: application/x-www-form-urlencoded\r\n"
                self.headers =self.headers +"Content-Length: %s\r\n" % len(self.data)
            wininet.HttpSendRequestA(hRequest, self.headers,len(self.headers),self.data,len(self.data))
        else:
            wininet.InternetCloseHandle(hRequest)
            wininet.InternetCloseHandle(hConn)
            wininet.InternetCloseHandle(hOpen)
            return
        data_buf =(ctypes.c_char *2048)()
        ret_data =''
        =ctypes.c_int(1)
        whilex.value !=0:
            wininet.InternetReadFile(hRequest,data_buf,2048,ctypes.byref(x))
            buf =(ctypes.c_char *x.value)()
            ctypes.memmove(buf,data_buf,x.value)
            ret_data +=buf[:x.value]
 
        head_buf =ctypes.create_string_buffer(2048)
        buf_size =ctypes.c_int(2048)
        wininet.HttpQueryInfoA(hRequest,22,head_buf,ctypes.byref(buf_size),0)
 
        wininet.InternetCloseHandle(hRequest)
        wininet.InternetCloseHandle(hConn)
        wininet.InternetCloseHandle(hOpen)
 
        self.response =(head_buf.value,ret_data)
        return
 
    defgetResponse(self):
        returnself.response

因为wininet无法设置超时,所以模块中的超时是利用Python threading模块来控制。

学Python才几天,如果代码中有写的不对的地方或者是有更好的解决方案,欢迎联系我一起讨论~

代码自由使用,转载需注明原出处

其实Python的学习,只要多看官方doc就可以了。(●´∀`●)

 

0 0
原创粉丝点击