Python爬虫学习

0 阅读25分钟

第一章 爬虫基础认知与环境配置

爬虫核心本质就是模拟浏览器,自动向网站服务器发送网络请求,获取网页数据后筛选、提取、保存有效内容。人工浏览网页是手动请求,爬虫是代码自动化批量执行这一流程。

完整核心流程:发送网络请求 → 获取网页源码 → 解析有效数据 → 数据去重 → 持久化存储

术语注释:服务器,存放网站所有网页、数据的远程主机,爬虫所有访问、数据获取操作,都是与服务器进行数据交互。

1.1 爬虫合规边界(必守规则)

爬虫技术本身合规,但爬取行为有明确约束,新手必须牢记三点:

1. 严禁爬取个人隐私、付费专属、涉密、版权保护数据;

2. 控制请求频率,禁止高频暴力请求,避免占用服务器资源、造成网站瘫痪;

3. 优先遵守网站robots协议(域名+/robots.txt),只爬取公开允许访问的目录。

1.2 必备依赖库安装

全文所有代码依赖以下工具库,终端执行一次即可永久使用,网络卡顿可切换国内镜像源安装。

pip install requests lxml beautifulsoup4 selenium openpyxl

核心库作用(精简版)

requests:爬虫核心请求库,负责发送网络请求、获取网页数据;

lxml:高效网页解析引擎,支持XPath精准定位数据;

beautifulsoup4:新手友好型解析工具,语法简洁易上手;

selenium:模拟真实浏览器,加载解析JS动态渲染页面;

openpyxl:读写Excel文件,实现表格数据存储。

1.3 本章常见坑点

1. 初次学习直接高频循环爬取,无任何延时伪装,极易触发网站IP封禁;

2. 忽略robots协议,违规爬取受限页面,存在合规风险;

3. 库安装失败多为网络超时、pip环境异常,优先切换镜像源排查。

1.4 高频面试/笔试真题(含答案)

题目1:简述Python爬虫完整工作流程

答案:模拟浏览器向目标服务器发送网络请求,接收并获取网页源码,通过解析工具筛选提取文本、链接、图片等有效数据,完成数据去重后,将数据持久化保存到文件或数据库中。

题目2:requests和selenium核心区别与适用场景

答案:requests是轻量请求库,仅获取静态网页源码,运行速度快、效率高,适配纯静态页面爬取;selenium模拟完整浏览器运行,可加载JS动态数据,适配动态页面,但运行速度慢、资源占用高。

题目3:爬虫合规使用的核心原则

答案:遵守网站robots协议,不窃取隐私、付费、涉密数据;控制请求频率,不恶意攻击服务器;商用爬取数据需获取网站官方授权。

第二章 requests库请求实操(静态爬虫核心)

静态页面数据直接写入网页源码,无需JS渲染,是新手入门最基础的爬取场景,requests库是静态爬虫的核心工具,所有静态爬取逻辑均基于GET、POST两种请求实现。

术语注释:请求头(Headers),发送网络请求时携带的身份信息,用于告知服务器访问终端类型,伪装浏览器请求头可规避绝大多数基础反爬。

2.1 GET请求(数据获取,高频使用)

GET请求用于单纯获取网站数据,日常网页浏览、关键词搜索、分页查看内容均为GET请求,参数直接展示在URL中。

import requests

# 目标网址
url = "https://www.baidu.com"
# 伪装浏览器请求头(基础反爬必备)
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
}

# 发送请求
response = requests.get(url=url, headers=headers)
# 统一编码,解决中文乱码
response.encoding = "utf-8"

# 输出数据
print("网页源码:", response.text)
print("响应状态码:", response.status_code)

2.2 响应对象核心属性

爬虫数据获取、状态判断必备属性,无冗余功能,全部为实战高频用法:

response.text:解码后的网页文本,用于提取文字、源码数据;

response.content:原始二进制数据,用于下载图片、视频、文件;

response.status_code:请求状态码,200=成功、404=页面不存在、403=被禁止访问;

response.headers:服务器返回的响应信息。

2.3 带参数GET请求(搜索/分页场景)

