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

问题描述 投票:0回答:3

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

不知道如何在不被阻止的情况下访问此网页。我将非常感谢您的帮助。

python selenium web-scraping python-requests bots
3个回答
19
投票

Selenium 相当容易检测到,尤其是所有主要的反机器人提供商(Cloudflare、Akamai 等)。

为什么?

  1. Selenium 和大多数其他主要网络驱动程序将名为

    navigator.webdriver
    的浏览器变量(网站可以访问)设置为
    true
    。您可以通过前往 Google Chrome 控制台并运行
    console.log(navigator.webdriver)
    自行检查。如果您使用的是普通浏览器,则会出现错误。

  2. 用户代理,通常所有设备都有所谓的“用户代理”,这是指访问网站的设备。 Selenium 的用户代理看起来像这样:

    Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/59.0.3071.115 Safari/537.36
    。你明白了吗?包括
    HeadlessChrome
    ,这是另一种检测途径。

这些只是检测 Selenium 浏览器的多种方式中的两种,我强烈建议您也阅读 thisthis

最后,如果您想要一个简单、直接的解决方案来绕过检测,实现我们讨论过的几乎所有这些概念,我建议使用 unDetected-chromedriver。这是一个开源项目,尽力让您的 Selenium chromedriver 看起来更人性化。


5
投票

我认为你的问题不是机器人检测。您不能仅使用

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)

可能有很多标题和正文信息是不必要的,您可以通过编码和测试来改进它。


0
投票

如果抓取大数据,代理旋转会很有用

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

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

© www.soinside.com 2019 - 2024. All rights reserved.