Python Requests 爬虫案例
Python Requests 爬虫案例
- 爬取小说网站
- 分页爬取小说网站
- 豆瓣电影评论
- 下载婚纱图片
- 百度图片
案例1 爬取小说网站
步骤:
- 爬取网页,保存html文件到本地
crawl_html.py
- 解析本地html文件内容,保存解析内容到本地文本文件
parse_html
#!/usr/bin/env python3
# -*- coding: utf-8 -*-"""
crawl_html.py
抓取笔趣阁小说《诡秘之主》第一章,保存为本地 txt
"""import requests
from pathlib import Path# 1. 目标页面
# url = "https://www.xbiquge.la/10/10489/2946624.html"
url = "https://www.1b0112db.xyz/book/64813/1.html"# 2. 浏览器 UA,防最简单反爬
headers = {"User-Agent": ("Mozilla/5.0 (Windows NT 10.0; Win64; x64) ""AppleWebKit/537.36 (KHTML, like Gecko) ""Chrome/114.0 Safari/537.36")
}# 3. 发送 GET 请求
resp = requests.get(url, headers=headers, timeout=10)
# 4. 网络异常统一处理
resp.raise_for_status() # 若状态码不是 200,直接抛异常
resp.encoding = resp.apparent_encoding # 自动推断网页编码(防止乱码)# 5. 保存原始 html(调试友好)
Path("debug.html").write_text(resp.text, encoding="utf-8")# 6. 打印前 300 字符观察
print(resp.text[:300])
#!/usr/bin/env python3
# -*- coding: utf-8 -*-"""
parse_html.py
抓取笔趣阁小说《诡秘之主》第一章,保存为本地 txt
"""
from bs4 import BeautifulSoup
from pathlib import Path# 1. 读取上节课保存的 html
html = Path("debug.html").read_text(encoding="utf-8")# 2. 创建 soup 对象;lxml 解析器速度快 uv add lxml
soup = BeautifulSoup(html, "lxml")
# Python 内置的 html.parser(无需额外安装)
# soup = BeautifulSoup(html, "html.parser")# 3. 找标题(h1 标签)
title = soup.find("h1").get_text(strip=True)
print("章节标题:", title)# 4. 找正文 div(class='content' 为假设)
content_div = soup.find("div", id="chaptercontent")
# paragraphs = [p.get_text(strip=True) for p in content_div.find_all("p")]
paragraphs = [p.get_text(strip=True) for p in content_div]
paragraphs = {item for item in paragraphs if item != ""}# 5. 合并段落并写文件
Path(f"{title}.txt").write_text("\n".join(paragraphs), encoding="utf-8")
print("保存完成,共", len(paragraphs), "段")
运行顺序:
python crawl_html.py
python parse_html.py
案例2 分页爬取小说网站
分页爬取小说网站某部小说,每个网页为该小说的一个章节。
分页爬取网页即可得到该小说的全部章节。
解析每个页面,把小说内容保存到本地文本文件中
#!/usr/bin/env python3
# -*- coding: utf-8 -*-"""
crawl_paging.py
抓取笔趣阁小说《诡秘之主》第一章,保存为本地 txt
"""
import randomimport requests
from pathlib import Pathfrom bs4 import BeautifulSoup
from trio import sleep# 目标页面
base_url = "https://www.90feaa.cfd/"
url = base_url + "/book/64813/1.html"# 浏览器 UA,防最简单反爬
headers = {"User-Agent": ("Mozilla/5.0 (Windows NT 10.0; Win64; x64) ""AppleWebKit/537.36 (KHTML, like Gecko) ""Chrome/139.0.0.0 Safari/537.36")
}def crawl_html(url):# 发送 GET 请求resp = requests.get(url, headers=headers, timeout=10)# 网络异常统一处理resp.raise_for_status() # 若状态码不是 200,直接抛异常resp.encoding = resp.apparent_encoding # 自动推断网页编码(防止乱码)# 返回网页文本return resp.textdef parse_page(html):# 创建 soup 对象;lxml 解析器速度快 uv add lxmlsoup = BeautifulSoup(html, "lxml")# 找标题(h1 标签)title = soup.find("h1").get_text(strip=True)print("章节标题:", title)# 找正文 div(class='content' 为假设)content_div = soup.find("div", id="chaptercontent")paragraphs = [p.get_text(strip=True) for p in content_div]paragraphs = {item for item in paragraphs if item != ""}# 合并段落并写文件Path(f"{title}.txt").write_text("\n".join(paragraphs), encoding="utf-8")print("保存完成,共", len(paragraphs), "段")# 判断有没有下一页 如果有下一页 继续读取pb_next = soup.find("a", id="pb_next")if pb_next:href_url = pb_next['href']new_html = crawl_html(base_url + href_url)parse_page(new_html)if __name__ == '__main__':html = crawl_html(url)parse_page(html)
案例3 豆瓣电影评论
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
douban.py
爬取豆瓣电影 Top250 并存 CSV
"""import csv
import time
import requests
from bs4 import BeautifulSoup
from tqdm import tqdm # 进度条# 1. 基础配置
BASE_URL = "https://movie.douban.com/top250"
HEADERS = {"User-Agent": ("Mozilla/5.0 (Windows NT 10.0; Win64; x64) ""AppleWebKit/537.36 (KHTML, like Gecko) ""Chrome/139.0.0.0 Safari/537.36")
}
PAGE_SIZE = 25 # 每页 25 条记录
MAX_PAGE = 10 # 共 250 条def fetch_one_page(start):"""start: 本页起始索引(0,25,50...)返回 BeautifulSoup 对象"""params = {"start": start}resp = requests.get(BASE_URL, headers=HEADERS, params=params, timeout=10)resp.raise_for_status()resp.encoding = "utf-8"return BeautifulSoup(resp.text, "lxml")def parse_one_page(soup):"""解析单页,返回 list[dict]"""items = soup.select("div.item") # 25 个 itemdata = []for item in items:title = item.select_one("span.title").get_text(strip=True)rating = item.select_one("span.rating_num").get_text(strip=True)quote_tag = item.select_one("p.quote")quote = quote_tag.get_text(strip=True) if quote_tag else ""data.append({"title": title, "rating": rating, "quote": quote})return datadef main():all_rows = []# 2. 循环 10 页for idx in tqdm(range(MAX_PAGE), desc="抓取进度"):soup = fetch_one_page(idx * PAGE_SIZE)all_rows.extend(parse_one_page(soup))# 3. 礼貌延时time.sleep(1.5)# 4. 写 CSVwith open("douban_top250.csv", "w", encoding="utf-8-sig", newline="") as f:writer = csv.DictWriter(f, fieldnames=["title", "rating", "quote"])writer.writeheader()writer.writerows(all_rows)print("已保存 douban_top250.csv,共", len(all_rows), "条")if __name__ == "__main__":main()
案例4 下载婚纱图片
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
wedding.py
爬取堆糖网 婚礼分类 婚纱照片 并下载
"""
# 导入必要库
import os # 用于文件路径操作
import requests # 用于发送网络请求
from bs4 import BeautifulSoup# 保存图片的文件夹名称
SAVE_DIR = "婚纱""""创建保存图片的文件夹,若已存在则不操作"""
if not os.path.exists(SAVE_DIR):os.makedirs(SAVE_DIR)print(f"创建图片保存文件夹: {SAVE_DIR}")
else:print(f"图片保存文件夹已存在: {SAVE_DIR}")
# 请求地址
url = 'https://www.duitang.com/category/'# 请求头
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36",
}
# 表单数据
form_data = {'cat': 'wedding'
}print('正在爬取,请稍等...')
# 发送请求 获取服务器响应
# 请求方式:GET POST PUT PATCH DELETE OPTION
response = requests.get(url=url, headers=headers, params=form_data)# 输出HTTP状态码
print(response.status_code)
# 输出服务器响应字符串
# print(response.text)
html = response.text
print('页面获取完成,正在解析...')
# 创建解析器
soup = BeautifulSoup(html, 'html.parser')
# 元素查找
# 获取页面中所有的img标签
imgs = soup.find_all('img')
print('解析完成正在下载...')
count = 0
for img in imgs:# print(img)print(img.get('src'))img_file = requests.get(img.get('src'))count += 1file_name = '图片' + str(count) + '.png'with open(file=f'{SAVE_DIR}/{file_name}', mode='wb') as f:f.write(img_file.content)
案例5 百度图片
- 向百度图片 API 接口请求想要的图片类型
- 解析返回的json数据,解析出图片下载地址
- 下载图片
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
baidu_images.py
1. 向百度图片 API 接口请求想要的图片类型
2. 解析返回的json数据,解析出图片下载地址
3. 下载图片
"""# 导入必要库
import requests # 用于发送网络请求
import os # 用于文件路径操作
import time # 用于设置请求间隔,避免过快请求
import json # 用于解析API返回的JSON数据
from urllib.parse import quote # 用于URL编码# -------------------------- 配置参数 --------------------------
# 搜索关键词(已URL编码)
# KEYWORD = quote("古风美女") # 将"古风美女"转为URL编码格式
# print(KEYWORD)
KEYWORD = "古风美女" # 搜索关键字
# 保存图片的文件夹名称
SAVE_DIR = "ancient_beauty_images"
# 爬取页数(每页约30张图)
MAX_PAGE = 20
# 请求头(模拟浏览器行为,避免被识别为爬虫)
HEADERS = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36","Referer": "https://image.baidu.com/", # 模拟从百度图片页面跳转"Connection": "keep-alive"
}
# 百度图片API接口(通过分析网络请求获取)
API_URL = "https://image.baidu.com/search/acjson"# -------------------------- 工具函数 --------------------------
def create_save_dir():"""创建保存图片的文件夹,若已存在则不操作"""if not os.path.exists(SAVE_DIR):os.makedirs(SAVE_DIR)print(f"创建图片保存文件夹: {SAVE_DIR}")else:print(f"图片保存文件夹已存在: {SAVE_DIR}")def download_image(img_url, save_path):"""下载单张图片并保存到本地:param img_url: 图片的URL:param save_path: 本地保存路径:return: 下载成功返回True,失败返回False"""try:# 发送请求获取图片数据(设置超时时间10秒)response = requests.get(url=img_url,headers=HEADERS,timeout=10,stream=True # 流式下载,适合大文件)# 检查请求是否成功(状态码200表示成功)if response.status_code == 200:# 写入图片文件(二进制模式)with open(save_path, "wb") as f:for chunk in response.iter_content(chunk_size=1024): # 分块写入if chunk:f.write(chunk)print(f"下载成功: {save_path}")return Trueelse:print(f"下载失败(状态码异常): {img_url},状态码: {response.status_code}")return Falseexcept Exception as e:print(f"下载失败(发生错误): {img_url},错误: {str(e)}")return False# -------------------------- 主爬取逻辑 --------------------------
def crawl_images():"""爬取百度图片API并下载图片"""create_save_dir() # 确保保存文件夹存在# 循环爬取多页for page in range(MAX_PAGE):print(f"\n开始爬取第 {page + 1} 页...")# 构造API请求参数(pn为起始位置,每页30张图)params = {"tn": "resultjson_com", # 固定参数,标识返回JSON格式"logid": "1193833708646682469", # 日志ID(可从浏览器请求中复制)"ipn": "rj", # 固定参数"ct": "201326592", # 固定参数"is": "", # 预留参数"fp": "result", # 固定参数"queryWord": KEYWORD, # 搜索关键词(URL编码后)"cl": "2", # 固定参数"lm": "-1", # 固定参数"ie": "utf-8", # 编码格式"oe": "utf-8", # 编码格式"adpicid": "", # 预留参数"st": "-1", # 固定参数"z": "", # 预留参数"ic": "0", # 固定参数"hd": "", # 预留参数"latest": "", # 预留参数"copyright": "", # 预留参数"word": KEYWORD, # 搜索关键词(URL编码后)"s": "", # 预留参数"se": "", # 预留参数"tab": "", # 预留参数"width": "", # 预留参数"height": "", # 预留参数"face": "0", # 预留参数(是否人脸)"istype": "2", # 固定参数"qc": "", # 预留参数"nc": "1", # 固定参数"fr": "", # 预留参数"expermode": "", # 预留参数"force": "", # 预留参数"pn": page * 30, # 起始位置(每页30张,第n页从n*30开始)"rn": "30", # 每页返回数量"gsm": hex(page * 30)[2:], # 十六进制起始位置(去掉0x前缀)"1690083455624": "" # 时间戳参数(可从浏览器请求中复制)}try:# 发送请求获取图片列表数据response = requests.get(url=API_URL,headers=HEADERS,params=params,timeout=15)# 解析JSON数据(注意:百度API返回的JSON可能包含多余字符,需处理)# 去除JSON前可能的干扰字符(如")]}'")json_data = response.text.lstrip(")]}'")data = json.loads(json_data)# data = response.json()# 提取图片URL列表(循环处理每张图)for i, img_info in enumerate(data.get("data", [])):# 过滤无效数据(无图片URL的条目)if not img_info.get("middleURL"):continue# 获取图片URL(middleURL为中等尺寸图片,可替换为hoverURL/objURL等)img_url = img_info["middleURL"]# 生成保存文件名(页面_序号.jpg)img_name = f"page_{page + 1}_img_{i + 1}.jpg"save_path = os.path.join(SAVE_DIR, img_name)# 下载图片download_image(img_url, save_path)# 每下载一张图,暂停0.5秒,避免请求过于频繁time.sleep(0.5)# 每页爬取完成后,暂停2秒再爬取下一页time.sleep(2)except Exception as e:print(f"第 {page + 1} 页爬取失败,错误: {str(e)}")continue # 继续爬取下一页# -------------------------- 程序入口 --------------------------
if __name__ == "__main__":print("开始爬取百度图片-古风美女...")crawl_images()print("\n爬取结束!图片已保存至:", os.path.abspath(SAVE_DIR))