杰瑞科技汇

requests超市是什么?

“超市”是一个非常宽泛的概念,它可能指:

requests超市是什么?-图1
(图片来源网络,侵删)
  1. 大型连锁超市的官方网站:如沃尔玛、家乐福、永辉等,这些网站通常有反爬虫机制,需要更复杂的技术。
  2. 在线生鲜/超市平台:如盒马、叮咚买菜、美团买菜等,这些是 API 驱动的,爬取它们的 API 数据是最高效的方式。
  3. 某个具体的、规模较小的本地超市网站:这种网站可能结构简单,是学习 requests 的绝佳入门案例。

下面,我将从最简单、最推荐的方式(爬取 API)开始,然后讲解如何爬取传统的网页,并最后提供一个完整的项目示例。


核心概念:requests

requests 是 Python 中最著名的 HTTP 库,它极大地简化了发送 HTTP 请求的过程,在爬虫中,我们用它来向服务器“请求”网页或数据。

主要功能

  • requests.get(url): 发送 GET 请求,用于获取网页或数据。
  • requests.post(url, data): 发送 POST 请求,常用于提交表单。
  • response.status_code: 获取响应状态码,200 表示成功。
  • response.text: 获取响应的文本内容(HTML 或 JSON)。
  • response.json(): 将响应内容直接解析为 Python 字典或列表(如果内容是 JSON 格式)。
  • response.headers: 获取响应头信息。
  • response.cookies: 获取响应的 cookies。

爬取在线超市的 API 数据 (推荐)

现代网站为了实现前后端分离,其数据通常通过 API 接口以 JSON 格式提供,这种方式比解析 HTML 简单得多,因为数据结构是固定的。

requests超市是什么?-图2
(图片来源网络,侵删)

目标:获取某个商品列表页面的商品名称、价格和图片链接。

步骤

  1. 找到 API 接口

    • 打开你想要爬取的超市网站(一个虚构的 supermarket-api.com)。
    • 打开浏览器的“开发者工具”(通常按 F12 或右键 -> 检查)。
    • 切换到 "Network" (网络) 标签页。
    • 刷新页面或进行一些操作(如下拉加载更多商品)。
    • 在网络请求列表中,寻找那些返回数据格式为 JSON 的请求,它们的 URL 通常包含 api, data, product 等关键词,响应类型是 application/json

    假设我们找到了这样一个 API:

    requests超市是什么?-图3
    (图片来源网络,侵删)
    • URL: https://api.supermarket-api.com/v1/products?page=1&limit=20
    • 请求方法: GET
    • (JSON):
      {
        "status": "success",
        "data": {
          "products": [
            {
              "id": 101,
              "name": "有机新鲜苹果",
              "price": 15.8,
              "unit": "500g",
              "image_url": "https://cdn.supermarket-api.com/imgs/apple.jpg"
            },
            {
              "id": 102,
              "name": "纯牛奶",
              "price": 68.0,
              "unit": "1L*12盒",
              "image_url": "https://cdn.supermarket-api.com/imgs/milk.jpg"
            }
            // ... 更多商品
          ]
        }
      }
  2. 编写 Python 代码

    import requests
    import json # 用于美化打印 JSON,非必需
    # 1. 定义 API 的 URL
    api_url = "https://api.supermarket-api.com/v1/products?page=1&limit=20"
    try:
        # 2. 发送 GET 请求
        # headers 可以模拟浏览器访问,避免被简单识别为爬虫
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
        }
        response = requests.get(api_url, headers=headers)
        # 3. 检查请求是否成功
        # response.raise_for_status() 会在状态码不是 2xx 时抛出异常
        response.raise_for_status()
        # 4. 解析 JSON 数据
        # requests 库的 .json() 方法会自动将响应内容转为 Python 字典
        data = response.json()
        # 5. 提取并打印我们想要的信息
        if data.get("status") == "success":
            products = data["data"]["products"]
            print(f"成功获取到 {len(products)} 个商品信息:\n")
            for product in products:
                name = product.get("name")
                price = product.get("price")
                unit = product.get("unit")
                image_url = product.get("image_url")
                print(f"商品名称: {name}")
                print(f"价格: ¥{price} / {unit}")
                print(f"图片链接: {image_url}")
                print("-" * 30)
    except requests.exceptions.HTTPError as http_err:
        print(f"HTTP 错误发生: {http_err}")
    except requests.exceptions.RequestException as err:
        print(f"请求发生错误: {err}")
    except json.JSONDecodeError:
        print("响应内容不是有效的 JSON 格式")
    

