前言

  在日常开发中,我们经常需要从网页上批量获取数据。手动复制粘贴效率太低,而Python的requests和BeautifulSoup组合就是最简单高效的网页抓取方案。本文将手把手带你完成一个完整的爬虫实例。

  1. 环境准备

  pip install requests beautifulsoup4 lxml

  - requests:发送HTTP请求
  - beautifulsoup4:解析HTML文档
  - lxml:高性能解析器(比默认解析器快很多)

  2. 发送请求获取网页内容

  import requests

  url = "https://quotes.toscrape.com/"  # 一个专门用于爬虫练习的网站

  headers = {
      "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
  }

  response = requests.get(url, headers=headers)
  response.encoding = "utf-8"

  print(f"状态码: {response.status_code}")
  print(f"网页长度: {len(response.text)} 字符")

  ▎ 注意: 添加User-Agent头部是为了模拟浏览器访问,避免被网站识别为爬虫直接拒绝。

  3. 使用BeautifulSoup解析HTML

  from bs4 import BeautifulSoup

  soup = BeautifulSoup(response.text, "lxml")

  # 提取所有名言
  quotes = soup.find_all("div", class_="quote")

  for quote in quotes:
      text = quote.find("span", class_="text").get_text()
      author = quote.find("small", class_="author").get_text()
      tags = [tag.get_text() for tag in quote.find_all("a", class_="tag")]

      print(f"名言: {text}")
      print(f"作者: {author}")
      print(f"标签: {', '.join(tags)}")
      print("-" * 50)

  4. 翻页抓取多页数据

  all_quotes = []

  for page in range(1, 4):  # 抓取前3页
      url = f"https://quotes.toscrape.com/page/{page}/"
      response = requests.get(url, headers=headers)
      soup = BeautifulSoup(response.text, "lxml")

      quotes = soup.find_all("div", class_="quote")
      for quote in quotes:
          data = {
              "text": quote.find("span", class_="text").get_text(),
              "author": quote.find("small", class_="author").get_text(),
              "tags": [tag.get_text() for tag in quote.find_all("a", class_="tag")]
          }
          all_quotes.append(data)

      print(f"第{page}页抓取完成,本页{len(quotes)}条数据")

  print(f"总共抓取 {len(all_quotes)} 条名言")

  5. 保存数据到文件

  import json
  import csv

  # 保存为JSON
  with open("quotes.json", "w", encoding="utf-8") as f:
      json.dump(all_quotes, f, ensure_ascii=False, indent=2)

  # 保存为CSV
  with open("quotes.csv", "w", encoding="utf-8", newline="") as f:
      writer = csv.DictWriter(f, fieldnames=["text", "author", "tags"])
      writer.writeheader()
      for item in all_quotes:
          item["tags"] = ", ".join(item["tags"])
          writer.writerow(item)

  print("数据已保存到 quotes.json 和 quotes.csv")

  6. 常用技巧总结

  ┌───────────┬────────────────────────────────────────────────────┐
  │   技巧    │                        说明                        │
  ├───────────┼────────────────────────────────────────────────────┤
  │ 添加延时  │ time.sleep(1) 避免请求过快被封IP                   │
  ├───────────┼────────────────────────────────────────────────────┤
  │ 异常处理  │ 用try-except包裹请求,防止单个页面失败导致整体中断 │
  ├───────────┼────────────────────────────────────────────────────┤
  │ 代理IP    │ requests.get(url, proxies={"http": "ip:port"})     │
  ├───────────┼────────────────────────────────────────────────────┤
  │ CSS选择器 │ soup.select("div.quote > span.text") 更灵活        │
  └───────────┴────────────────────────────────────────────────────┘

  # 完整的异常处理模板
  import time

  for page in range(1, 10):
      try:
          response = requests.get(url, headers=headers, timeout=10)
          # 解析逻辑...
          time.sleep(1)  # 每次请求间隔1秒
      except requests.RequestException as e:
          print(f"第{page}页请求失败: {e}")
          continue

  结语

  requests + BeautifulSoup 是Python爬虫入门的最佳组合,上手简单、功能强大。掌握这两个库后,你就可以批量获取各种公开网页数据了。后续可以学习Scrapy框架来处理更复杂的爬虫项目。

更多推荐