网络数据采集(爬虫基础)

课程定位

项目 内容
课程名称 网络数据采集(爬虫基础)
前置课程 Python基础
后续课程 数据清洗

教学目标

  1. 掌握网络爬虫的基本原理
  2. 理解HTTP协议及网页结构
  3. 熟练使用requests、BeautifulSoup、lxml/Xpath进行数据抓取

课程衔接

数据采集(爬虫) ──→ 数据存储 ──→ 数据清洗 ──→ 数据增广

第1部分爬虫原理与HTTP协议

1.1 为什么要学爬虫

  • 数据从哪里来
  • 爬虫在AI数据服务中的价值
  • 合法合规: robots.txt、爬虫协议

1.2 爬虫基本原理

什么是爬虫?

爬虫Crawler/Spider是一种自动化程序用于抓取互联网上的数据。

工作流程:

┌──────────┐    HTTP请求     ┌──────────┐    HTTP响应     ┌──────────┐
│  爬虫程序 │ ──────────────→ │  Web服务器 │ ──────────────→ │  爬虫程序 │
└──────────┘                  └──────────┘                  └──────────┘
       │                                                      │
       │                    ┌──────────┐                      │
       └──────────────────→│ 解析提取 │←─────────────────────┘
                            │ 保存数据 │
                            └──────────┘

爬虫的核心步骤:

  1. 发送请求向目标服务器发送HTTP请求
  2. 获取响应接收服务器返回的HTML/JSON等内容
  3. 解析数据:从响应中提取所需信息
  4. 保存数据将数据存储为CSV/JSON等格式

1.3 HTTP协议

请求与响应

  • 请求由请求行、请求头、请求体组成
  • 响应由状态行、响应头、响应体组成

GET与POST区别

方法 用途 参数位置 安全性
GET 获取数据 URL查询字符串 低(参数可见)
POST 提交数据 请求体中 高(参数不可见)

常见请求头

  • User-Agent:浏览器标识
  • Referer:请求来源页面
  • Cookie:会话跟踪

HTTP状态码

状态码 含义
200 请求成功
301/302 永久/临时重定向
403 禁止访问
404 页面不存在
500 服务器内部错误

1.4 网页结构基础

HTML

HTML是网页的结构标记语言。常用标签<div>, <span>, <a>, <p>, <table>, <li>

CSS选择器

通过class、id、标签名定位元素

  • .title —— class为title的元素
  • #header —— id为header的元素
  • a —— 所有a标签

XPath表达式

XML路径语言用于定位节点

表达式 含义
/html/body/div 从根节点开始的绝对路径
//div 任意位置的div标签
//div[@class="title"] class为title的div
//a/text() 获取a标签内的文本
//a/@href 获取a标签的href属性

DOM树

网页内容以树形结构组织,包括父节点、子节点、兄弟节点。


第2部分requests库

2.1 requests库简介

  • Python最流行的HTTP库
  • 简单易用的API设计
  • 支持HTTP/HTTPS协议

安装:

pip install requests

2.2 基本用法

import requests

# 发送GET请求
response = requests.get('https://example.com')

# 查看响应状态码
print(response.status_code)  # 200

# 查看响应内容(文本)
print(response.text)

# 查看响应内容JSON
print(response.json())

# 查看响应头
print(response.headers)

2.3 常用方法

方法 用途
requests.get() 发送GET请求
requests.post() 发送POST请求
requests.put() 发送PUT请求
requests.delete() 发送DELETE请求

2.4 常用属性

属性 用途
response.status_code HTTP状态码
response.text 响应内容(字符串)
response.content 响应内容(字节)
response.json() 响应内容JSON解析
response.headers 响应头
response.cookies Cookies

2.5 模拟浏览器请求

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
    'Referer': 'https://www.example.com',
}

response = requests.get(url, headers=headers)

2.6 带参数的请求

# URL查询参数
params = {'keyword': 'Python', 'page': 1}
response = requests.get('https://example.com/search', params=params)

# POST请求表单数据
data = {'username': 'test', 'password': '123456'}
response = requests.post('https://example.com/login', data=data)

2.7 Cookie与Session

# 设置Cookie
cookies = {'session_id': 'abc123'}
response = requests.get(url, cookies=cookies)

# 使用Session保持Cookie
session = requests.Session()
session.cookies.set('session_id', 'abc123')
response = session.get(url)

2.8 超时设置

response = requests.get(url, timeout=10)

第3部分BeautifulSoup库

3.1 BeautifulSoup简介

  • 用于解析HTML和XML的Python库
  • 提供导航、搜索、修改DOM树的功能
  • 常与requests配合使用

安装:

pip install beautifulsoup4 lxml

3.2 基本用法

from bs4 import BeautifulSoup

# 解析HTML使用lxml解析器
soup = BeautifulSoup(html_content, 'lxml')

解析器对比

解析器 速度 特点
lxml 推荐使用
html.parser Python内置
html5lib 最接近浏览器

3.3 查找元素

# 查找第一个匹配的元素
soup.find('div')                    # 标签名
soup.find('div', class_='title')    # 带class筛选
soup.find('div', id='header')        # 带id筛选

# 查找所有匹配的元素
soup.find_all('a')                   # 所有a标签
soup.find_all('a', limit=10)         # 限制数量