适用于网页搜索、分页爬取场景,通过params参数自动拼接URL参数,规避手动拼接的符号、空格错误。

import requests

url = "https://www.baidu.com/s"
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
}
# 搜索参数:wd=搜索关键词,pn=分页偏移量
params = {"wd": "python爬虫", "pn": 0}

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

2.4 POST请求(数据提交场景)

POST请求用于向服务器提交数据,如账号登录、表单提交、内容上传,参数存储在请求体中,不会展示在URL中,私密性更强。

import requests

url = "https://httpbin.org/post"
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
}
# 提交的表单数据
data = {"username": "test", "password": "123456"}

response = requests.post(url=url, headers=headers, data=data)
print(response.text)

2.5 本章常见坑点

1. 裸请求不配置User-Agent,直接被服务器识别为爬虫,返回403禁止访问;

2. 未手动设置编码,网页中文全部乱码,无法解析有效数据;

3. GET请求手动拼接参数,极易出现格式错误,优先使用params自动拼接;

4. 不判断状态码,请求失败后仍强行解析数据,导致代码报错。

2.6 高频面试/笔试真题(含答案)

题目1:GET和POST请求的区别与爬虫适用场景

答案:GET为数据读取请求,参数暴露在URL,无请求体,速度快,适合静态页面爬取、搜索、分页场景;POST为数据提交请求,参数存于请求体,私密性强,适合模拟登录、表单提交、数据上传场景。

题目2:爬虫中User-Agent的核心作用

答案:用于伪装客户端身份,屏蔽requests默认的爬虫标识,模拟真实浏览器访问,规避网站基础身份校验反爬机制。

题目3:text和content属性的使用区别

答案:text是解码后的字符串,用于提取网页文字数据;content是原始二进制字节数据,专门用于下载图片、视频、压缩包等文件。

题目4:200、403、404状态码含义

答案:200代表请求成功,数据正常获取;403代表请求被服务器拦截,大概率触发反爬;404代表目标网址错误、页面不存在。

第三章 网页数据解析(XPath+BeautifulSoup)

requests仅能获取完整网页源码,源码包含大量无用标签、冗余代码,解析工具的核心作用是精准筛选出标题、文本、链接、图片地址等有效数据,是爬虫从“获取源码”到“提取数据”的关键步骤。

术语注释:解析树,将杂乱无序的网页源码,整理成层级清晰的树形结构,让代码可以精准定位任意标签和对应内容。

3.1 XPath精准解析(高效首选)

XPath是爬虫主流解析语法,定位精准、运行速度快,适配绝大多数网页,搭配lxml库使用,适合批量提取数据。

核心常用语法

//标签名:全局匹配所有对应标签;/text():提取标签内文本;/@属性:提取标签属性(链接、图片地址);[@属性=值]:精准筛选指定标签。

import requests
from lxml import etree

url = "https://www.baidu.com"
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
}
response = requests.get(url, headers=headers)
response.encoding = "utf-8"

# 构建网页解析树
tree = etree.HTML(response.text)
# 精准提取网页标题
title = tree.xpath("//title/text()")[0]
print("网页标题:", title)

3.2 BeautifulSoup解析(新手友好)

语法贴合Python原生逻辑,通俗易懂,无需记忆复杂语法,适合新手快速完成简单页面的数据提取。

import requests
from bs4 import BeautifulSoup

url = "https://www.baidu.com"
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
}
response = requests.get(url, headers=headers)
response.encoding = "utf-8"

# 初始化解析器
soup = BeautifulSoup(response.text, "lxml")
# 提取标题
title = soup.title.string
print("网页标题:", title)

3.3 批量数据提取实战

适配爬虫高频的列表数据爬取场景,批量提取页面所有链接数据。

import requests
from lxml import etree

url = "https://www.baidu.com"
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
}
response = requests.get(url, headers=headers)
tree = etree.HTML(response.text)

# 批量提取页面所有超链接
link_list = tree.xpath("//a/@href")
for link in link_list:
    print(link)

3.4 本章常见坑点

1. XPath语法错误、标签层级匹配失误,导致返回空列表,无法提取数据;

