我想抓取以下网站:https://www.coches.net/segunda-mano/。
但是每次我用 python selenium 打开它时,我都会收到消息说他们将我检测为机器人。
如何绕过此检测?
首先我尝试使用 selenium 编写简单的代码:
from selenium import webdriver
from bs4 import BeautifulSoup
browser = webdriver.Chrome('C:/Python38/chromedriver.exe')
URL = 'https://www.coches.net/segunda-mano/'
browser.get(URL)
然后我按照要求尝试了,但也不起作用。
from selenium import webdriver
from bs4 import BeautifulSoup
from fake_useragent import UserAgent
import requests
ua = UserAgent()
headers = {"UserAgent":ua.random}
URL = 'https://www.coches.net/segunda-mano/'
r = requests.get(URL, headers = headers)
print(r.statuscode)
在这种情况下,我收到消息 403 = 状态代码,表明禁止访问该 URL。
不知道如何在不被阻止的情况下访问此网页。我将非常感谢您的帮助。
Selenium 相当容易检测到,尤其是所有主要的反机器人提供商(Cloudflare、Akamai 等)。
为什么?
Selenium 和大多数其他主要网络驱动程序将名为
navigator.webdriver
的浏览器变量(网站可以访问)设置为 true
。您可以通过前往 Google Chrome 控制台并运行 console.log(navigator.webdriver)
自行检查。如果您使用的是普通浏览器,则会出现错误。
用户代理,通常所有设备都有所谓的“用户代理”,这是指访问网站的设备。 Selenium 的用户代理看起来像这样:
Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/59.0.3071.115 Safari/537.36
。你明白了吗?包括HeadlessChrome
,这是另一种检测途径。
这些只是检测 Selenium 浏览器的多种方式中的两种,我强烈建议您也阅读 this 和 this。
最后,如果您想要一个简单、直接的解决方案来绕过检测,实现我们讨论过的几乎所有这些概念,我建议使用 unDetected-chromedriver。这是一个开源项目,尽力让您的 Selenium chromedriver 看起来更人性化。
我认为你的问题不是机器人检测。您不能仅使用
requests
来获取该页面的结果,因为它会在幕后发出 XHR 请求。所以你必须使用 Selenium、splash 等,但在这种情况下似乎是不可能的。
但是,如果您在页面中进行一些研究,您可以找到在幕后请求哪个 url 来显示结果。我做了这项研究并发现了这个页面(https://ms-mt--api-web.spain.advgo.net/search),它返回一个json,因此它将简化您在解析方面的工作。使用 chrome 开发工具我得到了curl请求并将其映射到python请求并获取此代码:
import json
import requests
headers = {
'authority': 'ms-mt--api-web.spain.advgo.net',
'sec-ch-ua': '" Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91"',
'accept': 'application/json, text/plain, */*',
'x-adevinta-channel': 'web-desktop',
'x-schibsted-tenant': 'coches',
'sec-ch-ua-mobile': '?0',
'user-agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36',
'content-type': 'application/json;charset=UTF-8',
'origin': 'https://www.coches.net',
'sec-fetch-site': 'cross-site',
'sec-fetch-mode': 'cors',
'sec-fetch-dest': 'empty',
'referer': 'https://www.coches.net/',
'accept-language': 'en-US,en;q=0.9,es;q=0.8',
}
data = '{"pagination":{"page":1,"size":30},"sort":{"order":"desc","term":"relevance"},"filters":{"categories":{"category1Ids":[2500]},"offerTypeIds":[0,2,3,4,5],"isFinanced":false,"price":{"from":null,"to":null},"year":{"from":null,"to":null},"km":{"from":null,"to":null},"provinceIds":[],"fuelTypeIds":[],"bodyTypeIds":[],"doors":[],"seats":[],"transmissionTypeId":0,"hp":{"from":null,"to":null},"sellerTypeId":0,"hasWarranty":null,"isCertified":false,"luggageCapacity":{"from":null,"to":null},"contractId":0}}'
while True:
response = requests.post('https://ms-mt--api-web.spain.advgo.net/search', headers=headers, data=data).json()
# you should parse items here.
print(response)
if not response["items"]:
break
data_dict = json.loads(data)
data_dict["pagination"]["page"] = data_dict["pagination"]["page"]+1 # get the next page.
data = json.dumps(data_dict)
可能有很多标题和正文信息是不必要的,您可以通过编码和测试来改进它。
如果抓取大数据,代理旋转会很有用
options = Options()
options.add_arguments('--proxy-server="#ip:#port"')
然后使用选项对象初始化 chrome 驱动程序