0

0

Python如何制作网络爬虫?Scrapy框架

看不見的法師

看不見的法師

发布时间:2025-08-12 09:35:01

|

928人浏览过

|

来源于php中文网

原创

使用python和scrapy制作网络爬虫的核心流程包括:安装scrapy、创建项目、定义spider、编写解析逻辑并利用选择器提取数据;2. scrapy通过设置user-agent、使用代理ip池、配置下载延迟和autothrottle、集成selenium或scrapy-splash等方式应对反爬机制;3. 数据存储与导出方式包括直接输出为json、csv、xml文件,或通过item pipelines将数据存入mysql、postgresql、sqlite、mongodb等数据库,也可推送至消息队列或云存储;4. 常见陷阱有选择器错误、allowed_domains限制、忽略robots.txt、异步逻辑误解和编码问题,调试技巧包括使用scrapy shell测试选择器、查看日志、保存响应内容、使用pdb断点调试以及设置dont_filter=true进行请求重试,最终通过持续测试与优化实现稳定抓取。

Python如何制作网络爬虫?Scrapy框架

用Python制作网络爬虫,特别是借助Scrapy框架,这绝对是条高效且令人着迷的路径。Scrapy不只是一个库,它是一整套成熟的爬虫框架,帮你把数据抓取、处理、存储的很多繁琐工作都自动化了,让你能更专注于如何从页面上提取你真正想要的信息。

解决方案

要用Python和Scrapy制作网络爬虫,核心流程其实挺清晰的,虽然初次接触可能会觉得概念有点多,但一旦上手,你会发现它真的能把效率拉满。

首先,你需要安装Scrapy。这很简单,打开你的终端或命令行,敲入:

pip install scrapy

安装完成后,我们通常会从创建一个Scrapy项目开始。这就像为你的爬虫任务搭一个脚手架:

scrapy startproject my_crawler_project

进入这个新创建的项目目录后,你就可以开始定义你的爬虫(Spider)了。Spider是Scrapy里最核心的部分,它定义了如何爬取一个网站以及如何从爬取到的页面中提取数据。你可以用命令生成一个基本的Spider:

cd my_crawler_project
scrapy genspider example_spider example.com

这会为你生成一个名为

example_spider.py
的文件,里面包含了基本的Spider结构。一个典型的Spider会包含
name
(爬虫的唯一标识)、
start_urls
(爬虫开始抓取的URL列表)和
parse
方法。
parse
方法是Scrapy收到响应后默认调用的回调函数,你在这里编写解析逻辑。

立即学习Python免费学习笔记(深入)”;

# my_crawler_project/my_crawler_project/spiders/example_spider.py
import scrapy

class ExampleSpider(scrapy.Spider):
    name = "example_spider"
    allowed_domains = ["example.com"] # 限制爬取范围,防止爬出界
    start_urls = ["http://www.example.com/page1", "http://www.example.com/page2"]

    def parse(self, response):
        # 这是一个示例,假设我们要提取页面标题和链接
        title = response.css('h1::text').get()
        links = response.css('a::attr(href)').getall()

        # 使用yield返回数据或新的请求
        yield {
            'title': title,
            'url': response.url,
            'extracted_links': links,
        }

        # 假设我们还想跟踪页面上的其他链接
        for next_page_link in links:
            if next_page_link is not None:
                # 使用response.urljoin处理相对路径
                yield response.follow(next_page_link, callback=self.parse)

在上面的

parse
方法中,我们使用了Scrapy强大的选择器(Selectors)来提取数据,支持CSS选择器和XPath。
yield
关键字在这里非常关键,它用于生成Item(你想要抓取的数据)或者新的Request(新的待抓取页面)。

通常,我们会定义一个

Item
来规范化我们想要抓取的数据结构。在
items.py
文件中:

# my_crawler_project/my_crawler_project/items.py
import scrapy

class MyCrawlerProjectItem(scrapy.Item):
    # 定义你的数据字段
    title = scrapy.Field()
    url = scrapy.Field()
    extracted_links = scrapy.Field()
    # 还可以添加其他字段,比如发布日期、作者等