2. 误将JS动态数据当作静态数据解析,静态源码无目标数据,误以为语法出错;

3. 提取数据后不做空值、去重判断,保存大量无效冗余数据;

4. BeautifulSoup解析器选错,统一使用lxml解析器避免报错。

3.5 高频面试/笔试真题(含答案)

题目1:XPath和BeautifulSoup优缺点对比

答案:XPath优点是定位精准、解析速度快、支持复杂层级筛选,适合批量爬取;缺点是需要记忆语法。BeautifulSoup优点是语法简单、新手易上手、可读性强;缺点是复杂页面解析效率低于XPath。

题目2:XPath中 / 和 // 的核心区别

答案:/ 是绝对路径,从网页根节点逐层匹配;// 是相对路径,全局模糊匹配所有符合条件的标签,爬虫90%场景使用//。

题目3:数据解析返回空列表的核心原因

答案:一是XPath语法或标签属性匹配错误;二是目标数据为JS动态渲染,静态源码无数据;三是网页结构改版,原有定位规则失效。

题目4:text()和属性提取的使用场景

答案:text()用于提取标签内的文字内容;@属性用于提取标签的链接、图片地址、class、id等属性信息。

第四章 爬虫数据持久化存储

爬取的内存数据程序结束后会自动丢失,持久化存储的作用是将数据保存到本地文件,实现数据留存。本章整合爬虫三大主流存储方式,覆盖新手所有实战场景。

4.1 TXT文本存储(简易日志/文本数据)

操作最简单,适合临时存储简短文本、爬取日志,爬虫优先使用a追加模式,避免数据覆盖。

# a=追加写入,utf-8解决中文乱码
with open("爬虫文本数据.txt", "a", encoding="utf-8") as f:
    f.write("百度首页爬取成功\n")

模式说明:w=清空重写(慎用),a=追加写入(爬虫专用)

4.2 JSON存储(结构化数据首选)

适配字典、列表结构化数据,格式通用、可读性强,是爬虫结构化数据的标准存储方式。

import json

# 爬虫获取的结构化数据
spider_data = {
    "title": "百度首页",
    "url": "https://www.baidu.com",
    "status": "爬取成功"
}

# 写入JSON文件,ensure_ascii=False保留中文
with open("spider_data.json", "w", encoding="utf-8") as f:
    json.dump(spider_data, f, ensure_ascii=False, indent=2)

4.3 Excel表格存储(可视化报表数据)

适合需要统计、展示、复盘的爬虫数据,通过openpyxl库实现表格写入,适配所有新版Excel文件。

from openpyxl import Workbook

# 创建工作簿与工作表
wb = Workbook()
ws = wb.active
ws.title = "爬虫数据汇总"

# 写入表头+数据
ws.append(["网页标题", "链接地址", "爬取状态"])
ws.append(["百度首页", "https://www.baidu.com", "成功"])

# 保存文件
wb.save("爬虫数据表格.xlsx")

4.4 本章常见坑点

1. 未设置utf-8编码,所有中文数据乱码无法正常查看;

2. 循环爬取使用w重写模式,每次运行覆盖历史数据,仅保留最后一条;

3. JSON存储未加ensure_ascii=False,中文转为Unicode编码;

4. 循环内重复创建Excel工作簿,导致数据混乱、生成冗余文件。

4.5 高频面试/笔试真题(含答案)

题目1:三种本地存储方式的适用场景

答案:TXT用于临时文本、日志存储;JSON用于结构化、接口通用数据存储;Excel用于可视化报表、数据统计展示,海量数据场景需搭配数据库。

题目2:ensure_ascii参数的核心作用

答案:默认值为True,会将中文转为Unicode编码;设置为False可正常保存、显示中文,是JSON爬虫存储的必备参数。

题目3:循环写入数据被覆盖的解决办法

答案:原因是使用w重写模式,替换为a追加模式,即可实现多次运行、循环写入不覆盖历史数据。

第五章 基础反爬规避与请求伪装

网站为防止恶意批量爬取、服务器被攻击,会设置反爬机制识别拦截爬虫。新手无需掌握复杂加密破解,做好基础伪装和频率控制,可规避80%的基础反爬拦截。

