返回博客
指南
Raluca PenciucLast updated on Mar 31, 20261 min read

如何用不到100行代码构建一个网络爬虫

如何用不到100行代码构建一个网络爬虫

我们身处数字时代,能够接触到海量的数据。借助这些信息,我们可以更好地了解自己的工作、娱乐、学习和生活方式。如果能针对特定主题获取更精准的信息,岂不是再好不过了吗?

本文将演示如何结合使用 BeautifulSoup 和 WebScrapingAPI,构建专属爬虫程序,从网站中采集目标数据。

温馨提示:在绝大多数情况下,抓取受版权保护的内容或个人信息属于违法行为。为确保安全,在抓取任何网站(尤其是社交媒体网站)之前,最好先获得明确的许可。

什么是网络爬虫

市面上有数不胜数的搜索引擎,我们都在使用它们。这些服务操作简便——您只需提出问题,它们便会在整个网络中搜寻答案。而在幕后,正是谷歌的 Googlebot 爬虫让谷歌搜索引擎取得了如此巨大的成功。

爬虫会根据您输入的关键词扫描网页,帮助搜索引擎对这些页面进行分类,并通过索引在后续检索中呈现结果。搜索引擎依赖爬虫收集网站信息,包括URL、超链接、元标签和文章内容,并分析HTML文本。

由于爬虫具备追踪已访问页面的能力,您无需担心它会无限期地卡在同一个网页上。公共互联网和内容筛选给网络爬虫带来了诸多挑战。每天,现有网站都会发布数十条新信息,更不用说每天涌现的新网站数量了。

最终,这要求它们搜索数百万个页面并持续更新索引。分析网站内容的系统依赖于它们,因此它们至关重要。

因此,爬虫固然重要,但为何要提及它们?因为我们将构建自己的机器人来辅助数据提取过程。这样,我们就可以依靠它来获取 URL,而无需手动将其输入到抓取工具中。更多自动化,太棒了!

安装

既然我们已经对网络爬虫有了基本了解,你可能想知道实际运行时会是什么样子。好吧,让我们深入探讨一下!

首先,我们需要搭建工作环境。请确保您的机器满足以下先决条件:

  • Python 3
  • 一个 Python 集成开发环境(IDE)。本指南将使用 Visual Studio Code,因为它轻量且无需额外配置。不过代码本身不依赖特定 IDE,因此你可以选择任何自己习惯的 IDE;

最后但同样重要的是,我们需要一个 API 密钥。您可以注册一个免费的 WSA 账户,前 14 天将获得 5000 次 API 调用额度。注册完成后,只需进入您的仪表盘,即可找到 API 密钥及其他有价值的资源。

开发爬虫

很好,我们已经备齐了工具,离开始构建爬虫更近了一步。但我们该如何使用它呢?具体实现方式可能因最终目标的不同而有所差异。

选择网站并检查 HTML

在本教程中,我们选择了一个销售各类零废弃产品的电商网站。我们将遍历所有页面,提取每页的产品列表,并最终将每页的数据存储为 CSV 文件。

为此,我们首先需要查看页面结构并制定策略。在页面任意位置右键点击,选择“检查元素”,随后“开发者工具”窗口将弹出。在这里,您可以查看网站的 HTML 文档,其中包含我们所需的所有数据。

构建爬虫

好,现在我们可以开始编写代码了!

首先在您的集成开发环境(IDE)中打开终端窗口,并运行以下命令,这将安装 BeautifulSoup 库,它能帮助我们从 HTML 中提取数据:

> pip install beautifulsoup4

接着,创建一个名为“products”的文件夹。它将帮助我们整理并把抓取结果存储在多个 CSV 文件中。

最后,创建“crawler.py”文件。我们将在此编写所有代码和爬取逻辑。完成后,可通过以下命令执行该文件:

> py crawler.py

接下来,让我们导入所需的库,然后定义一些全局变量:

import requests
from bs4 import BeautifulSoup
import csv

BASE_URL = "https://www.shopetee.com"
SECTION = "/collections/all-collections"
FULL_START_URL = BASE_URL + SECTION

ENDPOINT = "https://api.webscrapingapi.com/v1/"
API_KEY = "API_KEY"

现在,让我们定义爬虫的入口点:

def crawl(url, filename):
    page_body = get_page_source(url, filename)
    soup = BeautifulSoup(page_body, 'html.parser')
    start_crawling(soup, filename)

crawl(FULL_START_URL, 'etee-page1.txt')

我们实现 crawl 函数,该函数将通过 get_page_source 过程提取 HTML 文档。随后它将构建 BeautifulSoup 对象以简化解析工作,并调用 start_crawling 函数,从而开始遍历网站。

