使用 Python 抓取网站时设置代理



我想为我的爬虫设置代理。我正在使用请求模块和美丽的汤。 我找到了一个 API 链接列表,这些链接提供了具有 4 种协议的免费代理。

所有具有 3/4 协议的代理都可以工作(HTTP、SOCKS4、SOCKS5),除了一个,那就是使用 HTTPS 协议的代理。 这是我的代码:

from bs4 import BeautifulSoup
import requests
import random
import json
# LIST OF FREE PROXY APIS, THESE PROXIES ARE LAST TIME TESTED 50 MINUTES AGO, PROTOCOLS: HTTP, HTTPS, SOCKS4 AND SOCKS5
list_of_proxy_content = ["https://proxylist.geonode.com/api/proxy-list?limit=150&page=1&sort_by=lastChecked&sort_type=desc&filterLastChecked=50&country=CH&protocols=http%2Chttps%2Csocks4%2Csocks5",
"https://proxylist.geonode.com/api/proxy-list?limit=150&page=1&sort_by=lastChecked&sort_type=desc&filterLastChecked=50&country=FR&protocols=http%2Chttps%2Csocks4%2Csocks5",
"https://proxylist.geonode.com/api/proxy-list?limit=150&page=1&sort_by=lastChecked&sort_type=desc&filterLastChecked=50&country=DE&protocols=http%2Chttps%2Csocks4%2Csocks5",
"https://proxylist.geonode.com/api/proxy-list?limit=1500&page=1&sort_by=lastChecked&sort_type=desc&filterLastChecked=50&country=AT&protocols=http%2Chttps%2Csocks4%2Csocks5",
"https://proxylist.geonode.com/api/proxy-list?limit=150&page=1&sort_by=lastChecked&sort_type=desc&filterLastChecked=50&country=IT&protocols=http%2Chttps%2Csocks4%2Csocks5"]

# EXTRACTING JSON DATA FROM THIS LIST OF PROXIES
full_proxy_list = []
for proxy_url in list_of_proxy_content:

proxy_json = requests.get(proxy_url).text
proxy_json = json.loads(proxy_json)
proxy_json = proxy_json["data"]
full_proxy_list.extend(proxy_json)
# CREATING PROXY DICT
final_proxy_list = []
for proxy in full_proxy_list:
#print(proxy) # JSON VALUE FOR ALL DATA THAT GOES INTO PROXY
protocol = proxy['protocols'][0]
ip_ = proxy['ip']
port = proxy['port']

proxy = {protocol : protocol + '://' + ip_ + ':' + port}
final_proxy_list.append(proxy)

# TRYING PROXY ON 3 DIFERENT WEBSITES
for proxy in final_proxy_list:
print(proxy)
try:
r0 = requests.get("https://edition.cnn.com/", proxies=proxy, timeout = 15)
if r0.status_code == 200:
print("GOOD PROXY")
else:
print("BAD PROXY")
except:
print("proxy error")

try:        
r1 = requests.get("https://www.buelach.ch/", proxies=proxy, timeout = 15)
if r1.status_code == 200:
print("GOOD PROXY")        
else:
print("BAD PROXY")
except:
print("proxy error")

try:      
r2 = requests.get("https://www.blog.police.be.ch/", proxies=proxy, timeout = 15)
if r2.status_code == 200:
print("GOOD PROXY")        
else:
print("BAD PROXY")
except:
print("proxy error")
print()

我的问题是,为什么HTTPS代理不起作用,我做错了什么?

我的代理看起来像这样:

{'socks4': 'socks4://185.168.173.35:5678'}
{'http': 'http://62.171.177.80:3128'}
{'https': 'http://159.89.28.169:3128'}

我看到有时人们会传递这样的代理:

proxies = {"http": "http://10.10.1.10:3128",
"https": "http://10.10.1.10:1080"}

但是这个字典有 2 个协议,但在链接中它只有 http,为什么? 我可以只传递一个,我可以在此字典中传递 10 个不同的 IP 地址吗?

你的代码有几个问题。我将首先解决唾手可得的果实。

首先,您的袜子代理也不起作用。原因如下。 编写代理字典的正确方法可以在请求文档中找到。

