如何避免被机器人检测并使用Python爬取网站?

8

我的问题:

我想抓取以下网站: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)

然后我尝试了使用request,但它也不起作用。

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。

不知道如何在不被阻止的情况下进入此网页。非常感谢您的帮助。提前致谢。


请考虑给解决您问题的答案点赞并标记为已完成。 - Joaquin
3个回答

15

Selenium相当容易被检测到,特别是在所有主要的反机器人提供商(如Cloudflare、Akamai等)中。

为什么?

  1. Selenium和其他大多数主要的Web驱动程序会将一个名为navigator.webdriver的浏览器变量设置为true,网站可以访问它。你可以通过前往Google Chrome控制台并运行console.log(navigator.webdriver)来自己检查这一点。如果你使用普通的浏览器,则返回false。

  2. 用户代理(User-Agent)通常用于表示设备访问网站的信息。Selenium的User-Agent看起来像这样:Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/59.0.3071.115 Safari/537.36。你是否注意到了?其中包含了HeadlessChrome,这是另一种检测方式。

这只是Selenium浏览器可以被检测到的多种方式之一,我强烈建议阅读此内容以及此内容

最后,如果你想要一个容易使用的、能够绕过检测的解决方案,并且实现了我们谈论的几乎所有概念,我建议使用undetected-chromedriver。这是一个开源项目,尽最大努力使你的Selenium chromedriver看起来像人类。


5
我认为你的问题不是机器人检测。你无法仅使用requests从该页面获取结果,因为它在幕后进行XHR请求。因此,您必须使用Selenium、Splash等工具,但对于此情况似乎不可行。
然而,如果您在页面上进行一些研究,可以找到在幕后请求以显示结果的URL。我进行了这方面的研究,并发现了这个页面(https://ms-mt--api-web.spain.advgo.net/search),它返回一个json,因此在解析方面会更容易。使用Chrome开发工具,我得到了curl请求并将其映射到Python requests,获得了这段代码:
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)

可能有很多无用的头部和主体信息,您可以编写并测试代码以改进它。


0

如果要爬取大量數據,代理輪換可能會很有用。

options = Options()
options.add_arguments('--proxy-server="#ip:#port"')

然后使用选项对象初始化 Chrome 驱动程序


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接