Python爬虫实战:批量抓取旗帜图片源码解析
简介这份资源面向Python爬虫初学者与数据分析入门者提供一套完整的实战案例爬取东京奥运会奖牌国家及地区的旗帜图片。压缩包内包含HTML与Jupyter Notebook两类文件整体约54KBNotebook便于边写边看结果HTML则适合直接浏览代码与说明。案例串联起requests发送请求、BeautifulSoup解析页面、CSS选择器定位图片链接、PIL保存与处理图像、CSV或JSON落盘存储等环节并涉及异常处理与robots.txt合规意识帮助读者理解从抓取到落地的完整链路。已有217人学习适合想通过小项目打通爬虫基础、积累可复用代码模板的读者参考。1. 旗帜图片批量抓取一份能直接跑通的爬虫源码拆解做数据标注、UI 素材库或者地理信息可视化的开发者大概都遇到过同一个需求需要一批规格统一、命名规范的旗帜图片。手动一张张下载几百个条目下来鼠标点废、命名还容易乱。这份「部分国家及地区旗帜图片数据爬取源代码」就是冲着这个场景来的——它把「找到图片地址、批量下载、按规则落盘」这条链路固化成了可复用的脚本拿到手改几个参数就能跑。适合谁一是需要快速攒素材的前端或数据可视化开发者二是想找一个结构完整、逻辑不绕的爬虫练手项目的新手。它不涉及复杂反爬对抗重点在「稳定拿到图、存得整齐」属于那种读完就能上手改的实用型源码。2. 项目定位与技术选型为什么用 requests BeautifulSoup 而不是上框架2.1 这个项目到底解决什么问题先把需求说清楚。旗帜图片的获取本质是一个「列表页 → 详情页/图片直链 → 二进制文件落盘」的三段式流程。难点不在技术而在细节图片 URL 往往藏在img标签的src或>import requests # 构造会话对象复用连接提升批量请求效率 session requests.Session() # 伪装请求头模拟浏览器访问 session.headers.update({ 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 ), Accept: text/html,application/xhtmlxml,application/xml;q0.9,image/webp,*/*;q0.8, Accept-Language: zh-CN,zh;q0.9,en;q0.8, }) # 统一超时设置避免某个请求卡死拖垮整个流程 TIMEOUT (5, 15) # (连接超时, 读取超时)逻辑说明用Session而不是每次requests.get好处是 TCP 连接会被复用批量下载时能省下大量握手开销。headers里最关键的是User-Agent其次是Accept和Accept-Language它们共同决定服务器是否把你当正常浏览器。参数说明TIMEOUT设成元组形式第一个值是建立连接的最长等待第二个值是服务器开始返回数据后的读取等待。只写一个数字的话连接和读取共用同一个上限遇到慢站点容易误判超时。这个细节很多人不知道属于血泪经验。3.2 页面解析与图片链接提取拿到 HTML 后核心任务是把所有图片地址抠出来。这里要处理两种常见情况src直接给完整地址或者给相对路径需要拼接。from bs4 import BeautifulSoup from urllib.parse import urljoin def extract_image_urls(html, base_url): 从页面 HTML 中提取所有图片的绝对地址 soup BeautifulSoup(html, html.parser) urls [] for img in soup.find_all(img): # 优先取>import os import re def download_image(session, url, save_dir, index): 下载单张图片并按规则命名保存 try: resp session.get(url, timeout(5, 15), streamTrue) resp.raise_for_status() # 非 200 直接抛异常 except requests.RequestException as e: print(f[失败] {url} - {e}) return False # 从 URL 推断后缀兜底用 .png ext os.path.splitext(url.split(?)[0])[1] or .png # 用序号 原始名做文件名过滤非法字符 name re.sub(r[\\/:*?|], _, f{index:03d}{ext}) path os.path.join(save_dir, name) # 以二进制模式写入chunk 分块避免大图占满内存 with open(path, wb) as f: for chunk in resp.iter_content(chunk_size8192): if chunk: f.write(chunk) return True逻辑说明streamTrue配合iter_content是下载二进制文件的标准姿势图片不会一次性全读进内存。raise_for_status()让 4xx/5xx 直接进异常分支避免把错误页面当成图片存下来。文件名用index:03d补零保证排序时002排在010前面而不是字典序的010在002前。参数说明chunk_size8192是 8KB 一块对图片来说够用调大能减少写入次数但增加单次内存占用。re.sub那行是过滤 Windows 和 Linux 都不允许的文件名字符旗帜图片名里如果带冒号或斜杠不处理会直接报错。3.4 主流程串联与异常兜底把上面几块拼起来主流程就是「遍历页面 → 提取链接 → 逐张下载」。def run(start_url, save_dir): os.makedirs(save_dir, exist_okTrue) # 目录不存在则创建 session build_session() resp session.get(start_url, timeout(5, 15)) resp.encoding resp.apparent_encoding # 修正中文乱码 urls extract_image_urls(resp.text, start_url) success 0 for i, url in enumerate(urls, start1): if download_image(session, url, save_dir, i): success 1 print(f完成成功 {success} / 共 {len(urls)})逻辑说明os.makedirs(..., exist_okTrue)保证目录存在且不因重复创建报错。resp.apparent_encoding是根据内容自动推断编码比硬编码utf-8更稳能避免中文页面解析出乱码导致链接提取失败。循环里对每张图单独 try一张失败不影响后续这是批量任务的基本素养。参数说明start_url是列表页地址save_dir是输出目录。enumerate(..., start1)让序号从 1 开始符合人类习惯。4. 跑起来环境准备与执行步骤4.1 依赖安装与版本确认先把环境弄干净。建议用虚拟环境避免和系统里的包打架。# 创建并激活虚拟环境 python -m venv venv source venv/bin/activate # Windows 用 venv\Scripts\activate # 安装依赖 pip install requests beautifulsoup4逻辑说明venv是标准库自带的虚拟环境工具不需要额外装。激活后pip install的包只作用于当前环境删掉venv目录就等于彻底卸载不留残留。参数说明requests和beautifulsoup4是仅有的两个第三方依赖。如果源码里还用了lxml作为解析器那就再补一个pip install lxml它比内置的html.parser快但对不规范 HTML 的容错稍弱。4.2 配置修改与首次运行跑之前先改config.py把目标地址和保存路径换成你自己的。# config.py START_URL https://example.com/flags # 换成实际列表页地址 SAVE_DIR ./images # 图片输出目录 MAX_PAGES 5 # 需要翻页时控制页数逻辑说明把易变参数集中管理是让脚本可复用的关键。START_URL决定抓哪里SAVE_DIR决定存哪里MAX_PAGES控制抓取深度避免不小心把整个站点爬穿。参数说明SAVE_DIR用相对路径时是相对于脚本运行目录不是脚本所在目录。如果你在别的路径下执行输出会跑到意料之外的地方建议第一次跑用绝对路径确认行为。改完直接运行python main.py正常的话终端会逐行打印下载进度images/目录里逐渐堆满图片。第一次跑建议把MAX_PAGES设成 1先验证单页逻辑通不通再放开规模。4.3 结果校验怎么确认下载是完整的跑完别急着关终端做三件事校验第一看文件数量。终端最后一行会打印「成功 X / 共 Y」如果 X 明显小于 Y说明有链接下载失败往上翻日志找[失败]开头的行。第二看文件大小。用ls -lh images/扫一眼如果出现大量 0 字节或几 KB 的文件多半是把错误页面存下来了检查raise_for_status是否生效。第三抽查内容。随便打开几张图确认不是占位图、不是验证码页面、不是 HTML 文本被改了后缀。提示如果失败率很高先别改代码把失败的那条 URL 单独用浏览器打开看看能不能访问。很多时候是目标站点对高频请求做了限流加个time.sleep(0.5)就能缓解。5. 避坑与常见问题排查5.1 下载下来全是 0 字节或打不开现象文件生成了但大小是 0或者图片查看器报「格式不支持」。原因最常见的是把response.text当二进制写进了文件。text是解码后的字符串写进wb模式的文件会出问题。另一个原因是请求被重定向到了登录页或错误页返回的是 HTML 而不是图片。解决确认下载函数里用的是response.content或iter_content不是response.text。同时加上raise_for_status()让非 200 响应直接暴露出来而不是被静默写进文件。5.2 图片链接提取为空现象终端打印「共 0」一张都没抓到。原因目标页面的图片是 JS 动态加载的requests拿到的原始 HTML 里没有img标签或者图片地址藏在style的background-image里而不是src。解决先在浏览器里「查看网页源代码」不是审查元素搜一下有没有img标签。如果没有说明是动态渲染得换思路——要么找 XHR 接口直接拿 JSON 数据要么用能执行 JS 的工具。如果是background-image就得改解析逻辑从style属性里用正则抠 URL。5.3 中文文件名乱码或保存报错现象保存时报UnicodeEncodeError或者文件名变成一堆问号。原因从 URL 或页面标题提取的文件名里含中文或特殊字符而文件系统对字符集敏感。解决统一用序号命名把原始名里的非法字符用re.sub过滤掉。如果一定要保留中文确保脚本文件本身是 UTF-8 编码并在文件头声明。最省事的做法就是纯数字命名彻底绕开字符集问题。5.4 跑一半被限流或封 IP现象前几十张正常后面全部超时或返回 403。原因请求频率太高触发了站点的访问频率限制。解决在每次下载之间加time.sleep(random.uniform(0.3, 1.0))用随机间隔模拟人类操作节奏。如果站点限制严格还得考虑轮换请求头或降低并发。记住一点爬虫的礼貌程度直接决定它能跑多久别把间隔设成 0。5.5 重复下载同一张图现象images/里出现内容相同但文件名不同的图片。原因同一张图在页面上以不同 URL 出现比如带不同查询参数去重逻辑没覆盖到。解决去重时不能只比对完整 URL最好对 URL 做归一化——去掉查询参数、统一协议和域名大小写再比对。或者在下载前算一下内容的哈希值已存在就跳过。后者更彻底但要多读一次文件。6. 二次开发把脚本改造成可维护的采集工具跑通只是起点真正让它好用得做几处改造。第一处是配置外置。把目标地址、保存目录、请求间隔、超时时间全挪到config.py甚至一个 JSON 文件里这样换目标站点时不用动核心代码。我一般会加一个settings.json用json.load读进来改配置连 Python 都不用碰。第二处是断点续传。批量下载最怕跑到一半断了重跑又从第一张开始。做法很简单下载前检查目标文件是否已存在且大小大于 0是就跳过。这样重跑时只补缺失的部分省时省流量。def should_skip(path): 已存在且非空则跳过实现断点续传 return os.path.exists(path) and os.path.getsize(path) 0第三处是日志替代 print。脚本阶段print够用但要长期跑或者定时跑就得用logging模块把成功、失败、跳过分别记到文件里方便事后排查。配置一个FileHandler把级别设成INFO失败信息用WARNING一眼能筛出来。第四处是并发提速。图片下载是 IO 密集型任务用concurrent.futures.ThreadPoolExecutor开几个线程速度能翻几倍。但要注意并发数别开太大一般 4 到 8 个线程足够开太多反而容易被限流。下面是个最小改造示例from concurrent.futures import ThreadPoolExecutor def batch_download(session, urls, save_dir, workers5): 多线程批量下载控制并发数避免触发限流 with ThreadPoolExecutor(max_workersworkers) as pool: futures [ pool.submit(download_image, session, url, save_dir, i) for i, url in enumerate(urls, start1) ] results [f.result() for f in futures] return sum(results)逻辑说明ThreadPoolExecutor用线程池并发执行下载任务max_workers控制同时进行的请求数。pool.submit返回 future 对象f.result()阻塞等待结果。因为下载是 IO 等待为主线程模型在这里比多进程更合适开销也小。参数说明workers5是经验值对大多数中小站点够用且不易触发限流。如果目标站点响应慢可以适当调大如果频繁 403就调小甚至退回单线程加延时。最后说个验证方法。改完任何一处别直接上全量跑。先拿 5 到 10 张图做小样本测试确认文件名、内容、日志都正常再放开规模。我吃过亏——有次改完并发直接全量跑结果因为一个路径拼接 bug几百张图全存到了错误目录清理了半天。从那以后我每次改完下载逻辑都强制先用小样本走一遍完整链路确认落盘位置和文件内容都对再放开跑。希望这些经验能帮到你少走点弯路。本文还有配套的精品资源点击获取

