Python中使用cloudscraper的逐步指南

学习如何在Python中使用cloudscraper来绕过Cloudflare的保护,处理错误,并探索针对反机器人系统的替代解决方案。
4 min read
Python中的Cloudscraper

在本教程中,您将学习如何使用cloudscraper Python库绕过Cloudflare的机器人检测,处理常见错误,并探索针对最强大反机器人保护的替代抓取解决方案。

如何在Python中使用cloudscraper

在本教程中,您将尝试使用和不使用cloudscraper从受Cloudflare保护的网站抓取数据。为此,您将使用Beautiful Soup和Requests包。如果您不熟悉这些包,请查看这篇Python网络抓取指南以了解更多信息。

首先,通过运行以下pip命令来安装所需的包:

pip install tqdm==4.66.5 requests==2.32.3 beautifulsoup4==4.12.3

为了使本教程更易于理解,以下网络爬虫被创建用于从ChannelsTV 网站上某一天发布的新闻文章中抓取元数据:

import requests
from bs4 import BeautifulSoup
from datetime import datetime
from tqdm.auto import tqdm

def extract_article_data(article_source, headers):
    response = requests.get(article_source, headers=headers)
    if response.status_code != 200:
        return None

    soup = BeautifulSoup(response.content, 'html.parser')

    title = soup.find(class_="post-title display-3").text.strip()

    date = soup.find(class_="post-meta_time").text.strip()
    date_object = datetime.strptime(date, 'Updated %B %d, %Y').date()

    categories = [category.text.strip() for category in soup.find('nav', {"aria-label": "breadcrumb"}).find_all('li')]

    tags = [tag.text.strip() for tag in soup.find("div", class_="tags").find_all("a")]

    article_data = {
        'date': date_object,
        'title': title,
        'link': article_source,
        'tags': tags,
        'categories': categories
    }

    return article_data

def process_page(articles, headers):
    page_data = []
    for article in tqdm(articles):
        url = article.find('a', href=True).get('href')
        if "https://" not in url:
            continue
        article_data = extract_article_data(url, headers)
        if article_data:
            page_data.append(article_data)
    return page_data

def scrape_articles_per_day(base_url, headers):
    day_data = []
    page = 1

    while True:
        page_url = f"{base_url}/page/{page}"
        response = requests.get(page_url, headers=headers)

        if not response or response.status_code != 200:
            break

        soup = BeautifulSoup(response.content, 'html.parser')
        articles = soup.find_all('article')

        if not articles:
            break
        page_data = process_page(articles, headers)
        day_data.extend(page_data)

        page += 1

    return day_data

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36',
}

URL = "https://www.channelstv.com/2024/08/01/"

scraped_articles = scrape_articles_per_day(URL, headers)
print(f"{len(scraped_articles)} articles were scraped.")
print("Samples:")
print(scraped_articles[:2])

在这段代码中,定义了三个函数以方便抓取过程。第一个函数,名为extract_article_data,从单个文章中加载数据并提取元数据,如发布日期、标题、标签和类别,存入一个Python字典中,然后返回。加载和提取步骤是使用Requests和Beautiful Soup Python库实现的。

第二个函数,process_page,获取特定页面上所有文章的链接,并调用extract_article_data函数来提取其中的数据,将每个元数据字典存储在一个列表中,然后返回。最后一个函数,名为scrape_articles_per_day,使用while循环来递增页码,并抓取每一页上的文章数据,直到到达不存在的页面。

接下来,您定义要抓取的URL,并将过滤日期指定为2024年8月1日,以及一个包含示例用户代理的headers变量。您调用scrape_articles_per_day函数并传入URLheaders变量。然后,您打印被抓取的文章数量和前两个结果。

理想情况下,这个爬虫应该可以工作,但实际上它无法工作,因为ChannelsTV网站使用了Cloudflare来防止您通过extract_article_datascrape_articles_per_day函数中实现的直接请求来访问其网页内容。

当您尝试运行此脚本时,您的输出看起来像这样:

0 articles were scraped.
Samples:
[]

引入cloudscraper

早些时候,当您打算从一篇文章中抓取特定元数据时,由于Cloudflare的保护,什么也没有返回。在本节中,您将安装并使用cloudscraper来绕过此问题。

首先,通过运行以下pip命令来安装cloudscraper库:

pip install cloudscraper==1.2.71

然后,导入该包并定义一个fetch_html_content函数,如下所示:

import cloudscraper

