Python爬虫实战:手把手教你用requests+lxml批量下载mzsock网站图片(附完整源码)
Python爬虫实战从零开始构建图片采集系统1. 环境准备与工具选择在开始爬虫项目之前我们需要搭建合适的工作环境。Python作为爬虫开发的首选语言拥有丰富的生态系统和易用的语法特性。这里推荐使用Python 3.8版本它能提供更好的异步支持和性能优化。必备工具包安装pip install requests lxml pillow为什么选择requestslxml组合requests比标准库urllib更人性化的HTTP客户端lxml解析速度比BeautifulSoup快3-5倍特别适合结构化数据提取Pillow后续可能需要对下载的图片进行格式转换或压缩开发环境配置建议使用VS Code或PyCharm等专业IDE安装Python扩展插件配置好代码自动补全和调试功能注意不同操作系统下路径处理方式可能不同建议使用pathlib模块进行跨平台路径操作2. 网页结构分析与数据定位现代网站通常采用动态渲染技术但我们的目标站点仍保持传统HTML结构。打开开发者工具(F12)可以看到页面由以下几个关键部分组成导航栏包含分页链接内容区图片列表以li元素组织页脚版权信息等典型XPath选择器示例# 获取所有图片条目 li_list tree.xpath(//section/div[1]/ul/li) # 提取单个图片链接 img_url li.xpath(./div[1]/a/href)[0] # 获取图片标题 title li.xpath(./h3/a/title)[0]常见定位问题解决方案元素层级变化使用相对路径而非绝对路径动态class改用其他稳定属性定位懒加载检查data-src等属性3. 反爬策略应对方案网站通常会设置基础防护措施我们需要模拟正常浏览器行为标准请求头配置headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64), Accept-Language: zh-CN,zh;q0.9, Referer: http://example.com/, Accept-Encoding: gzip, deflate }流量控制策略随机延迟time.sleep(random.uniform(0.5, 1.5))代理IP轮换使用免费代理池服务请求间隔控制在2-3秒/次重要遵守robots.txt规则设置合理的爬取频率避免对目标服务器造成负担4. 完整爬虫系统实现下面是一个增强版的爬虫实现包含错误处理和日志记录import requests from lxml import etree import re import os import time import random from pathlib import Path class ImageSpider: def __init__(self): self.base_url http://example.com/mv/ self.output_dir Path(./downloads) self.headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) } self.setup_dirs() def setup_dirs(self): self.output_dir.mkdir(exist_okTrue) def fetch_page(self, url): try: resp requests.get(url, headersself.headers, timeout10) resp.raise_for_status() return resp.text except Exception as e: print(f请求失败: {url}, 错误: {e}) return None def parse_list_page(self, html): tree etree.HTML(html) items [] for li in tree.xpath(//li[classitem]): item { title: li.xpath(.//h3/a/title)[0], url: li.xpath(.//div/a/href)[0] } items.append(item) return items def download_image(self, url, save_path): try: resp requests.get(url, streamTrue, timeout15) with open(save_path, wb) as f: for chunk in resp.iter_content(1024): f.write(chunk) print(f下载成功: {save_path}) return True except Exception as e: print(f下载失败: {url}, 错误: {e}) return False def run(self, pages5): for page in range(1, pages1): url f{self.base_url}page/{page} if page 1 else self.base_url html self.fetch_page(url) if not html: continue items self.parse_list_page(html) for item in items: self.process_item(item) time.sleep(random.uniform(0.5, 1.5)) def process_item(self, item): detail_html self.fetch_page(item[url]) if not detail_html: return tree etree.HTML(detail_html) images tree.xpath(//p[classimg_jz]/a/img/src) for idx, img_url in enumerate(images, 1): ext img_url.split(.)[-1].lower() if ext not in [jpg, jpeg, png, gif]: ext jpg filename f{item[title]}_{idx}.{ext} save_path self.output_dir / filename self.download_image(img_url, save_path) time.sleep(0.3) if __name__ __main__: spider ImageSpider() spider.run()5. 高级技巧与优化建议5.1 性能优化方案多线程下载实现from concurrent.futures import ThreadPoolExecutor def batch_download(urls): with ThreadPoolExecutor(max_workers4) as executor: executor.map(download_image, urls)存储优化策略使用哈希值命名避免重复下载实现断点续传功能添加图片MD5校验5.2 异常处理机制常见异常类型及处理方式异常类型触发场景解决方案ConnectionError网络连接问题重试机制代理切换Timeout服务器响应慢增加超时阈值404/403页面不存在/禁止访问跳过当前任务XPathError页面结构变化更新选择器5.3 数据存储方案对比存储方式选择参考本地文件系统优点简单直接无需额外依赖缺点难以管理大量文件数据库存储MySQL结构化存储元数据MongoDB适合非结构化数据云存储服务AWS S3/Azure Blob Storage七牛云/阿里云OSS6. 项目扩展方向这个基础爬虫可以进一步发展为完整的数据采集系统自动化调度添加定时任务APScheduler实现增量爬取可视化监控使用Prometheus收集指标Grafana展示爬虫状态分布式扩展基于Scrapy-Redis构建使用Celery任务队列数据处理流水线图片去重感知哈希自动 taggingCNN模型在实际项目中我们还需要考虑法律合规性。建议只爬取允许公开访问的内容并尊重网站的版权声明。对于商业用途的项目最好事先获得官方授权。