相关新闻

RS485与Modbus网关选型指南:老设备联网改造实战

RS485与Modbus网关选型指南:老设备联网改造实战

1. 老设备联网改造,为什么网关选型是第一道坎车间里那台用了快十年的温控仪表,屏幕上还跳着稳定的数字,可它唯一的对外接口就是一个DB9串口,跑的还是RS485半双工。老板说要把数据接进新上的监控平台,你拿着笔记本蹲在设…

2026/10/15 16:13:34 阅读更多 →
Nacos生产集群部署:高可用、可观测、可伸缩的元数据中心实践

Nacos生产集群部署:高可用、可观测、可伸缩的元数据中心实践

1. 项目概述:为什么Nacos集群不是“配个IP就完事”的事Nacos生产环境集群部署,这八个字背后藏着的不是一套配置清单,而是一整套服务治理基础设施的稳定性底座。我做过不下二十个微服务项目的上线支撑,凡是把Nacos当单点用、或者三…

2026/10/15 16:13:34 阅读更多 →
MATLAB性能瓶颈?用TDM-GCC与mexFunction编译C代码提速15倍

MATLAB性能瓶颈?用TDM-GCC与mexFunction编译C代码提速15倍

很多人在MATLAB里写算法原型,跑得很开心,一旦遇到循环性能瓶颈就头疼。我自己最常用的一招,就是在MATLAB里直接编译运行C/C代码,通过mexFunction接口把C代码变成MATLAB原生函数,既保留C的执行效率,又保住MA…

