selenium爬虫使用了代理为什么还是被服务器判定为机器人?
1、前言
继上一篇文章selenium爬虫使用代理情况下不设置这几个参数,代理就白加了介绍了在使用selenium+chromedriver+chrome这套组合开发爬虫即使在使用了代理IP,如果不关闭webrtc还是可能被服务器嗅探到真实的IP地址。
2、问题
今天我们说一下另外一种即使加了代理,并且关闭了webrtc还是会被服务器识别为爬虫的情况,那就是浏览器的时区和地理位置。
3、原因
我们需要知道的一点:对于被访问的Web服务器端来说它能获取到访问者的IP,并且根据IP查询到此IP所属地理位置和时区。
以上我画了一个简图,我们来更加详细的梳理一下一次完整的网站访问流程: - 1、selenium启动浏览器,此时浏览器获取本地操作系统时区和地理位置 - 2、浏览器访问网站,网站后端获取到浏览器的ip,返回网页内容(js、html等) - 3、网页js调用浏览器api获取到第一步浏览器获取到的系统时区和地理位置 - 4、网页js将获取到的信息传给网站后端 - 5、网站后端通过风控查询到浏览器ip所属时区和地理位置,并与js传来的进行对比,如果一致则判断访问者是人类否则是机器人
了解了整个访问流程我们再来说一下为什么加了代理还是被判定为机器人访问:
一般正常情况下,时区、地理位置、IP三者是一致的,也就是说如果你操作系统时区和地理位置是上海、那么查询你的IP所属时区和地理位置肯定也是上海;但是如果你使用了美国洛杉矶的IP代理,那么查询你的IP所属时区和地理位置肯定是洛杉矶的,与js获取到的你本地的上海的时区和地理位置位置不一致,网站服务器便会判定你使用了代理,是机器人。
4、解决方案
解决方案从逻辑上来说其实很简单,就是在设置代理的时候,同时将浏览器的时区和地理位置设置为代理IP所属时区以及地理位置。 获取IP所属时区和地理位置我们使用一个第三方免费开放的接口:http://ip-api.com 使用返回结果格式为json的接口,代码如下:
def get_timezone_geolocation(ip):
import requests
url = "http://ip-api.com/json/{ip}"
response=requests.get(url)
return response.json()
返回的json格式举例:
{
"query": "123.123.123.123",
"status": "success",
"continent": "Asia",
"continentCode": "AS",
"country": "China",
"countryCode": "CN",
"region": "SC",
"regionName": "Sichuan",
"city": "Chengdu",
"district": "",
"zip": "",
"lat": 67.6667,//经度
"lon": 123.0667,//纬度
"timezone": "Asia/Shanghai",//时区
"offset": 28800,
"currency": "CNY",
"isp": "Chinanet",
"org": "Chinanet SC",
"as": "AS4134 CHINANET-BACKBONE",
"asname": "CHINANET-BACKBONE",
"mobile": false,
"proxy": false,
"hosting": false
}
我们需要的时区是json中timezone这个字段,地理位置为lat和lon这两个字段。
接下来我们利用获取到的时区和经纬度,把它传给浏览器
等等在这之前我们看看只加上代理,不设置时区和地理位置,访问:https://whoer.net/ 代码如下:
from selenium import webdriver
def get_timezone_geolocation(ip):
import requests
url = f"http://ip-api.com/json/{ip}"
response = requests.get(url)
return response.json()
chrome_options = webdriver.ChromeOptions()
chrome_options.add_experimental_option(
"excludeSwitches", ["enable-automation"])
chrome_options.add_experimental_option('useAutomationExtension', False)
chrome_options.add_argument('lang=zh-CN,zh,zh-TW,en-US,en')
chrome_options.add_argument(
'user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36')
chrome_options.add_argument("proxy-server=socks5://127.0.0.1:1080")
driver = webdriver.Chrome(
"./chromedriver", chrome_options=chrome_options)
print(res_json)
driver.get("https://whoer.net/")
从上图我们可以看到,我们代理的时区是:America/Phoenix
但是系统时间是中国标准时间,显然不对。
接下来我们加上代理并且设置时区和地理位置,代码如下:
废话少说,咱们直接上测试代码:
from selenium import webdriver
def get_timezone_geolocation(ip):
import requests
url = f"http://ip-api.com/json/{ip}"
response = requests.get(url)
return response.json()
chrome_options = webdriver.ChromeOptions()
chrome_options.add_experimental_option(
"excludeSwitches", ["enable-automation"])
chrome_options.add_experimental_option('useAutomationExtension', False)
chrome_options.add_argument('lang=zh-CN,zh,zh-TW,en-US,en')
chrome_options.add_argument(
'user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36')
chrome_options.add_argument("proxy-server=socks5://127.0.0.1:1080")
driver = webdriver.Chrome(
"./chromedriver", chrome_options=chrome_options)
res_json = get_timezone_geolocation("xxx.xxx.xxx.xxx")
print(res_json)
geo = {
"latitude": res_json["lat"],
"longitude": res_json["lon"],
"accuracy": 1
}
tz = {
"timezoneId": res_json["timezone"]
}
driver.execute_cdp_cmd("Emulation.setGeolocationOverride", geo)
driver.execute_cdp_cmd("Emulation.setTimezoneOverride", tz)
driver.get("https://whoer.net/")
以上代码get_timezone_geolocation("xxx.xxx.xxx.xxx")里面的xxx读者可以设置一个自己的ip后再运行代码,我自己的vpn代理服务器ip就不展示了,你懂的。 运行结果如下:
显然我们看到我们将浏览器的时区和地理位置与代理IP一致。
如果你们认为做到以上:关闭webrtc、设置浏览器时区和地理位置,就高枕无忧了吗?
No,这还不够,服务器还能通过其他方式知道你是谁,想知道更多的,咱们下期更新见! 防止失联,关注微信公众号:码道工程。
自言自语
哈哈哈
请先登陆 或 注册