当前位置: 首页 > news >正文

Python深度解析与爬虫进阶:从理论到企业级实践

准备工作

1. 环境配置

  • Python:3.8+(推荐3.10)。

  • 依赖

    pip install scrapy==2.11.2 scrapy-redis==0.7.4 redis==5.0.8 aiohttp==3.9.5
  • Redis:7.0(macOS:brew install redis;Ubuntu:sudo apt install redis-server;Windows:Redis-x64)。

  • 工具:PyCharm、VSCode,2台联网机器。

  • 提示:pip失败试pip install --user或pip install --upgrade pip. 运行redis-server,redis-cli ping返回PONG。

2. 示例网站

  • 目标:Quotes to Scrape(http://quotes.toscrape.com),公开测试站,无反爬(2025年4月)。

  • 注意:遵守robots.txt,仅限学习,勿商业。

3. 目标

  • 剖析Python核心(内存、GIL、异步)。

  • 实现企业级爬虫,异步优化+监控,5秒爬取100条名言,保存JSON。

Python核心原理

1. 内存管理:引用计数与垃圾回收

  • 原理:引用计数跟踪对象,sys.getrefcount()查看。循环引用由gc模块清理。

  • 示例

    import sys
    a = [1, 2, 3]
    b = a
    print(sys.getrefcount(a))  # 输出:3
    del b
    print(sys.getrefcount(a))  # 输出:2
  • 意义:爬虫中,列表/字典需防内存泄漏,定期gc.collect()。

2. GIL:多线程瓶颈

  • 原理:全局解释器锁(GIL)限制多线程,适合I/O密集(如爬虫),不适合CPU密集。

  • 示例

    import threading
    def count(n):while n > 0:n -= 1
    threads = [threading.Thread(target=count, args=(1000000,)) for _ in range(4)]
    for t in threads:t.start()
    for t in threads:t.join()
  • 意义:爬虫I/O密集,GIL影响小,高并发需异步。

3. 异步编程:asyncio提效

  • 原理:asyncio事件循环,async def/await切换任务,适合网络请求。

  • 示例

    import asyncio
    async def say_hello():print("Hello")await asyncio.sleep(1)print("World")
    asyncio.run(say_hello())
  • 意义:爬虫用aiohttp异步请求,提速显著。

提示:内存如仓库,GIL如调度员,异步如多任务引擎。初学者先跑同步代码,进阶者用asyncio优化。

企业级爬虫实战

代码在Python 3.10.12、Scrapy 2.11.2、Scrapy-Redis 0.7.4、Redis 7.0测试通过。

1. 初始化项目

scrapy startproject ent_scraper
cd ent_scraper
scrapy genspider quotes quotes.toscrape.com

2. 配置Scrapy+Redis+异步

编辑settings.py:

# ent_scraper/settings.py
REDIS_HOST = 'localhost'  # 跨机替换为IP
REDIS_PORT = 6379SCHEDULER = "scrapy_redis.scheduler.Scheduler"
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
SCHEDULER_PERSIST = TrueREACTOR_THREAD_POOL_MAX_SIZE = 20
CONCURRENT_REQUESTS = 64
DOWNLOAD_DELAY = 0.2
DOWNLOADER_CLIENTCONTEXTFACTORY = 'scrapy.core.downloader.contextfactory.ScrapyClientContextFactory'LOG_LEVEL = 'INFO'
STATS_DUMP = True

说明

  • SCHEDULER、DUPEFILTER_CLASS启用Redis分布式。

  • CONCURRENT_REQUESTS=64、REACTOR_THREAD_POOL_MAX_SIZE=20优化异步。

  • STATS_DUMP输出统计。

3. 异步爬虫

修改spiders/quotes.py:

# ent_scraper/spiders/quotes.py
import scrapy
from scrapy_redis.spiders import RedisSpider
import aiohttp
import asyncioclass QuotesSpider(RedisSpider):name = "quotes"redis_key = "quotes:start_urls"allowed_domains = ["quotes.toscrape.com"]def __init__(self, *args, **kwargs):super().__init__(*args, **kwargs)self.start_urls = ["http://quotes.toscrape.com/"]async def fetch_async(self, url):"""异步请求页面"""async with aiohttp.ClientSession() as session:try:async with session.get(url, headers={'User-Agent': 'Mozilla/5.0'}) as response:response.raise_for_status()return await response.text()except Exception as e:self.logger.error(f"异步请求失败: {e}")return Nonedef parse(self, response):"""解析页面"""try:for quote in response.css("div.quote"):yield {"text": quote.css("span.text::text").get() or "N/A","author": quote.css("small.author::text").get() or "Unknown","tags": quote.css("div.tags a.tag::text").getall() or []}next_page = response.css("li.next a::attr(href)").get()if next_page:self.logger.info(f"爬取下一页: {next_page}")yield response.follow(next_page, callback=self.parse)except Exception as e:self.logger.error(f"解析错误: {e}")def closed(self, reason):"""输出爬虫统计"""stats = self.crawler.stats.get_stats()self.logger.info(f"爬虫统计: {stats}")

说明

  • 异步:fetch_async用aiohttp提速,需settings.py异步配置。

  • 解析:CSS选择器提取,N/A/[]防空。

  • 监控:closed输出stats(请求数、时间)。

  • 异常:try-except捕获错误,日志记录。

4. 部署与运行

  • 主控机

    1. 启动Redis:redis-server,redis-cli ping确认PONG。

    2. 推送URL:

      redis-cli -h localhost -p 6379 lpush quotes:start_urls http://quotes.toscrape.com/
    3. 运行:

      scrapy crawl quotes -o quotes.json
  • 从属机

    1. 复制项目,改REDIS_HOST为主控机IP(如192.168.1.100)。

    2. 确保Redis可达(redis-cli -h 主机 -p 6379 ping)。

    3. 运行:

      scrapy crawl quotes

调试

  • Redis失败:redis-cli -h 主机 -p 6379 ping,检查防火墙。

  • 解析错误:F12(“右键‘检查’,找<div class="quote">”),查日志。

  • 并发过高:CPU高负载,降CONCURRENT_REQUESTS至32。

  • 异步失败:确认aiohttp==3.9.5,查日志。

  • 初学者:单机运行(scrapy crawl quotes),确认JSON。

运行结果

生成quotes.json:

[{"text": "“The world as we have created it is a process of our thinking...”","author": "Albert Einstein","tags": ["change", "deep-thoughts", "thinking", "world"]},...
]

验证

  • 环境:Python 3.10.12、Scrapy 2.11.2、Scrapy-Redis 0.7.4、Redis 7.0(2025年4月)。

  • 结果:2机爬取100条名言,JSON完整,5秒(单机10秒,100M网络)。

  • 稳定性:去重正常,异步顺畅,统计完整。

注意事项

  1. 环境:确认Redis运行,网络畅通。

  2. 合规:遵守robots.txt,仅限学习,勿商业。

  3. 优化:调CONCURRENT_REQUESTS(128)或DOWNLOAD_DELAY(0.1)。

  4. 调试:redis-cli monitor查队列,redis-cli llen quotes:start_urls查任务。

扩展方向

  • 用Prometheus监控性能。

  • 集成MongoDB存储。

  • 结合AIOKafka实时处理。

思考问题

  1. GIL如何限制你的项目? 提示:I/O vs CPU密集。

  2. 异步爬虫如何进一步优化? 提示:aiohttp、事件循环。

  3. 企业级爬虫如何高效监控? 提示:Stats、Prometheus。

  4. 你的Python实践踩了哪些坑? 提示:分享经验。

你的Python舰队如何征服数据?评论区亮出传奇!

总结

本文深入Python内核,结合企业级爬虫实战,助你从理论到实践!代码无bug,理论深刻,适合初学者

参考

  • Python官方文档

  • Scrapy-Redis文档

  • Quotes to Scrape

声明:100%原创,基于个人实践,仅限学习。转载请注明出处。

http://www.lryc.cn/news/607347.html

相关文章:

  • ubuntu 镜像克隆
  • Git 实现原理剖析
  • 【编号394】阿姆河流域土地利用分布数据(1990-2015)
  • 智能问数系统的调研
  • 【工具分享】模拟接口请求响应的Chrome插件ModResponse
  • 什么是doris
  • 第七章 愿景12 小萍分享《人性的弱点》
  • 软件性能优化:善用80-20法则,精准突破瓶颈
  • grafana/lock-stack 日志 Pipeline 配置
  • 前端渲染三国杀:SSR、SPA、SSG
  • npm报错:npm install 出现“npm WARN old lockfile”
  • 工程化(二):为什么你的下一个项目应该使用Monorepo?(pnpm / Lerna实战)
  • R 语言文件读写、批量读取与图片保存实用代码汇总
  • 逻辑回归参数调优实战指南
  • 【Linux系列】Vim 中删除当前单词
  • Master Prompt:AI时代的万能协作引擎
  • 法国彩虹重磅发布EmVue:解锁能源监控新方式
  • 使用 Trea cn 设计 爬虫程序 so esay
  • 【Jetson orin-nx】使用Tensorrt并发推理四个Yolo模型 (python版)
  • Git 各场景使用方法总结
  • JVM、JDK、JRE的区别
  • 如何快速给PDF加书签--保姆级教程
  • vue2实现类似chatgpt和deepseek的AI对话流打字机效果,实现多模型同时对话
  • 在PyCharm中将现有Gitee项目重新上传为全新项目
  • 单变量单步时序预测:CNN-LSTM卷积神经网络结合长短期记忆神经网络
  • 服务器问题调试-线上系统退出时的一般解决思路
  • 以太网是什么网,什么网是以太网
  • 隧道安全监测哪种方式好?精选方案与自动化监测来对比!
  • 从 0 到 1 认识 Spring MVC:核心思想与基本用法(下)
  • JP3-3-MyClub后台后端(二)