2026/10/15 16:13:34 阅读更多 →

最新新闻

小程序手机号授权登录全流程详解:从申请到解密避坑指南

小程序手机号授权登录全流程详解:从申请到解密避坑指南

开发小程序手机号登录功能,最头疼的往往不是代码怎么写,而是你发现代码写完了、测试也过了,一到真机预览,手机号那一栏永远返回不了明文,打开后台一看,咦,怎么只回来一段加密串?这篇…

2026/10/15 17:02:07 阅读更多 →
DBC文件转C代码:车载ECU中CAN协议解析的工程化实践

DBC文件转C代码:车载ECU中CAN协议解析的工程化实践

简介:本资源是一款面向汽车电子与嵌入式开发工程师的DBC文件自动化处理工具,专为CAN总线通信中频繁出现的DBC解析需求设计。手动将DBC协议定义转换为C语言结构体、编解码函数易出错且耗时,该工具通过Python脚本实现一键生成标准化C代码&#…

2026/10/15 17:02:07 阅读更多 →
MRAS电机参数自适应辨识Simulink仿真模型

MRAS电机参数自适应辨识Simulink仿真模型

简介:本资源是一套面向电机控制方向学生与工程师的MATLAB/Simulink教学级仿真平台,聚焦永磁同步电机(PMSM)无位置传感器控制中的核心难点——在线参数辨识与自适应调节。通过模型参考自适应系统(MRAS)实现对…