术语注释:反爬,网站的安全防护机制,通过校验请求身份、频率、来源,区分真实用户和爬虫,拦截恶意访问请求。

5.1 完整请求头伪装

仅配置UA伪装效果有限,完善Headers参数,模拟真实浏览器完整请求信息,大幅降低被拦截概率。

import requests

url = "https://www.baidu.com"
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
    "Referer": "https://www.baidu.com",
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"
}

response = requests.get(url, headers=headers)
print("请求状态码:", response.status_code)

5.2 延时防封禁(频率控制)

代码请求速度远快于人工浏览,高频连续请求会直接封禁IP,添加随机延时模拟人工操作节奏,是低成本防封禁核心方案。

import requests
import time

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
}

# 多页循环爬取
for page in range(1, 4):
    url = f"https://www.baidu.com/s?wd=python&pn={page*10}"
    res = requests.get(url, headers=headers)
    print(f"第{page}页爬取成功")
    # 固定延时,可改为随机延时更逼真
    time.sleep(1.5)

5.3 本章常见坑点

1. 仅配置UA,缺失Referer、Accept等参数,伪装不完整,仍会被反爬识别;

2. 无延时循环爬取,短时间密集请求,直接触发IP封禁;

3. 请求头参数拼写、大小写错误,导致伪装失效。

5.4 高频面试/笔试真题(含答案)

题目1:网站基础反爬手段有哪些?

答案:常见基础反爬包括UA身份校验、请求来源Referer校验、请求频率限制、IP封禁、Cookie登录态校验,高阶反爬包含验证码、JS参数加密、指纹校验等。

题目2:爬虫添加延时的核心意义

答案:模拟人工浏览网页的操作节奏,降低请求频率,避免短时间密集请求触发反爬,有效防止IP被封禁,提升爬虫稳定性。

题目3:Referer请求头的作用

答案:标识当前请求的来源页面,部分网站会拦截无来源、非法来源的请求,配置Referer可完善伪装逻辑,规避来源校验反爬。

第六章 会话保持与登录态爬取(Cookie/Session)

多数网站的核心数据、详情页面需要登录后才能访问,匿名请求无法获取有效数据。本章讲解Cookie和Session两种登录态维持方案,实现权限页面爬取。

术语注释:Cookie,网站存储在本地的小型文本数据,用于记录用户登录状态、浏览信息,短期有效;Session,服务端会话对象,自动管理Cookie,全程维持登录状态,无需手动配置。

6.1 手动Cookie登录爬取

适合短期单次爬取,直接复制浏览器登录后的Cookie,放入请求头即可携带登录态访问权限页面。

import requests

# 需登录权限的目标网址
url = "权限页面地址"
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
    "Cookie": "浏览器登录后复制的完整Cookie"
}

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

6.2 Session自动会话保持(长期爬取推荐)

Session会话对象可自动保存、携带登录Cookie,一次模拟登录后,全程保持登录状态,无需手动重复配置,稳定性远高于手动Cookie。

import requests

# 创建持久会话对象
session = requests.session()
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
}

# 1. 模拟账号登录,自动保存登录Cookie
login_url = "网站登录接口地址"
login_data = {"username": "账号", "password": "密码"}
session.post(login_url, data=login_data, headers=headers)

# 2. 携带登录态访问权限页面
res = session.get("权限页面地址", headers=headers)
print(res.text)

6.3 本章常见坑点

1. 手动Cookie过期未更新,登录态失效,爬取数据为空或跳转登录页;

2. 未使用Session,每次请求都是全新匿名连接,无法维持登录状态;

3. 登录接口参数错误、账号密码错误,导致登录失败,权限页面无法访问。

6.4 高频面试/笔试真题(含答案)

题目1:Cookie和Session在爬虫中的区别与选型

答案:Cookie是本地静态数据,需手动配置、易过期,适合短期单次爬取;Session是动态会话对象,自动管理登录态,无需重复登录,稳定性强,适合长期批量爬取权限页面。

题目2:权限页面必须携带Cookie的原因