# CSS选择器推荐
soup.select('.title')                # class为title
soup.select('#header')               # id为header
soup.select('div a')                 # div下的a标签
soup.select('div > a')               # div直接子节点a

3.4 获取元素内容

# 获取文本
element.get_text()                   # 获取所有文本
element.string                       # 获取直接文本

# 获取属性
element['href']                      # 获取href属性
element.get('class')                 # 获取class属性

3.5 导航DOM树

# 向下导航
soup.head                            # head标签
soup.body                            # body标签
soup.div.p                           # 层层深入

# 向上/横向导航
element.parent                       # 父节点
element.next_sibling                 # 下一个兄弟元素

第4部分lxml库与XPath

4.1 lxml简介

  • 高性能的XML和HTML处理库
  • 支持XPath和XSLT
  • C语言实现速度快

安装:

pip install lxml

4.2 XPath基础语法

表达式 含义
/ 根节点
// 任意位置
. 当前节点
.. 父节点
@ 属性
* 任意元素
[n] 第n个元素从1开始

4.3 XPath示例

from lxml import etree

tree = etree.HTML(html_content)

# 基本路径
tree.xpath('//div')                  # 所有div标签
tree.xpath('//div/p')                 # div下的p标签

# 属性选择
tree.xpath('//div[@class="title"]')          # class等于title
tree.xpath('//div[contains(@class, "title")]')  # class包含title
tree.xpath('//a[@href]')             # 有href属性的a标签

# 获取文本
tree.xpath('//div/text()')           # div内的文本

# 获取属性
tree.xpath('//a/@href')              # 所有a标签的href属性

# 位置选择
tree.xpath('//li[1]')                # 第一个li
tree.xpath('//li[last()]')          # 最后一个li

# 逻辑运算
tree.xpath('//div[@id="main" and @class="content"]')

4.4 在Python中使用lxml

from lxml import etree

# 解析HTML字符串
html = '<html><body><div class="title">Hello</div></body></html>'
tree = etree.HTML(html)

# 获取元素
titles = tree.xpath('//div[@class="title"]')
for title in titles:
    print(title.text)                # 获取文本
    print(title.get('class'))        # 获取属性

# 获取文本内容(安全方式)
text = tree.xpath('string(//div[@class="title"])')

4.5 lxml与BeautifulSoup对比

特性 BeautifulSoup lxml
API设计 面向对象,友好 XPath表达式
速度 较慢
灵活性
适用场景 复杂DOM结构 结构清晰的页面

第5部分实战案例

爬取电影评分数据

import requests
from bs4 import BeautifulSoup
import csv
import time

# 1. 发送请求
url = 'https://movie.douban.com/top250'
headers = {'User-Agent': 'Mozilla/5.0...'}
response = requests.get(url, headers=headers)

# 2. 解析数据
soup = BeautifulSoup(response.text, 'lxml')
movies = []

for item in soup.select('.item'):
    title = item.select_one('.title').get_text()
    rating = item.select_one('.rating_num').get_text()
    quote = item.select_one('.inq').get_text() if item.select_one('.inq') else ''
    
    movies.append({
        'title': title.strip(),
        'rating': rating,
        'quote': quote
    })

# 3. 保存为CSV
with open('movies.csv', 'w', newline='', encoding='utf-8') as f:
    writer = csv.DictWriter(f, fieldnames=['title', 'rating', 'quote'])
    writer.writeheader()
    writer.writerows(movies)

print(f'已保存 {len(movies)} 部电影到 movies.csv')

使用lxml/XPath的写法

import requests
from lxml import etree

url = 'https://movie.douban.com/top250'
headers = {'User-Agent': 'Mozilla/5.0...'}

response = requests.get(url, headers=headers)
tree = etree.HTML(response.text)

# 使用XPath提取数据
movies = []
for item in tree.xpath('//div[@class="item"]'):
    title = item.xpath('.//span[@class="title"]/text()')
    rating = item.xpath('.//span[@class="rating_num"]/text()')
    
    if title and rating:
        movies.append({
            'title': title[0],
            'rating': rating[0]
        })

print(f'共提取 {len(movies)} 部电影')

进阶技巧

  • 分页爬取
  • 错误处理与重试
  • 爬取间隔(防止被封)

第6部分数据存储

CSV存储

import pandas as pd
df = pd.DataFrame(movies)
df.to_csv('data.csv', index=False, encoding='utf-8-sig')

JSON存储

import json
with open('data.json', 'w', encoding='utf-8') as f:
    json.dump(movies, f, ensure_ascii=False, indent=2)

Excel存储

df.to_excel('data.xlsx', index=False)

核心库总结

库名 功能定位 适用场景
requests HTTP请求库 发送网络请求,获取网页内容
BeautifulSoup HTML/XML解析库 解析HTML提取数据支持CSS选择器
lxml XML/HTML处理库 高性能解析支持XPath
XPath 路径查询语言 精确快速定位XML/HTML中的元素

推荐组合:

  • 新手入门requests + BeautifulSoupCSS选择器更直观
  • 进阶开发requests + lxmlXPath更强大速度更快

所需安装的Python库

pip install requests beautifulsoup4 lxml pandas openpyxl
Description
数据爬取学习材料
Readme 29 KiB
Languages
Python 100%