第4章:Web数据采集基础
说实话,做数据采集这些年,我踩过的坑比走过的路还多。但Web采集这块,只要你把基础打牢了,后面就顺了。今天咱们就聊聊HTTP协议、HTML基础、静态页面抓取和动态页面抓取这四块内容。
4.1 HTTP协议与请求响应模型
HTTP协议,说白了就是浏览器和服务器之间对话的规矩。你想想看,你在浏览器输入一个网址,回车,页面就出来了。这背后发生了什么?
我习惯把HTTP请求比作点外卖:
- 客户端(浏览器):你就是那个饿了的食客
- 服务器:后厨的厨师
- HTTP请求:你下的单
- HTTP响应:厨师做好的菜
一个完整的HTTP请求包含四部分:
请求行:GET /index.html HTTP/1.1
请求头:Host: www.example.com
User-Agent: Mozilla/5.0
Cookie: session_id=12345
空行
请求体:(GET请求没有,POST请求有数据)
响应也是类似的:
状态行:HTTP/1.1 200 OK
响应头:Content-Type: text/html
Content-Length: 1234
空行
响应体:<html>...</html>
重点记住几个状态码:
- 200:成功,一切正常
- 301/302:重定向,页面搬家了
- 403:禁止访问,你没权限
- 404:页面不存在
- 500:服务器内部错误
我在项目中遇到过最坑的事:爬一个电商网站,明明代码没问题,但就是拿不到数据。后来一查,原来是服务器返回了301重定向,我的代码没处理。嗯,从那以后我写爬虫第一件事就是检查状态码。
4.2 HTML/CSS基础与选择器
HTML是网页的骨架,CSS是衣服。你要抓数据,首先得知道数据长什么样。
一个典型的HTML结构:
<!DOCTYPE html>
<html>
<head>
<title>商品列表</title>
</head>
<body>
<div class="product">
<h2 class="name">iPhone 15</h2>
<span class="price">¥6999</span>
<a href="/detail/123">查看详情</a>
</div>
</body>
</html>
CSS选择器是定位元素的利器。我个人最常用的几种:
| 选择器 | 示例 | 说明 |
|---|---|---|
| 标签选择器 | div | 选中所有div标签 |
| 类选择器 | .price | 选中class="price"的元素 |
| ID选择器 | #main | 选中id="main"的元素 |
| 后代选择器 | div .price | 选中div内部的.price元素 |
| 属性选择器 | [href] | 选中所有带href属性的元素 |
小技巧:在浏览器按F12打开开发者工具,用Elements面板可以直接右键复制CSS选择器。我刚开始学的时候全靠这个功能,省了不少事。
4.3 静态网页抓取(Requests+BeautifulSoup)
静态网页,就是内容直接写在HTML里的页面。这种最简单,用Requests拿HTML,用BeautifulSoup解析就行。
我写爬虫的标配代码:
import requests
from bs4 import BeautifulSoup
# 1. 发送请求
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}
url = 'https://example.com/products'
response = requests.get(url, headers=headers)
# 2. 检查状态
if response.status_code == 200:
print('请求成功!')
else:
print(f'请求失败,状态码:{response.status_code}')
# 3. 解析HTML
soup = BeautifulSoup(response.text, 'html.parser')
# 4. 提取数据
products = soup.select('.product')
for product in products:
name = product.select_one('.name').text.strip()
price = product.select_one('.price').text.strip()
print(f'{name}: {price}')
这里有几个坑,我当年都踩过:
避坑指南:
- 一定要加User-Agent,不然很多网站直接拒绝你
- response.encoding要设置正确,中文乱码就靠它
- BeautifulSoup的解析器用'lxml'比'html.parser'快很多
我曾经爬一个新闻网站,数据总是少几条。排查了半天,发现是页面用了分页,我只抓了第一页。所以,记得检查页面有没有分页机制。
4.4 动态网页抓取(Selenium基础)
现在很多网站都用JavaScript动态加载数据。你直接拿Requests请求,HTML里啥都没有。这时候就得请出Selenium了。
Selenium说白了就是一个自动化浏览器工具。它能模拟真实用户的操作:点击、滚动、输入文字等等。
基本用法:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
# 启动浏览器
driver = webdriver.Chrome()
# 访问页面
driver.get('https://example.com')
# 等待元素加载
wait = WebDriverWait(driver, 10)
element = wait.until(
EC.presence_of_element_located((By.CLASS_NAME, 'product'))
)
# 获取数据
products = driver.find_elements(By.CLASS_NAME, 'product')
for product in products:
name = product.find_element(By.CLASS_NAME, 'name').text
print(name)
# 关闭浏览器
driver.quit()
什么时候用Selenium?
- 页面内容是通过AJAX异步加载的
- 需要模拟用户操作(点击、滚动、翻页)
- 页面有复杂的JavaScript渲染
- 需要处理登录、验证码等交互
但Selenium也有缺点:慢、吃内存。我建议能用Requests解决的,就别用Selenium。杀鸡不用牛刀嘛。
最后,我画了一张图,把今天讲的内容串起来:
这张图把整个流程串起来了。你想想看,从分析页面开始,判断是静态还是动态,然后选择对应的工具去抓取,最后把数据存起来。每一步都有对应的技术选型。
好了,这一章的内容就到这。记住一句话:Web采集没有银弹,理解原理比背代码更重要。遇到问题多想想HTTP协议,多看看HTML结构,很多问题自然就解决了。
公众号:蓝海资料掘金营,微信deep3321