答案:权限页面需要校验用户登录身份,匿名请求无登录凭证,服务器判定为未登录用户,直接拦截请求或跳转登录页面,必须携带有效Cookie证明登录身份。

题目3:requests.session的核心优势

答案:自动保存、传递Cookie,全程维持会话状态,简化登录态爬虫代码,避免重复登录操作,大幅提升权限页面爬取的稳定性和效率。

第七章 动态JS页面爬取(Selenium)

传统requests仅能获取静态源码,无法加载JS异步渲染的数据。当下多数网页数据均为动态加载,静态源码无有效数据,必须通过Selenium模拟真实浏览器,完成页面渲染后再提取数据。

术语注释:动态渲染,浏览器自动执行JS代码,异步加载、展示页面数据的过程,是现代网页主流加载方式。

7.1 Selenium基础页面渲染

新版Selenium无需手动配置浏览器驱动,自动适配本地浏览器,开箱即用,可获取渲染后的完整网页源码。

from selenium import webdriver
from selenium.webdriver.common.by import By
import time

# 初始化浏览器
driver = webdriver.Chrome()
# 打开动态网页
driver.get("https://www.baidu.com")
# 等待页面完全渲染
time.sleep(2)
# 获取渲染后的完整源码
html = driver.page_source
print(html)
# 关闭浏览器,释放进程
driver.quit()

7.2 浏览器交互自动化(输入+点击)

模拟人工输入内容、点击按钮,适配需要手动交互才能加载数据的动态页面。

from selenium import webdriver
from selenium.webdriver.common.by import By
import time

driver = webdriver.Chrome()
driver.get("https://www.baidu.com")
time.sleep(1)

# 定位输入框并输入关键词
driver.find_element(By.ID, "kw").send_keys("python爬虫")
# 点击搜索按钮
driver.find_element(By.ID, "su").click()

time.sleep(2)
# 获取交互后渲染的页面数据
print(driver.page_source)
driver.quit()

7.3 无头静默运行(后台执行)

关闭浏览器可视化窗口,后台静默运行,节省系统资源,适合批量自动化爬取。

from selenium import webdriver
from selenium.webdriver.chrome.options import Options

# 配置无头模式参数
chrome_options = Options()
chrome_options.add_argument("--headless=new")

# 后台启动浏览器
driver = webdriver.Chrome(options=chrome_options)
driver.get("https://www.baidu.com")
print("页面标题:", driver.title)
driver.quit()

7.4 本章常见坑点

1. 未设置页面等待,代码执行速度快于页面渲染速度,出现元素找不到报错;

2. 运行结束不关闭浏览器,残留大量后台进程,占用电脑内存;

3. 滥用Selenium,静态页面也使用浏览器渲染,浪费资源、降低爬取效率;

4. 元素定位规则错误,导致交互、解析操作失效。

7.5 高频面试/笔试真题(含答案)

题目1:静态页面和动态页面的爬取区别

答案:静态页面数据直接写入源码,requests可直接爬取,速度快、效率高;动态页面数据由JS异步加载,静态源码无数据,必须用Selenium模拟浏览器渲染页面后,才能解析有效数据。

题目2:Selenium的优缺点与适用场景

答案:优点是完美适配JS动态页面,无需解析加密参数,模拟真实浏览器,反爬规避能力强;缺点是运行速度慢、资源占用高,不适合海量高频爬取,仅用于动态页面场景。

题目3:动态爬虫必须设置页面等待的原因

答案:页面JS渲染需要时间,代码执行是瞬时的,未等待直接操作元素,会因页面未加载完成报元素不存在错误,等待时间可保证渲染完成后再执行操作。

第八章 代理IP与代理池防封禁

高频、批量爬取场景下,本机固定IP极易被网站封禁。代理IP可替换访问IP、隐藏本机真实地址,是突破IP封禁、提升爬虫爬取量级的核心方案。

术语注释:代理IP,第三方网络中转IP,爬虫通过代理IP访问网站,服务器仅识别代理IP,无法获取、封禁本机真实IP。

8.1 单代理IP使用实操

适配小规模爬取、临时规避IP限制,通过proxies参数绑定代理地址。