2026/10/15 17:02:07 阅读更多 →
熟练AI工具堪比十年前Office,前端招人该考会用还是判断对错?

熟练AI工具堪比十年前Office,前端招人该考会用还是判断对错?

熟练AI工具堪比十年前Office,前端招人该考会用还是判断对错? 最近脉脉上一则前端招人讨论撕开了一个决策冲突:把熟练使用 AI 工具写进 JD,与十年前写熟练使用 Office 如出一辙;半年内人人都会装工具,但两位…

2026/10/15 17:02:07 阅读更多 →
DBC文件转C代码:嵌入式CAN协议解析的工程化实践

DBC文件转C代码:嵌入式CAN协议解析的工程化实践

简介:本资源是一款面向汽车电子与嵌入式开发工程师的DBC文件自动化处理工具,专为解决CAN总线通信中手动解析DBC文件导致的类型定义繁琐、编解码逻辑重复、易出错等痛点而设计。资源包含1个核心Python脚本(dbc2c.py)、1个说明文档&…

2026/10/15 17:02:07 阅读更多 →
从复制源码到本地Maven:Android多工程共享组件的完整实践

从复制源码到本地Maven:Android多工程共享组件的完整实践

做Android开发久了,几乎都会被同一件事绊住:自己封装好的通用组件,比如网络层、图片加载封装、一套带基础ViewModel的UI库,忽然要在第二个、第三个工程里使用。我最早的处理办法很粗暴——把源码文件夹直接复制进新工程&#xff0…

2026/10/15 17:01:06 阅读更多 →

日新闻

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

1. 为什么选择容器化方式部署 LoRa 网络服务LoRa 物联网项目落地时,网络服务器是整个链路的核心枢纽。它负责接收网关上报的数据包、完成去重与解密、再把有效载荷分发给上层应用。早期大家习惯把网络服务器直接装在物理机上,依赖一堆系统库和特定版本的…

2026/10/15 0:00:46 阅读更多 →
共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

1. 共享推理服务里,扩缩容到底难在哪做过大模型推理服务部署的人,大概都经历过这样的场景:一个团队共用一套推理集群,A 业务跑的是 7B 的小模型,B 业务跑的是 72B 的大模型,C 业务白天流量高、晚上几乎归零…

2026/10/15 0:00:46 阅读更多 →
Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

1. 引子:一次内核恐慌引发的追查先从一个真实场景说起。某次我给一台老旧的嵌入式设备折腾系统裁减,为了把启动时间压进两秒以内,我手贱地把一串自认为“没用”的 systemd 服务给 disable 了,其中就包括systemd-remount-fs.servic…

2026/10/15 0:00:46 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/15 16:18:54 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/14 16:30:29 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/15 13:48:15 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 9:49:14 阅读更多 →