然后,在你的Spider中导入并使用它:

# my_crawler_project/my_crawler_project/spiders/example_spider.py
# ...
from my_crawler_project.items import MyCrawlerProjectItem

class ExampleSpider(scrapy.Spider):
    # ...
    def parse(self, response):
        item = MyCrawlerProjectItem()
        item['title'] = response.css('h1::text').get()
        item['url'] = response.url
        item['extracted_links'] = response.css('a::attr(href)').getall()
        yield item
        # ...

数据抓取后,你可能还需要对它们进行清洗、验证或存储。Scrapy的

Item Pipelines
就是为此而生。在
pipelines.py
中定义你的处理逻辑,然后在
settings.py
中启用它们。

最后,运行你的爬虫,通常在项目根目录下执行:

scrapy crawl example_spider -o output.json
-o
参数可以将抓取到的数据直接输出到JSON、CSV等文件。

这只是Scrapy的冰山一角,它还有中间件、设置文件等诸多功能,让你可以精细控制爬虫的行为,处理各种复杂的场景。

Scrapy如何处理反爬机制?

在网络爬虫的世界里,反爬机制就像网站设下的迷宫,总得想办法绕过去。Scrapy本身虽然强大,但应对反爬,很多时候需要我们手动配置和一些策略。这不像有个按钮一按就搞定,更像是玩一场策略游戏,需要针对不同网站的特点来调整。

最常见也最基础的反爬,就是检查你的

User-Agent
。很多网站会识别那些一看就是机器人的
User-Agent
字符串,然后直接拒绝访问。Scrapy默认的
User-Agent
就是“Scrapy/X.Y.Z”,这明摆着告诉人家“我是爬虫”。解决办法很简单,在项目的
settings.py
里设置一个看起来像真实浏览器
User-Agent
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124124 Safari/537.36'
如果你想更进一步,可以维护一个
User-Agent
列表,通过自定义下载中间件(Downloader Middleware)来实现随机切换,让每次请求的身份都不同。

IP限制也是个大头。网站会监控来自同一个IP的请求频率,一旦发现异常,就可能封禁这个IP。这时,代理IP池就派上用场了。你可以购买或收集一些高质量的代理IP,然后同样通过下载中间件,让Scrapy的每个请求都通过不同的代理IP发出。这块儿配置起来稍微复杂一点,涉及到代理的验证、轮换策略,甚至失败重试机制。但一旦搭建起来,效果立竿见影。

请求频率控制也是一个关键点。有些网站不会直接封IP,而是通过返回验证码或者降低响应速度来“劝退”你。Scrapy的

DOWNLOAD_DELAY
设置就能派上用场,它会让你每次请求之间间隔一段时间,模拟人类的浏览行为。
DOWNLOAD_DELAY = 2  # 每次请求间隔2秒
Scrapy还有一个
AUTOTHROTTLE
扩展,能根据网站的响应情况动态调整下载延迟,这比固定延迟要智能得多,能更好地平衡效率和反反爬。

对于一些依赖JavaScript渲染内容的网站,Scrapy默认是无法处理的,因为它只抓取原始HTML。这时候,你就需要集成像

Scrapy-Splash
或者
Selenium
这样的工具
Scrapy-Splash
是一个轻量级的JavaScript渲染服务,Scrapy可以把请求发给它,让它渲染完成后再把HTML返回给Scrapy处理。而
Selenium
则是一个更重量级的浏览器自动化工具,可以模拟用户在浏览器中的所有操作,包括点击、滚动、填写表单等,但它的性能开销相对较大。

最后,遇到验证码(CAPTCHA)或者复杂的登录流程,这通常是最头疼的。简单的图片验证码可能可以接入第三方打码平台,但行为验证码、滑动验证码等就非常棘手了,很多时候需要人工介入或者更高级的机器学习模型来识别。这块儿往往是爬虫工程师最“绝望”的地方,因为这意味着你可能需要放弃一部分数据,或者投入巨大的精力去攻克。