def fetch_html_content(url, headers):
    try:
        scraper = cloudscraper.create_scraper()
        response = scraper.get(url, headers=headers)

        if response.status_code == 200:
            return response
        else:
            print(f"Failed to fetch URL: {url}. Status code: {response.status_code}")
            return None
    except Exception as e:
        print(f"An error occurred while fetching URL: {url}. Error: {str(e)}")
        return None

该函数将要抓取的URL和请求头作为输入参数,返回一个响应对象或None。在函数中,您定义了一个try-except块。在try块中,您使用cloudscraper.create_scraper方法创建一个爬虫。接下来,您调用scraper.get方法并传入urlheaders变量。如果响应的状态码为200,则返回响应。否则,打印一条错误消息并返回None。同样,如果在try块中发生错误,将触发except块,其中打印一条适当的消息并返回¨C30C。

接下来,您将脚本中每个requests.get调用替换为这个fetch_html_content函数。首先,在您的extract_article_data函数中进行如下替换:

def extract_article_data(article_source, headers):
    response = fetch_html_content(article_source, headers)

然后,在您的scrape_articles_per_day函数中替换requests.get调用,如下所示:

def scrape_articles_per_day(base_url, headers):
    day_data = []
    page = 1

    while True:
        page_url = f"{base_url}/page/{page}"
        response = fetch_html_content(page_url, headers)

通过定义此函数,cloudscraper库可以帮助您绕过Cloudflare的限制。

当您运行代码时,输出如下所示:

Failed to fetch URL: https://www.channelstv.com/2024/08/01//page/5. Status code: 404
55 articles were scraped.
Samples:
[{'date': datetime.date(2024, 8, 1),
  'title': 'Resilience, Tear Gas, Looting, Curfew As #EndBadGovernance Protests Hold',
  'link': 'https://www.channelstv.com/2024/08/01/tear-gas-resilience-looting-curfew-as-endbadgovernance-protests-hold/',
  'tags': ['Eagle Square', 'Hunger', 'Looting', 'MKO Abiola Park', 'violence'],
  'categories': ['Headlines']},
 {'date': datetime.date(2024, 8, 1),
  'title': 'Mother Of Russian Artist Freed In Prisoner Swap Waiting To 'Hug' Her',
  'link': 'https://www.channelstv.com/2024/08/01/mother-of-russian-artist-freed-in-prisoner-swap-waiting-to-hug-her/',
  'tags': ['Prisoner Swap', 'Russia'],
  'categories': ['World News']}]

cloudscraper的其他功能

正如您所见,cloudscraper可以帮助您绕过Cloudflare的IUAM保护,但cloudscraper还有其他值得强调的功能。

使用代理

代理充当您的计算机和目标网站之间的中间服务器,使您在浏览互联网时更加匿名。您的请求通过它们路由,这样目标网站(如受Cloudflare保护的网站)就会将代理服务器视为流量来源,而不是您的设备。

使用cloudscraper,您可以定义代理并将其传递给您已经创建的cloudscraper对象,如下所示:

scraper = cloudscraper.create_scraper()

proxy = {
    'http': 'http://your-proxy-ip:port',
    'https': 'https://your-proxy-ip:port'
}

response = scraper.get(URL, proxies=proxy)

在这里,您用默认值定义了一个爬虫对象。然后,您定义了一个包含httphttps代理的代理字典。最后,您将代理字典对象传递给scraper.get方法,就像使用常规的request.get方法一样。

更改用户代理和JavaScript解释器

虽然您在之前的脚本中直接指定了用户代理,但cloudscraper库也可以自动生成用户代理。这减少了脚本编写过程中所需的手动配置,并允许您模拟具有不同浏览器身份的真实用户。这是随机完成的,但您也可以通过向cloudscraper.create_scraper方法传递一个浏览器参数来选择它采样的用户代理类型。这个浏览器参数包含一个字典,存储了浏览器和平台的字符串值,以及桌面和移动设备的布尔值。

cloudscraper还允许您指定与爬虫一起使用的JavaScript解释器和引擎。默认的是由cloudscraper团队创建的本地解算器。其他可用选项有Node.js、Js2Py、ChakraCore和v8eval。

以下是一个示例代码片段,展示了解释器和浏览器的指定:

scraper = cloudscraper.create_scraper(
    interpreter="nodejs",
    browser={
        "browser": "chrome",
        "platform": "ios",
        "desktop": False,
    }
)

在这里,您将解释器设置为"nodejs",并向浏览器参数传递一个字典。在这个字典中,浏览器设置为Chrome,平台设置为"ios"。desktop参数设置为False,意味着浏览器在移动设备上运行,因为mobile和desktop值默认都设置为True。在这种情况下,Cloudflare选择在Chrome浏览器上运行的移动iOS用户代理。