# your way
proxy = {'socks4': 'socks4://ip:port'}
# the correct way
proxy = {'https': 'socks4://ip:port'}   # note the s in https
# or another correct way
proxy = {'http': 'socks4://ip:port'}  # Note the http with no s
# best correct way if your urls are mixed http:// https://
proxies = {
'http': 'socks4://ip:port',
'https': 'socks4://ip:port',
}

这些条目中的httphttps不是代理服务器的协议,而是您的 url 的协议。

例如:https://www.example.comvshttp://www.example.com

https://

URL 的请求将转到https条目,而对http://URL 的请求将转到http条目。如果您只提供一个条目{'http': 'socks4://ip:port'},并且 url 请求是针对https://url,则该请求不会被代理,并且您自己的 ip 将被公开。由于浏览时没有socks4://www.example.com这样的事情,因此您发出的请求没有代理。

通过代理和VPN进行任何工作时,我不喜欢测试代码并向我将运行最终代码的服务器发送请求。我喜欢使用 ipinfo.io。他们的 json 响应包括有关连接 IP 的信息。这样,我可以确保连接通过代理并且不发送误报。

注意:由于负载均衡器的原因,连接 IP 与代理 IP 不同的情况并不少见。只需确保连接 IP 不是您自己的。您可以使用浏览器访问以下代码中的 url 来检查您自己的 ip。

因为您使用的是{'socks4': 'socks4://ip:port'}而不是正确的{'https': 'socks4://ip:port'},所以您仍然收到 200 个状态代码,并且您的代码返回误报。它返回 200 是因为您确实连接了,但使用您自己的 ip 而不是通过代理。

由于您没有提供有关实际发生情况的细节,因此我在代码中添加了一些快速而肮脏的错误处理,以了解发生了什么。一些错误与服务器端配置有关,因为大多数https代理都需要某种身份验证,例如证书或登录名(尽管它们是"免费"和"公共"的)。

我的不完美但有效的代码如下。在Python 3.8.12上测试。有关代理连接错误的一些信息位于其下方。

提示:检查您的网址。country=CH在第一个可能应该说country=CNcountry=AT应该说country=AR.我的代码反映了这一点。

from bs4 import BeautifulSoup
import requests
import json
import time
# LIST OF FREE PROXY APIS, THESE PROXIES ARE LAST TIME TESTED 50 MINUTES AGO
# PROTOCOLS: HTTP, HTTPS, SOCKS4 AND SOCKS5
list_of_proxy_content = [
"https://proxylist.geonode.com/api/proxy-list?limit=150&page=1&sort_by=lastChecked&sort_type=desc&filterLastChecked=50&country=CN&protocols=http%2Chttps%2Csocks4%2Csocks5",
"https://proxylist.geonode.com/api/proxy-list?limit=150&page=1&sort_by=lastChecked&sort_type=desc&filterLastChecked=50&country=FR&protocols=http%2Chttps%2Csocks4%2Csocks5",
"https://proxylist.geonode.com/api/proxy-list?limit=150&page=1&sort_by=lastChecked&sort_type=desc&filterLastChecked=50&country=DE&protocols=http%2Chttps%2Csocks4%2Csocks5",
"https://proxylist.geonode.com/api/proxy-list?limit=1500&page=1&sort_by=lastChecked&sort_type=desc&filterLastChecked=50&country=AR&protocols=http%2Chttps%2Csocks4%2Csocks5",
"https://proxylist.geonode.com/api/proxy-list?limit=150&page=1&sort_by=lastChecked&sort_type=desc&filterLastChecked=50&country=IT&protocols=http%2Chttps%2Csocks4%2Csocks5",
]