import requests

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
}
# 代理IP格式:协议://IP:端口
proxies = {
    "http": "http://127.0.0.1:7890",
    "https": "http://127.0.0.1:7890"
}

# 携带代理发送请求,隐藏本机IP
response = requests.get("https://httpbin.org/ip", headers=headers, proxies=proxies)
print("当前访问IP:", response.text)

8.2 简易代理池轮询(稳定防封)

单个代理IP高频请求仍会被封禁,代理池存储多个有效IP,随机轮询使用,大幅提升爬虫稳定性。

import requests
import random

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
}
# 代理IP池,可自行扩充有效IP
proxy_list = [
    "http://127.0.0.1:7890",
    "http://127.0.0.1:7891",
    "http://127.0.0.1:7892"
]

# 轮询使用代理,异常捕获避免代码报错终止
for i in range(3):
    proxy = random.choice(proxy_list)
    proxies = {"http": proxy, "https": proxy}
    try:
        res = requests.get("https://httpbin.org/ip", headers=headers, proxies=proxies, timeout=5)
        print(f"代理{proxy} 请求成功")
    except:
        print(f"代理{proxy} 失效,跳过")

8.3 本章常见坑点

1. 未做异常捕获,代理IP失效、超时直接导致程序报错终止;

2. 依赖免费代理IP,存活率极低、延迟高,仅适合测试,不适合正式项目;

3. 代理协议与请求协议不匹配,导致代理不生效。

8.4 高频面试/笔试真题(含答案)

题目1:爬虫代理IP的核心使用场景

答案:海量批量爬取、高频请求场景,防止本机IP被网站封禁;突破网站单IP访问限制,通过多代理轮询提升爬取量级和稳定性。

题目2:代理池的核心作用

答案:整合多个有效代理IP,随机轮询调用,避免单个代理高频请求被封禁,自动规避失效IP,保障爬虫长期稳定运行。

题目3:免费代理和付费代理的差异

答案:免费代理公开透明、存活率低、延迟高、不稳定,仅适合学习测试;付费代理独享、延迟低、存活率高、稳定性强,适配正式爬虫项目。

第九章 增量爬虫与数据去重

普通全量爬虫每次运行都会重复爬取历史数据,造成资源浪费、数据冗余。增量爬虫仅爬取网站新增、更新数据,搭配去重机制,是爬虫长期定时运行的必备优化方案。

术语注释:增量爬取,跳过已抓取的历史数据,仅抓取网站新增、更新内容的爬虫运行模式。

9.1 URL去重(最简增量逻辑)

通过记录已爬取URL,运行时自动比对,跳过历史链接,仅爬取新链接,实现基础增量更新。

import requests

# 已爬取的历史URL列表
old_urls = ["https://www.baidu.com"]
new_url = "https://www.baidu.com"
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"}

# 增量判断:仅爬取未记录的新链接
if new_url not in old_urls:
    res = requests.get(new_url, headers=headers)
    print("新数据爬取成功")
else:
    print("数据已存在,跳过爬取")

9.2 文件持久化去重(长期有效)

将已爬取URL保存到本地文件,重启程序、再次运行仍可保留去重记录,实现长期增量爬取。

# 读取历史已爬取链接
try:
    with open("spider_urls.txt", "r", encoding="utf-8") as f:
        old_list = f.read().splitlines()
except:
    old_list = []

new_url = "https://www.baidu.com"
# 增量爬取逻辑
if new_url not in old_list:
    print("开始爬取新增数据")
    # 爬取逻辑可自行扩展
    with open("spider_urls.txt", "a", encoding="utf-8") as f:
        f.write(new_url + "\n")
else:
    print("数据已存在,跳过本次爬取")

9.3 本章常见坑点

1. 无去重机制,重复爬取海量冗余数据,浪费网络和存储资源;

2. 仅内存记录去重数据,程序重启后记录清空,重新全量爬取;

3. 仅通过URL去重,无法识别页面内容更新的旧数据,适配场景有限。

9.4 高频面试/笔试真题(含答案)

题目1:什么是增量爬虫?核心优势

