最近需要在公司學習socket編程,但是不能直接連接外網,需要設置一個代理才能正常訪問。報錯示例:
import socket def blocking(wd): sock = socket.socket() sock.connect(('www.baidu.com',80)) # 連接百度 request = 'GET {} HTTP/1.0\r\nHost:www.baidu.com\r\n\r\n'.format('/s?wd={}'.format(wd)) # 構造http請求頭 response = b'' # 用於接收數據 sock.send(request.encode()) # 發送http請求 chunk = sock.recv(1024) # 一次接收1024字節數據 while chunk: # 循環接收數據,若沒有數據了說明已接收完 response += chunk # 字符串拼接 chunk = sock.recv(1024) print(response.decode()) if __name__ == '__main__': blocking('python')
解決辦法:要使用代理,需要用到socks這兩個包。socks在python3中不是自帶的,所以需要通過pip install PySocks這個模塊。
增加如下帶代碼即可:
import socks import socket socks.set_default_proxy(socks.HTTP, '地址', 端口, True, 用戶名, 密碼) socket.socket = socks.socksocket
修改后示例:
import socket import socks # pip install PySocks socks.set_default_proxy(socks.HTTP,addr='192.168.105.71',port=80) #設置socks代理 socket.socket = socks.socksocket # 把代理應用到socket def blocking(wd): sock = socket.socket() sock.connect(('www.baidu.com',80)) # 連接百度 request = 'GET {} HTTP/1.0\r\nHost:www.baidu.com\r\n\r\n'.format('/s?wd={}'.format(wd)) # 構造http請求頭 response = b'' # 用於接收數據 sock.send(request.encode()) # 發送http請求 chunk = sock.recv(1024) # 一次接收1024字節數據 while chunk: # 循環接收數據,若沒有數據了說明已接收完 response += chunk # 字符串拼接 chunk = sock.recv(1024) print(response.decode()) if __name__ == '__main__': blocking('python')
可以看到已經正常請求到百度。
注意:socks的類型,即set_default_proxy的第一個參數,網上很多資料寫的都是socks.SOCKS5。如果出現下面這個錯誤,請檢查代理服務的類型,我這里改成socks.HTTP即可正常發送請求:
socks.GeneralProxyError: Socket error: Connection closed unexpectedly