处理CAPTCHA

CAPTCHA旨在区分人类和机器人,当您进行抓取时,它们常常会阻止您的目标网页加载。cloudscraper的一个好处是它支持一些第三方的CAPTCHA解算器,专门用于reCAPTCHAhCaptcha等。如果您对其他第三方CAPTCHA解算器感兴趣,您可以通过GitHub支持票向cloudscraper团队提供建议。

以下代码片段向您展示了如何修改您的爬虫来处理CAPTCHA:

scraper = cloudscraper.create_scraper(
  captcha={
    'provider': 'capsolver',
    'api_key': 'your_capsolver_api_key'
  }
)

在这段代码中,您将您的CAPTCHA提供商指定为Capsolver,并提供您的Capsolver API密钥。两个值都存储在一个字典中,并传递给cloudscraper.create_scraper方法中的CAPTCHA参数。

常见的cloudscraper错误

虽然cloudscraper是绕过Cloudflare限制的简便方法,但在开始使用它时,您可能会遇到一些错误。以下是您可能遇到的一些最常见的错误(以及解决方案)。

模块未找到(module not found)

module not found错误是Python中常见的错误,当您尝试导入或使用一个在您的Python环境中不存在的库时会发生。

在Python中工作时,您在一个环境中操作,只有安装在该活动环境中的库才能被您的脚本或笔记本访问。module not found错误意味着您要么没有激活相关的(虚拟)环境,要么没有在您的环境中安装该包。

要在Windows中激活您的虚拟环境,运行以下命令:

.\<venv-name>\Scripts\activate.bat

如果您使用的是Linux或macOS,可以使用以下命令:

source &lt;venv-name>/bin/activate

如果根本没有安装该包,请运行以下命令进行安装:

pip install cloudscraper

cloudscraper无法绕过最新的Cloudflare版本

当您尝试使用一个设计用于绕过旧版Cloudflare的cloudscraper版本时,会出现cloudscraper can't bypass the latest Cloudflare version错误。这是一个问题,因为更新的Cloudflare版本可能会带来更改,限制旧版本的cloudscraper,直到Python库更新。

如果您运行的是旧版本的cloudscraper,最好使用以下命令升级您的包:

pip install -U cloudscraper

如果您已经在使用最新版本的cloudscraper,您可能需要等待更新或找到一个可行的替代解决方案。

cloudscraper的替代方案

如果在实现了这里所学的内容后,您仍然无法绕过Cloudflare的保护,您应该考虑使用Bright Data。

Bright Data拥有最大的代理网络之一,包括数据中心ISP移动住宅代理。使用这些代理作为中介,您可以避免IP阻止,提高性能,绕过地理限制,保护您的隐私。

要使用Bright Data绕过Cloudflare的保护,您所要做的就是创建一个账户,进行配置,并获取您的API凭证。然后,您可以使用这些凭证来访问目标URL的数据,如下所示:

import requests

host = 'brd.superproxy.io'
port = 22225

username = 'brd-customer-<customer_id>-zone-<zone_name>'
password = '<zone_password>'

proxy_url = f'http://{username}:{password}@{host}:{port}'

proxies = {
    'http': proxy_url,
    'https': proxy_url
}

response = requests.get(URL, proxies=proxies)

在这里,您使用Python的Requests库发出一个GET请求,并通过proxies参数传入代理。创建的代理使用您的Bright Data用户名、密码、主机和端口号。特别是您的用户名,是基于您的Bright Data客户ID和区域名称定义的——所有这些都可以从您的账户中获取。

结论

在本教程中,您学习了如何在Python中使用cloudscraper库来抓取受Cloudflare保护的网站。您还了解了一些可能遇到的常见错误以及如何规避它们。虽然cloudscraper可以成为绕过Cloudflare的IUAM的好解决方案,但和任何免费技术一样,它有其局限性。这就是为什么您还学习了如何使用令人印象深刻的Bright Data代理网络和网络解锁器来访问受Cloudflare保护的网站。

Bright Data为您提供了自动化工具,使您可以在没有任何限制的情况下访问互联网数据。您还可以使用其庞大的代理网络来减少请求失败的次数,如果自动化不是您的目标。

准备好将您的网络抓取提升到一个新水平了吗?了解我们的高级代理和专业的网络数据收集服务如何轻松绕过最强大的机器人保护。立即开始免费试用吧!