总之,处理反爬是一个持续学习和迭代的过程,没有一劳永逸的方案。你需要根据目标网站的具体情况,灵活运用Scrapy的各种配置和扩展,甚至结合外部工具。

Scrapy的数据存储与导出有哪些方式?

Scrapy抓取到的数据,最终肯定是要保存下来的,不然爬虫就白忙活了。Scrapy在数据存储和导出方面提供了相当多的灵活性,从最简单的文件输出到复杂的数据库集成,应有尽有。我个人觉得,选择哪种方式,主要看你的数据量、后续的数据处理需求以及你对数据持久化的要求。

最直接、最便捷的方式,就是直接输出到文件。Scrapy内置了多种格式的导出器:

  • JSON/JSON Lines: 这是我最常用的,因为它结构清晰,易于阅读和解析。JSON Lines(每行一个JSON对象)特别适合大数据量,因为它允许你流式地写入和读取,而不需要一次性加载所有数据到内存。
    scrapy crawl your_spider -o output.json
    scrapy crawl your_spider -o output.jl
    (JSON Lines)
  • CSV: 如果你的数据结构比较扁平,或者需要用电子表格软件打开,CSV是个不错的选择。
    scrapy crawl your_spider -o output.csv
  • XML: 虽然现在用得少了,但Scrapy也支持XML格式导出。
    scrapy crawl your_spider -o output.xml

这些文件导出方式非常适合快速测试、小规模数据抓取或者作为临时存储。但对于需要频繁查询、更新或者大规模的数据,文件就不那么方便了。

这时候,数据库就成了更好的选择。Scrapy通过

Item Pipelines
与各种数据库无缝集成。
Item Pipelines
是Scrapy处理Item(你抓取到的数据)的组件链,每个Item在被Scrapy处理之前,都会经过你定义的管道。你可以在管道里进行数据清洗、去重,然后插入到数据库。

Videoleap
Videoleap

Videoleap是一个一体化的视频编辑平台

下载
  • 关系型数据库 (如MySQL, PostgreSQL, SQLite): 这种方式非常常见。你需要在

    pipelines.py
    中编写代码,使用像
    SQLAlchemy
    psycopg2
    mysql-connector-python
    这样的库来连接数据库,并执行INSERT或UPDATE操作。 一个简单的SQLite管道可能长这样:

    # my_crawler_project/my_crawler_project/pipelines.py
    import sqlite3
    
    class SQLitePipeline:
        def __init__(self):
            self.conn = sqlite3.connect('my_data.db')
            self.cur = self.conn.cursor()
            self.cur.execute('''
                CREATE TABLE IF NOT EXISTS articles (
                    title TEXT,
                    url TEXT PRIMARY KEY,
                    extracted_links TEXT
                )
            ''')
            self.conn.commit()
    
        def process_item(self, item, spider):
            try:
                self.cur.execute('''
                    INSERT INTO articles (title, url, extracted_links) VALUES (?, ?, ?)
                ''', (item.get('title'), item.get('url'), str(item.get('extracted_links'))))
                self.conn.commit()
            except sqlite3.IntegrityError: # 处理主键冲突,例如URL重复
                spider.logger.warning(f"Duplicate item found: {item.get('url')}")
            return item
    
        def close_spider(self, spider):
            self.conn.close()

    别忘了在

    settings.py
    中启用你的管道:
    ITEM_PIPELINES = {'my_crawler_project.pipelines.SQLitePipeline': 300,}

  • NoSQL数据库 (如MongoDB, Redis): 对于非结构化或半结构化数据,NoSQL数据库可能更合适。比如MongoDB,你可以直接将Scrapy Item(本质上是字典)存储为JSON文档。同样,你需要一个对应的Python客户端库(如

    pymongo
    )并在管道中实现逻辑。

除了这些,如果你需要将数据推送到消息队列(如Kafka, RabbitMQ)进行实时处理,或者上传到云存储(如AWS S3, Google Cloud Storage),也都可以通过自定义

Item Pipelines
来实现。管道的强大之处在于,它为你提供了一个集中处理抓取数据的“钩子”,你可以根据业务需求,自由地扩展和定制数据处理流程。