答案:增量爬虫是仅抓取网站新增、更新数据的爬虫模式,不重复爬取历史数据。优势是减少数据冗余、节省网络请求资源、大幅提升长期爬取效率,适合定时更新的爬虫项目。

题目2:爬虫常用数据去重方案

答案:基础方案:URL列表去重、本地文件持久化去重;进阶方案:数据库唯一索引去重、MD5数据指纹去重,适配不同量级爬虫项目。

题目3:全量爬虫和增量爬虫的区别

答案:全量爬虫每次运行爬取全部数据,重复率高、效率低,仅适合首次初始化数据;增量爬虫仅更新新增数据,无冗余、效率高,适合日常定时迭代爬取。

第十章 异步并发高效爬虫(aiohttp)

此前所有爬虫均为同步串行执行,必须等待单个请求完成才能执行下一个,海量数据爬取效率极低。异步爬虫可实现多请求并发执行,效率数倍提升,是大规模爬虫的核心优化方案。

术语注释:异步并发,无需等待单个任务执行完成,同时发起多个网络请求,多任务并行运行,大幅缩短整体耗时。

10.1 aiohttp异步爬虫实战

异步爬虫必须使用aiohttp库,禁止混用同步requests库,避免阻塞异步事件循环。

import aiohttp
import asyncio

# 异步请求单个链接
async def get_spider_data(url):
    headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"}
    async with aiohttp.ClientSession() as session:
        async with session.get(url, headers=headers) as res:
            html = await res.text()
            print(f"{url} 并发爬取成功")
            return html

# 批量并发任务
async def main():
    url_list = [
        "https://www.baidu.com",
        "https://httpbin.org/get",
        "https://httpbin.org/ip"
    ]
    # 创建并发任务
    tasks = [asyncio.create_task(get_spider_data(url)) for url in url_list]
    await asyncio.gather(*tasks)

# 启动异步程序
if __name__ == "__main__":
    asyncio.run(main())

10.2 本章常见坑点

1. 异步代码混用同步requests库,阻塞事件循环,导致并发失效、程序卡死;

2. 并发数量过高,请求过于密集,直接触发网站反爬、IP封禁;

3. 缺失await关键字,异步任务无法正常执行。

10.3 高频面试/笔试真题(含答案)

题目1:同步爬虫与异步爬虫核心区别

答案:同步爬虫串行执行,单任务完成后执行下一个,速度慢、逻辑简单,适合少量数据爬取;异步爬虫并发执行,多请求同时发起,耗时短、效率高,适合海量数据批量爬取,代码复杂度略高。

题目2:aiohttp和requests能否混用?原因

答案:不能混用。requests是同步阻塞库,会破坏异步事件循环机制,导致并发失效、程序报错卡死,异步场景必须全程使用aiohttp。

题目3:异步爬虫的优缺点与使用限制

答案:优点是并发效率高、海量数据爬取耗时极短;缺点是代码逻辑复杂,并发不可控易触发反爬,必须手动限制并发数量,不能无限制并发请求。

第十一章 爬虫高频面试笔试真题汇总

本章汇总全书核心高频考点,整合入门到进阶必考题,覆盖实操、原理、排错、优化全场景,适合面试笔试冲刺、知识点复盘。

1. 完整爬虫流程与核心组件

答案:完整流程:伪装请求发送请求 → 获取网页源码 → 解析有效数据 → 数据去重 → 持久化存储。核心组件:请求模块(requests/aiohttp)、解析模块(lxml/bs4)、反爬伪装模块、会话保持模块、代理防封模块、数据存储模块。

2. 主流网站反爬机制及对应解决方案

答案:UA校验→伪装浏览器请求头;频率限制→添加延时、控制并发;登录权限限制→Cookie/Session会话保持;动态JS渲染→Selenium浏览器渲染;IP封禁→代理IP池轮询。

3. 爬虫IP被封禁的排查与解决思路

答案:立即停止高频请求,降低爬取频率;添加随机人工延时;替换代理IP规避封禁;搭建代理池实现多IP轮询;长期爬取开启增量模式,减少无效请求。

4. 动态页面爬取失败排查流程

答案:先查看静态