# EXTRACTING JSON DATA FROM THIS LIST OF PROXIES
full_proxy_list = []
for proxy_url in list_of_proxy_content:
proxy_json = requests.get(proxy_url).text
proxy_json = json.loads(proxy_json)
proxy_json = proxy_json["data"]
full_proxy_list.extend(proxy_json)
if not full_proxy_list:
print("No proxies to check. Exiting...")
exit
else:
print(f"Found {len(full_proxy_list)} proxy servers. Checking...n")
# CREATING PROXY DICT
final_proxy_list = []
for proxy in full_proxy_list:
# print(proxy)  # JSON VALUE FOR ALL DATA THAT GOES INTO PROXY
protocol = proxy["protocols"][0]
ip_ = proxy["ip"]
port = proxy["port"]
proxy = {
"https": protocol + "://" + ip_ + ":" + port,
"http": protocol + "://" + ip_ + ":" + port,
}
final_proxy_list.append(proxy)
# TRYING PROXY ON 3 DIFERENT WEBSITES
for proxy in final_proxy_list:
print(proxy)
try:
# Use ipinfo.io to test proxy ip
url = "https://ipinfo.io/json?token=67e01402d14101"
r0 = requests.get(url, proxies=proxy, timeout=15)
if r0.status_code == 200:
# The 3-line block below only works on ipinfo.io
output = r0.json()
real_ip = output["ip"]
print(f"GOOD PROXY [IP = {real_ip}] {proxy}n")
# Do something with the response
html_page = r0.text
soup = BeautifulSoup(r0.text, "html.parser")
print(soup, "n")
r0.close()  # close the connection so it can be reused
# Break out of the proxy loop so we do not send multiple successful
# requests to the same url. Info needed was already obtained.
# Comment out to check all possible proxies during testing.
break
else:
# If the response code is something other than 200,
# it means the proxy worked, but the website did not.
print(f"BAD URL: [status code: {r0.status_code}]n{r0.headers}n")
r0.close()
time.sleep(5)  # Don't overload the server
except Exception as error:
print(f"BAD PROXY: Reason: {str(error)}n")

您看到的大多数错误都是超时错误,这应该是不言自明的。

其他错误是服务器端错误,因为它们的配置阻止了您的连接。

简短列表,但不要太技术性:

  • Remote end closed connection without response是服务器端 尽管连接到它,但还是断然拒绝发送您的请求。

  • 407 Proxy Authentication Required是其中一个错误我 上述。这要么希望您提供用户/通行证,要么要求您提供 证书。

  • [Errno 111] Connection refused是其中一个错误我 上述。

重要说明:如果您在运行上述代码后看到以下错误之一check_hostname requires server_hostnameEOF occurred in violation of protocolSSL: WRONG_VERSION_NUMBER,请降级您的 urllib3 库。在一些最新版本中,存在代理错误以及其他一些错误。您可以使用命令pip install -U urllib3==1.25.11python3 -m pip install -U urllib3==1.25.11来执行此操作。

我对这个主题做了一些研究,现在我很困惑为什么你想要HTTPS的代理。

虽然想要HTTP的代理是可以理解的,但(HTTP未加密)HTTPS是安全的。

您的代理是否可能因为您不需要而无法连接?

我不是代理专家,所以如果我发布一些完全愚蠢的东西,我深表歉意。


不过,我不想让你完全空手而归。 如果您正在寻找完全的隐私,我建议您使用VPN。Windscribe和RiseUpVPN都是免费的,可以加密计算机上的所有数据。(桌面版本,而不是浏览器扩展。

虽然这不是一个完全自动化的过程,但它仍然非常有效。

您正在寻找的是一个用于保存代理的类,这些代理在您的爬虫中操作后会定期轮换(时间相关或指令相关),以掩盖您的身份。

proxies = {"http": "http://10.10.1.10:3128",
"https": "http://10.10.1.10:1080"} 

这些类型的 IP 地址引用一个域,该域在内部刷新基础 IP 地址,并将您重定向到域下的某个 IP 地址。

其中大多数是付费服务。

您必须像下面这样介绍您的证书。 它对我有用。我不知道免费代理服务提供证书,但您可以在SSL服务或代理提供商上获得证书。我的代理提供程序 (zyte) 也提供 CA 证书。

verify='C:/Python39/zyte-proxy-ca.crt' 

一个例子;

import requests
from bs4 import BeautifulSoup   
response = requests.get(
"https://www.whatismyip.com/",
proxies={
"http": "http://proxy:port/",
"https": "http://proxy:port/",
},
verify='C:/Python39/zyte-proxy-ca.crt' 
)
print("Scrape Process Has Been Successfuly...")

soup = BeautifulSoup(response.text, 'lxml')
print(soup.title)

最新更新