选择哪种存储方式,真的取决于你的具体需求。如果是为了快速验证一个想法,或者数据量不大,文件导出最省心。如果数据需要长期保存、频繁查询,或者与其他系统集成,那么数据库无疑是更专业的选择。

开发Scrapy爬虫时常见的陷阱与调试技巧?

开发Scrapy爬虫,就像解谜一样,充满乐趣,但也难免会遇到一些让你挠头的问题。我个人在调试Scrapy时,经常会遇到一些重复性的“坑”,但好在Scrapy提供了不少趁手的工具来帮助我们排查。

常见的陷阱:

  1. 选择器(Selectors)错误: 这是最最常见的。你看着浏览器开发者工具里的XPath或CSS路径,觉得万无一失,结果爬虫跑起来就是抓不到数据。

    • 原因: 网站的HTML结构可能动态加载、或者你复制的路径太绝对,经不起一点点变化。有时,
      ::text
      ::attr()
      的用法也会混淆。
    • 表现:
      item['field']
      为空,或者抓到了一堆
      None
  2. start_urls
    allowed_domains
    设置不当:

    • 原因:
      start_urls
      里写错了URL,或者
      allowed_domains
      设置得太严格,导致Scrapy直接过滤掉了有效的请求。
    • 表现: 爬虫启动后很快就结束,或者日志里出现大量“Filtered offsite request”的警告。
  3. 忽略

    robots.txt
    Scrapy默认是遵守
    robots.txt
    规则的。如果你要爬取的路径被
    robots.txt
    禁止了,Scrapy就不会去爬。

    • 原因: 没有在
      settings.py
      中设置
      ROBOTS_TXT_OBEY = False
      (如果你确实需要忽略)。
    • 表现: 爬虫不抓取任何页面,或者只抓取了
      robots.txt
      允许的部分。
  4. 异步特性理解不足: Scrapy是异步的,这意味着你的

    parse
    方法返回
    yield
    一个
    Request
    后,这个请求会立刻被调度,而不是等待当前页面的所有处理完成。如果你的逻辑依赖于某个请求的结果,但没有正确使用回调函数(
    callback
    ),就可能出问题。

    • 原因: 试图在
      parse
      方法中直接获取一个尚未完成的请求结果。
    • 表现: 数据缺失,或者逻辑流程混乱。
  5. 反爬机制触发: 网站检测到你是爬虫,直接返回空内容、验证码、或者HTTP 403/404/500错误。

    • 原因:
      User-Agent
      太明显、请求频率过高、没有使用代理等。
    • 表现: 日志里大量HTTP错误码,或者抓取到的页面内容不正确。
  6. 编码问题: 有时候,网站的编码不是UTF-8,或者响应头里没有正确声明编码,导致抓取到的中文等非ASCII字符显示为乱码。

    • 原因: 没有正确处理
      response.encoding
      或手动指定编码。
    • 表现: 抓取到的文本内容是乱码。

趁手的调试技巧:

  1. scrapy shell
    这是我的“瑞士军刀”。当你对某个页面的HTML结构或选择器拿不准时,
    scrapy shell
    能让你在一个交互式环境中模拟请求并测试选择器。
    scrapy shell "http://www.example.com/some_page"
    进入shell后,你可以直接使用
    response.css()
    response.xpath()
    来测试你的选择器,甚至可以
    view(response)
    在浏览器中查看当前响应的页面,这简直太方便了。

  2. 日志(Logging): Scrapy的日志系统非常详细,默认会输出很多有用的信息,比如请求状态码、被过滤的请求等。

    • 设置日志级别:
      settings.py
      中设置
      LOG_LEVEL = 'DEBUG'
      可以获取更详细的日志信息,帮助你追踪请求和响应的每一个细节。
    • 自定义日志: 在你的Spider中,可以使用
      self.logger.info("...")
      self.logger.debug("...")
      来输出自定义的调试信息,帮助你理解代码的执行流程和变量的值。
  3. 查看下载的响应: 当你怀疑某个请求返回的内容不对劲时,可以将

    response.body
    保存到本地文件,然后用浏览器打开查看。

    # 在parse方法中
    with open('debug_response.html', 'wb') as f:
        f.write(response.body)

    这能让你直观地看到Scrapy实际接收到的页面内容,判断是抓取问题还是解析问题。

  4. pdb
    或IDE调试器: 对于复杂的逻辑问题,直接在代码中设置断点,使用Python的内置调试器
    pdb
    或者PyCharm等IDE的调试功能,一步步跟踪代码执行,查看变量状态,是最直接有效的办法。

    import pdb; pdb.set_trace() # 在你想设置断点的地方加入这行
  5. dont_filter=True
    在调试Request时,如果你想重复发送某个请求(即使Scrapy认为它是重复的),可以在
    Request
    对象中设置
    dont_filter=True
    。这在测试特定URL或调试循环抓取时非常有用,但记得调试完要移除。

