一、基本定义
网络爬虫(Web Crawler) 是一种自动化程序,能够模拟人类浏览网页的行为,从互联网上自动抓取、解析和存储所需信息。Python爬虫特指使用Python语言编写的这类程序。
二、典型应用场景
搜索引擎:构建网页索引库
数据分析:采集市场/社交/金融数据
价格监控:电商平台比价系统
内容聚合:新闻资讯整合
学术研究:文献数据收集
安全监测:网站漏洞扫描
三、爬虫类型分类
类型 | 特点 | 应用场景 |
通用爬虫 | 搜索引擎式全网抓取 | Google/Baidu搜索引擎 |
聚焦爬虫 | 针对特定主题/网站定向采集 | 价格监控、舆情分析 |
增量式爬虫 | 只抓取更新内容 | 新闻网站监控 |
深层爬虫 | 突破网站层级限制 | 垂直领域数据采集 |
分布式爬虫 | 多节点协同工作 | 大规模数据采集任务 |
四、爬虫流程
爬虫的工作流程可概括为"请求-响应-解析-存储"四步循环:
1)发送 HTTP 请求
爬虫通过 HTTP 请求从目标网站获取 HTML 页面,常用的库包括 requests。
2)解析 HTML 内容
获取 HTML 页面后,爬虫需要解析内容并提取数据,常用的库有 BeautifulSoup、lxml、Scrapy 等。
3)提取数据
通过定位 HTML 元素(如标签、属性、类名等)来提取所需的数据。
4)存储数据
将提取的数据存储到数据库、CSV 文件、JSON 文件等格式中,以便后续使用或分析。
五、常见的请求头和响应头
1)常见的请求头(Request Headers):
1. User-Agent: 用户代理。标识客户端类型(浏览器、操作系统等)。爬虫中常用来伪装成浏览器。
2. Accept: 告诉服务器客户端能够处理的内容类型,如text/html, application/json等。
3. Accept-Language: 客户端接受的语言。
4. Accept-Encoding: 客户端接受的编码方式(如gzip, deflate),服务器可能以此方式压缩响应。
5. Referer: 表示当前请求是从哪个页面链接过来的。
6. Connection: 控制本次请求后的连接状态,如keep-alive表示保持连接。
7. Host: 请求的目标主机名和端口号。
8. Cookie: 用于携带服务器之前设置的Cookie信息,维持会话状态。
9. Content-Type: 在POST请求中常见,表示请求体的数据类型(如application/x-www-form-urlencoded, application/json)。
10. Authorization: 用于身份验证,如Bearer token或Basic认证。
#请求头示例
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': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
'Referer': 'https://www.google.com/',
'Cookie': 'session_id=abc123; user_token=xyz456'}
response = requests.get('https://example.com', headers=headers)
2)常见的响应头(Response Headers):
1. Content-Type: 响应体的内容类型(如text/html; charset=utf-8)。
2. Content-Length: 响应体的长度(字节)。
3. Content-Encoding: 响应体的编码方式(如gzip),需要客户端解压。
4. Set-Cookie: 服务器设置Cookie,后续请求可通过Cookie头带回。
5. Server: 服务器软件信息(如Apache, Nginx)。
6. Date: 响应生成的日期和时间。
7. Cache-Control: 控制缓存的行为(如no-cache, max-age=3600)。
8. Expires: 响应过期的日期和时间(旧版HTTP)。
9. Location: 在重定向响应(3xx)中,表示新的URL。
10. Access-Control-Allow-Origin: CORS(跨域资源共享)相关,指定哪些站点可以跨域访问资源。
在爬虫中,我们经常需要设置请求头来模拟浏览器行为,避免被服务器识别为爬虫。同时,通过分析响应头,我们可以正确处理响应内容(如解压、编码)以及处理重定向和会话状态。
#响应头示例
content_type = response.headers.get('ContentType')
if 'application/json' in content_type:
data = response.json()
elif 'text/html' in content_type:
soup = BeautifulSoup(response.text, 'html.parser')
# 处理重定向
if response.status_code in (301, 302, 303, 307, 308):
redirect_url = response.headers['Location']
print(f"重定向至: {redirect_url}")
# 处理Cookie
if 'Set-Cookie' in response.headers:
cookies = response.cookies
# 保存Cookie用于后续请求
六、响应状态码
在 Python 爬虫开发中,理解 HTTP 响应状态码至关重要。这些三位数字代码直观地反映了服务器对请求的处理结果,是爬虫错误处理和逻辑控制的核心依据。状态码分为五大类,覆盖了从成功响应到服务器错误的各种情况。
状态码 | 名称 | 含义 | 爬虫处理策略 |
200 | OK | 请求成功,响应体中包含请求的资源 | 正常解析内容 |
201 | Created | 资源创建成功(常见于POST请求) | 获取响应中的资源位置 |
204 | No Content | 请求成功,但响应体无内容 | 继续后续操作 |
301 | Moved Permanently | 资源永久重定向 | 更新书签,后续请求直接访问新URL |
302 | Found | 资源临时重定向 | 跟随重定向,但保留原URL |
304 | Not Modified | 资源未修改(配合If-Modified-Since使用) | 使用本地缓存内容 |
307 | Temporary Redirect | 临时重定向(保持原请求方法) | 保持原请求方法重试 |
308 | Permanent Redirect | 永久重定向(保持原请求方法) | 更新书签并保持原方法 |
400 | Bad Request | 请求语法错误 | 检查请求参数格式(特别是POST数据) |
401 | Unauthorized | 未认证/认证失败 | 添加身份验证头(Authorization) |
403 | Forbidden | 服务器拒绝请求(无权限) | 检查Cookie/Referer,尝试伪装浏览器 |
404 | Not Found | 资源不存在 | 放弃请求,记录错误 |
405 | Method Not Allowed | 请求方法不被允许 | 更换HTTP方法(如POST改为GET) |
408 | Request Timeout | 请求超时 | 增加超时时间重试 |
429 | Too Many Requests | 请求过于频繁 | 关键:降低请求频率,添加随机延迟 |
500 | Internal Server Error | 服务器内部错误 | 稍后重试(指数退避策略) |
502 | Bad Gateway | 网关错误(上游服务器无效响应) | 等待后重试 |
503 | Service Unavailable | 服务不可用(服务器过载或维护) | 检查Retry-After头,按建议时间重试 |
504 | Gateway Timeout | 网关超时 | 增加超时时间重试 |
七、爬虫示例(爬取小说)
通过爬虫代码,爬取(三国演义全文_古诗文网)
首先拿到网址后,打开f12,观察请求头请求方法,可以看到请求方法是get。
然后定位资源位置,此处得到每个章节对应的url
打开url后得到我们所需的资源
import requests
from bs4 import BeautifulSoup
# 1、通过url获取资源
url = r'https://www.gushiwen.cn/guwen/book_46653FD803893E4F7F702BCF1F7CCE17.aspx'
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0"}
page_text = requests.get(url=url, headers=headers).text
# 2、保存每个小章节的url
soup = BeautifulSoup(page_text, 'lxml')
li = soup.select('body > div.main3 > div > div.sons > div > ul > span')
# 3、保存文档
fp = open('./爬取文件/sanguo.txt','w', encoding='utf-8')
for i in li:
detail_url = 'https://www.gushiwen.cn' + i.a['href'] # 每个章节的url
detail_title = i.a.string # 对应的章节
detail_text = requests.get(url=detail_url,headers=heads).text
detail_soup = BeautifulSoup(detail_text, 'lxml')
div_tag = detail_soup.find_all('p')
fp.write(detail_title)
for i in div_tag:
contson = i.text
fp.write(contson + '\n')
print(f'{detail_title}爬取成功!!')
fp.close()