[200227]Python通过代理访问外网实践

从零开始的Python学习手记

python的语言格式什么的都不是问题,略过,主要麻烦在于建包之类的

 

情况:工作环境有限,无法访问许多外网,也没有IDE

目的:访问某网站提供信息并获取回复

 

原始基础代码:

# Get Token
import requests
tokenResponse = requests.get("http://aaa.com/getToken")
import json
jsonToken = json.loads(tokenResponse.text)
token = ""
if jsonToken["errorCode"] == 0:
	token = jsonToken["source"]["token"]
	pass
else : print(str(jsonToken["errorCode"])+":"+jsonToken["message"])

问题1:Failed to establish a new connection: [Errno 11001] getaddrinfo failed

解决思路1:网站无法访问,需要代理,使用socket代理

——————

问题2:代理服务器需要用户名密码验证

解决思路2:使用Pysocks包进行验证

*无法连接外网下载Pysocks

https://github.com/Anorov/PySocks下载后,使用python setup.py install安装

代码2:

import requests
import socket
import socks  # pip install PySocks

socks.set_default_proxy(socks.SOCKS5,addr='xxx.xxx.xxx.xxx', port=xx, rdns=True/False, username='xxx', password='xxx')
socket.socket = socks.socksocket
sock = socket.socket()

sock.connect("http://aaa.com/getToken")
request = 'GET {} HTTP/1.0\r\nHost:aaa.com/getToken'.format('/s?wd={}'.format(wd))
response = b''
sock.send(request.encode())
response = sock.recv(40960)
print(response.decode())

——————

问题3:PySocks doesn't support IPv6

经测试,并不是如错误信息的原因,而是sock.connect没有双层括号

代码3:

import socks

socks.set_default_proxy(socks.SOCKS5,[...]) 

sock = socks.socksocket()
url = "http://aa.com/getToken"

sock.connect((url,8080)) #必须要双层括号,且必须有端口号

——————

问题4:Socket error: Connection closed unexpectedly

解决:修改为socks.HTTP

——————

问题5: encoding with 'idna' codec failed (UnicodeError: label too long)

解决:url过长,缩短就又回到连接问题了

*如果一直报[Errno 11001] getaddrinfo failed,考虑修改rdns连接方式,即proxy属性中True/False

——————

问题6:[*] Note: The HTTP proxy server may not be supported by PySocks (must be a CONNECT tunnel proxy)

经查代码,400, 403, 405这三种情况会报此错,我本次是400: Bad Request

可能性A:目标地址为HTTPS

可能性B:请求访问接口时传入的参数过大

可能性C:HttpGet或 HttpPost都不能传包含 ” 、“{“、”}”这样的参数,需要对特殊字符进行转义,把 ” 转成%22,把 { 转成%7b,把 } 转成%7d

可能性D:两个完全相同但是从属不同域的key=value段,放入请求中的cookie中,导致cookie过大

可能性E:前端提交数据的字段名称或者是字段类型和后台的实体类不一致,导致无法封装;

可能性F:前端提交的到后台的数据应该是json字符串类型,而前端没有将对象转化为字符串类型;

可能性G:URL是否“模糊匹配”

etc.

不同尝试如下:

10.27.*.*, 8080(本机Foreigh Address)

Socket error: 407: Unauthorized



10.24.*.*, 8080(本机Local Address)

ConnectionRefusedError: [WinError 10061] No connection could be made because the target machine actively refused it



10.24.*.*, 8080(老板给我的代理ip)

socks.HTTPError: 400: Bad Request

The HTTP proxy server may not be supported by PySocks (must be a CONNECT tunnel proxy)



***, 8080(netstat中端口号为8080的地址)

socks.HTTPError: 302: Found



***, 8080(乱填的地址)

socket.gaierror: [Errno 11001] getaddrinfo failed



10.24.*.*, 8080(同事的Local Address)

TimeoutError: [WinError 10060] A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond

报错信息大全吗这里是?抓狂.gif

解决:目标网址,只能是Host!不带后续

*一个小tip,cmd中运行python程序卡住想要退出,又没有PauseBreak键,可以Fn+B

——————————

由此问题7:sendall后无反应

解决:

request = 'GET {} HTTP/1.0\r\nHost: xxx.com\r\n\r\n'.format('/aaa?bbb={}'.format(bbb))
sock.sendall(request.encode())

要用这种格式

————————

问题8:json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

解决:json格式不符

输出时容易漏看,实际获得的是这个:

“HTTP/1.1 200
Server: nginx
Date: Tue, 03 Mar 2020 09:30:10 GMT
Content-Type: application/json;charset=UTF-8
Connection: close

{"message":"AAA","status":200,"source":null}”

tokenResponse = str(sock.recv(4096),'utf-8')
import re
match = re.findall('\{.*?\}', tokenResponse)
print(match)
jsonToken = json.loads(match[0])

——————————

 

齐活了!!

终于齐活了!!

 

yay!!!

代码对比:

初始:

# Get Token
import requests
tokenResponse = requests.get("http://aaa.com/getToken")
import json
jsonToken = json.loads(tokenResponse.text)
token = ""
if jsonToken["errorCode"] == 0:
	token = jsonToken["source"]["token"]
	pass
else : print(str(jsonToken["errorCode"])+":"+jsonToken["message"])

最终:

import requests
import socks  # pip install PySocks
import json
import re
#取得token

socks.set_default_proxy(socks.HTTP, "***.***.***.***", 8080, True, "username", "password")
sock = socks.socksocket()
url="aaa.com"
sock.connect((url,80))
#print("connected")

request = 'GET {} HTTP/1.0\r\nHost: aaa.com\r\n\r\n'.format('/getToken')

try:
    print(request)
    sock.sendall(request.encode())
except Exception as err:
    print (err)

tokenResponse = str(sock.recv(4096),'utf-8')
match = re.findall('\{.*?\}', tokenResponse)
#print(match)

jsonToken = json.loads(match[0])
token = ""
if jsonToken["errorCode"] == 0:
    token = jsonToken["source"]["token"]
    pass
else : print(str(jsonToken["errorCode"])+":"+jsonToken["message"])

 


版权声明:本文为iwaspure原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。