调试爬虫是一个经验积累的过程。多动手,多观察日志,多使用

scrapy shell
,你会发现自己解决问题的能力会越来越强。毕竟,每一次成功的爬取,背后都可能是一次又一次的试错和调整。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
mysql修改数据表名
mysql修改数据表名

MySQL修改数据表:1、首先查看数据库中所有的表,代码为:‘SHOW TABLES;’;2、修改表名,代码为:‘ALTER TABLE 旧表名 RENAME [TO] 新表名;’。php中文网还提供MySQL的相关下载、相关课程等内容,供大家免费下载使用。

668

2023.06.20

MySQL创建存储过程
MySQL创建存储过程

存储程序可以分为存储过程和函数,MySQL中创建存储过程和函数使用的语句分别为CREATE PROCEDURE和CREATE FUNCTION。使用CALL语句调用存储过程智能用输出变量返回值。函数可以从语句外调用(通过引用函数名),也能返回标量值。存储过程也可以调用其他存储过程。php中文网还提供MySQL创建存储过程的相关下载、相关课程等内容,供大家免费下载使用。

247

2023.06.21

mongodb和mysql的区别
mongodb和mysql的区别

mongodb和mysql的区别:1、数据模型;2、查询语言;3、扩展性和性能;4、可靠性。本专题为大家提供mongodb和mysql的区别的相关的文章、下载、课程内容,供大家免费下载体验。

281

2023.07.18

mysql密码忘了怎么查看
mysql密码忘了怎么查看

MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS 应用软件之一。那么mysql密码忘了怎么办呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

516

2023.07.19

mysql创建数据库
mysql创建数据库

MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS 应用软件之一。那么mysql怎么创建数据库呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

256

2023.07.25

mysql默认事务隔离级别
mysql默认事务隔离级别

MySQL是一种广泛使用的关系型数据库管理系统,它支持事务处理。事务是一组数据库操作,它们作为一个逻辑单元被一起执行。为了保证事务的一致性和隔离性,MySQL提供了不同的事务隔离级别。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

387

2023.08.08

sqlserver和mysql区别
sqlserver和mysql区别

SQL Server和MySQL是两种广泛使用的关系型数据库管理系统。它们具有相似的功能和用途,但在某些方面存在一些显著的区别。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

533

2023.08.11

mysql忘记密码
mysql忘记密码

MySQL是一种关系型数据库管理系统,关系数据库将数据保存在不同的表中,而不是将所有数据放在一个大仓库内,这样就增加了速度并提高了灵活性。那么忘记mysql密码我们该怎么解决呢?php中文网给大家带来了相关的教程以及其他关于mysql的文章,欢迎大家前来学习阅读。

605

2023.08.14

C++ 设计模式与软件架构
C++ 设计模式与软件架构

本专题深入讲解 C++ 中的常见设计模式与架构优化,包括单例模式、工厂模式、观察者模式、策略模式、命令模式等,结合实际案例展示如何在 C++ 项目中应用这些模式提升代码可维护性与扩展性。通过案例分析,帮助开发者掌握 如何运用设计模式构建高质量的软件架构,提升系统的灵活性与可扩展性。

14

2026.01.30

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 22.4万人学习

Django 教程
Django 教程

共28课时 | 3.7万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号