优点

  • 数据结构清晰:JSON 对应 Python 字典,解析非常方便。
  • 效率高:只传输数据,没有多余的 HTML 标签,流量小,速度快。
  • 稳定:网站改版通常不会轻易改动其核心 API。

爬取传统网页的 HTML 内容

如果目标网站没有提供 API,或者你无法找到它,那么就需要解析返回的 HTML 页面,这通常需要另一个库 BeautifulSouplxml

目标:获取一个超市网页上所有商品的名称和价格。

步骤

  1. 分析网页结构

    • 在浏览器中打开目标商品页面。
    • 右键点击一个商品名称 -> “检查”,找到包裹该名称的 HTML 标签和类名(class)或 ID。
    • 同样,找到价格所在的标签和类名。

    假设我们发现:

    • 每个商品都在一个 <div class="product-item"> 容器里。
    • 商品名称在 <h3 class="product-name">...</h3> 中。
    • 商品价格在 <span class="product-price">...</span> 中。
  2. 编写 Python 代码

    import requests
    from bs4 import BeautifulSoup # 需要先安装: pip install beautifulsoup4
    # 1. 定义目标网页的 URL
    html_url = "https://www.some-supermarket.com/products/fresh-fruit"
    try:
        # 2. 发送 GET 请求获取 HTML
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
        }
        response = requests.get(html_url, headers=headers)
        response.raise_for_status() # 检查请求是否成功
        # 3. 使用 BeautifulSoup 解析 HTML
        # 'html.parser' 是 Python 内置的解析器,也可以用 'lxml' (更快,需额外安装)
        soup = BeautifulSoup(response.text, 'html.parser')
        # 4. 使用 CSS 选择器查找所有商品
        # .product-item 会查找所有 class 为 "product-item" 的标签
        product_items = soup.find_all('div', class_='product-item')
        print(f"在页面上找到 {len(product_items)} 个商品:\n")
        # 5. 遍历每个商品,提取信息
        for item in product_items:
            # 在每个商品容器内查找名称和价格
            name_tag = item.find('h3', class_='product-name')
            price_tag = item.find('span', class_='product-price')
            # .get_text(strip=True) 可以获取标签内的文本并去除首尾空白
            name = name_tag.get_text(strip=True) if name_tag else "未找到名称"
            price = price_tag.get_text(strip=True) if price_tag else "未找到价格"
            print(f"商品名称: {name}")
            print(f"商品价格: {price}")
            print("-" * 30)
    except requests.exceptions.RequestException as err:
        print(f"请求发生错误: {err}")
    except Exception as e:
        print(f"解析页面时发生错误: {e}")
    

注意

  • 这种方法非常脆弱,一旦网站更新了 HTML 结构(比如改了 class 名),你的爬虫就会立刻失效。
  • 对于复杂的网站,JavaScript 动态加载的内容可能无法被 requests 直接获取,这时需要更高级的工具如 Selenium

完整项目示例:爬取超市商品并保存为 CSV

让我们将场景一和场景二结合起来,做一个更实用的例子:爬取数据并保存到 CSV 文件,方便用 Excel 查看。

目标:爬取 API 数据,并将结果保存为 supermarket_products.csv 文件。

准备工作

  1. 安装必要的库:
    pip install requests beautifulsoup4 pandas
    • requests: 发送请求。
    • beautifulsoup4: 虽然这个例子主要用 requests.json(),但保留它以防万一需要解析 HTML。
    • pandas: 处理数据并保存为 CSV 的神器。

代码 (supermarket_scraper.py)