def get_page_source(url, filename):
    params = {
        "api_key": API_KEY,
        "url": url,
        "render_js": '1'
    }
    page = requests.request("GET", ENDPOINT, params=params)
    soup = BeautifulSoup(page.content, 'html.parser')
    body = soup.find('body')

    file_source = open(filename, mode='w', encoding='utf-8')
    file_source.write(str(body))
    file_source.close()

    return str(body)

如前所述,get_page_source 函数将使用 WebScrapingAPI 获取网站的 HTML 内容,并将其写入 <body> 部分的文本文件中,因为该部分包含我们所需的所有信息。

现在,让我们退一步,看看如何实现我们的目标。产品按页面组织,因此我们需要反复访问每个页面才能提取所有产品。

这意味着只要还有可用页面,我们的爬虫就会执行一些递归步骤。要将这一逻辑转化为代码,我们需要观察 HTML 是如何描述这些条件的。

若返回开发者控制台,你会发现每个页码实际上都是通往新页面的链接。不仅如此,鉴于我们当前位于首页且此前没有其他页面,左箭头按钮已被禁用。

因此,以下算法必须:

  • 访问该页面;
  • 提取数据(我们将在下一步实现此功能);
  • 在 HTML 文档中查找分页容器;验证“下一页”箭头是否禁用,若已禁用则停止,若未禁用,则获取新链接并调用新页面的爬取函数。
def start_crawling(soup, filename):

    extract_products(soup, filename)

    pagination = soup.find('ul', {'class': 'pagination-custom'})
    next_page = pagination.find_all('li')[-1]
    
    if next_page.has_attr('class'):
        if next_page['class'] == ['disabled']:
            print("You reached the last page. Stopping the crawler...")
    else:
        next_page_link = next_page.find('a')['href']
        next_page_address = BASE_URL + next_page_link
        next_page_index = next_page_link[next_page_link.find('=') + 1]
        crawl(next_page_address, f'etee-page{next_page_index}.txt')

提取数据并导出为 CSV

最后,让我们看看如何提取所需的数据。我们再仔细查看一下 HTML 文档,可以发现通过观察类名就能获取有价值的信息。

我们将提取产品的名称、评分、评论数量和价格,但您可以根据需要提取更多信息。

还记得我们之前创建的“products”文件夹吗?现在我们将创建一个 CSV 文件,用于导出从每个页面抓取的数据。该文件夹将帮助我们集中管理这些数据。

def extract_products(soup, filename):
    csv_filename = filename.replace('.txt', '.csv')
    products_file = open(f'products/{csv_filename}', mode='a', encoding='utf-8', newline='')
    products_writer = csv.writer(products_file, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL)
    products_writer.writerow(['Title', 'Rating', 'Reviews', 'Price on sale'])

    products = soup.find_all('div', {'class': 'product-grid-item'})
    for product in products:
        product_title = product.find('div', {'class': 'item-title'}).getText().strip()
        product_rating = product.find('span', {'class': 'jdgm-prev-badge__stars'})['data-score']
        product_reviews = product.find('span', {'class': 'jdgm-prev-badge__text'}).getText().strip()
        product_price_on_sale = product.find('span', {'class': 'money'}).getText()
        products_writer.writerow([product_title, product_rating, product_reviews, product_price_on_sale])

运行程序后,你可以在新创建的文件中看到所有提取的信息。

结语

大功告成!我们仅用不到 100 行代码,结合 Python 的 BeautifulSoup 和 WebScrapingAPI,就制作了自己的网页爬虫。当然,具体代码量可能因任务复杂度而异,但对于一个能够遍历网站页面的爬虫来说,这已经相当划算了。

在本指南中,我们使用了 WebScrapingAPI 的免费试用版,前 14 天提供 5000 次 API 调用,这完全足够构建一个功能强大的爬虫。  

专注于爬虫的逻辑本身,而不必担心网络爬取过程中遇到的各种难题,这非常有帮助。它为我们节省了时间、精力以及其他可观的成本,例如使用自有代理——这仅仅是使用网络爬取 API 所能获得的几个优势。

关于作者
Raluca Penciuc, 全栈开发工程师 @ WebScrapingAPI
Raluca Penciuc全栈开发工程师

Raluca Penciuc 是 WebScrapingAPI 的全栈开发工程师,主要负责开发爬虫、优化规避机制,并探索可靠的方法以降低在目标网站上的被检测概率。

开始构建

准备好扩展您的数据收集规模了吗?

加入2,000多家企业,使用WebScrapingAPI在无需任何基础设施开销的情况下,以企业级规模提取网络数据。