import requests
import pandas as pd
import time
import random
# --- 配置 ---
# 假设的 API URL
BASE_API_URL = "https://api.supermarket-api.com/v1/products"
# 请求头,模拟浏览器
HEADERS = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
    'Accept': 'application/json, text/plain, */*'
}
# 要爬取的页数
PAGES_TO_SCRAPE = 5
# 输出文件名
OUTPUT_CSV_FILE = 'supermarket_products.csv'
def fetch_products_from_api(page):
    """从指定页面获取商品数据"""
    params = {
        'page': page,
        'limit': 20  # 每页20个商品
    }
    try:
        response = requests.get(BASE_API_URL, headers=HEADERS, params=params)
        response.raise_for_status()
        data = response.json()
        if data.get("status") == "success":
            return data["data"]["products"]
        else:
            print(f"第 {page} 页请求失败: {data.get('message')}")
            return []
    except requests.exceptions.RequestException as e:
        print(f"请求第 {page} 页时出错: {e}")
        return []
def main():
    """主函数"""
    all_products = []
    print(f"开始爬取,计划爬取 {PAGES_TO_SCRAPE} 页数据...")
    for page in range(1, PAGES_TO_SCRAPE + 1):
        print(f"正在爬取第 {page} 页...")
        products_on_page = fetch_products_from_api(page)
        if not products_on_page:
            print(f"第 {page} 页没有获取到数据,可能已到达最后一页。")
            break
        all_products.extend(products_on_page)
        # --- 礼貌性爬虫 ---
        # 随机暂停 1 到 3 秒,避免请求过于频繁被封 IP
        sleep_time = random.uniform(1, 3)
        print(f"等待 {sleep_time:.2f} 秒...")
        time.sleep(sleep_time)
    if not all_products:
        print("未能获取任何商品数据。")
        return
    print(f"\n爬取完成,共获取 {len(all_products)} 个商品。")
    # --- 使用 pandas 处理数据 ---
    # 将列表 of 字典 转换为 DataFrame
    df = pd.DataFrame(all_products)
    # 选择我们需要的列
    # 假设 API 返回的字段是 'name', 'price', 'unit', 'image_url'
    # 如果字段名不同,请根据实际情况修改
    desired_columns = ['name', 'price', 'unit', 'image_url']
    df = df[desired_columns]
    # 保存为 CSV 文件
    # index=False 表示不保存行索引 (0, 1, 2...)
    # encoding='utf-8-sig' 可以确保用 Excel 打开时中文不会乱码
    df.to_csv(OUTPUT_CSV_FILE, index=False, encoding='utf-8-sig')
    print(f"数据已成功保存到文件: {OUTPUT_CSV_FILE}")
if __name__ == "__main__":
    main()

重要注意事项与最佳实践

  1. 合法性

    • 永远不要爬取有版权声明或明确禁止爬取的网站。
    • 查看网站的 robots.txt 文件(https://www.example.com/robots.txt),它规定了哪些页面不希望被爬虫访问。
    • 只爬取公开的、非私有的数据。
  2. 礼貌性爬虫

    • 设置 User-Agent:让你的请求看起来像来自普通浏览器。
    • 控制请求频率:使用 time.sleep() 在请求之间加入随机延迟,避免对服务器造成过大压力。
    • 处理 cookies 和 session:如果需要登录才能访问,要妥善处理 cookies。
  3. 反爬虫机制

    • IP 封禁:如果请求太频繁,你的 IP 可能会被暂时封禁,解决方案是使用代理 IP 池。
    • 验证码:当检测到异常行为时,网站会弹出验证码,这通常需要使用第三方识别服务或更高级的自动化工具(如 Selenium)。
    • 动态加载:数据由 JavaScript 生成,requests 无法获取,解决方案是使用 SeleniumPlaywright 等工具模拟浏览器行为。
  4. 数据存储

    • 对于少量数据,CSV 文件足够。
    • 对于大量数据,考虑使用数据库,如 SQLite (轻量级)、MySQL 或 PostgreSQL。

希望这份详细的指南能帮助你开始使用 Python requests 爬取超市数据!从爬取 API 开始是最佳实践,因为它更稳定、更高效。

分享:
扫描分享到社交APP
上一篇
下一篇