【0基础学爬虫】爬虫基础之scrapy的使用
字数 1799 2025-08-20 18:18:23

Scrapy爬虫框架全面教学文档

一、Scrapy简介

Scrapy是一个用于爬取网站并提取结构化数据的强大且灵活的开源框架。它具有以下特点:

  • 提供简单易用的工具和组件
  • 支持定义爬虫、调度请求、处理响应并存储提取的数据
  • 具有高效的异步处理能力
  • 支持分布式爬取
  • 通过中间件和扩展机制可以方便地定制和扩展功能
  • 广泛应用于数据挖掘、信息聚合和自动化测试等领域

二、Scrapy工作流程

  1. 启动爬虫:Scrapy启动并激活爬虫,从初始URL开始爬取
  2. 调度请求:爬虫生成初始请求,并将其发送给调度器
  3. 下载页面:调度器将请求发送给下载器,下载器从互联网获取页面
  4. 处理响应:下载器将响应返回给引擎,传递给爬虫
  5. 提取数据:爬虫从响应中提取数据(items)和更多的URL(新的请求)
  6. 处理数据:提取的数据通过项目管道进行处理,清洗并存储
  7. 继续爬取:新的请求被调度器处理,继续下载和提取数据,直到所有请求处理完毕

三、Scrapy安装与项目创建

1. 安装Scrapy

pip install scrapy

2. 创建新项目

scrapy startproject scrapy_demo

3. 创建爬虫模板

cd scrapy_demo
scrapy genspider example example.com

4. 项目结构说明

scrapy_demo/
    ├── spiders/          # 存放爬虫文件
    ├── items.py          # 定义爬取的数据结构
    ├── middlewares.py    # 定义下载中间件和爬虫中间件
    ├── pipelines.py      # 定义管道,用于处理爬虫提取的数据
    ├── settings.py       # 项目的基本配置

四、Scrapy基本使用

1. 编写基础爬虫

import scrapy

class ExampleSpider(scrapy.Spider):
    name = "example"
    start_urls = ["https://movie.douban.com/top250"]

    def parse(self, response):
        print(response.text)

2. 运行爬虫

scrapy crawl example

3. 解决403问题和robots协议

在settings.py中修改:

# 不遵守robots协议
ROBOTSTXT_OBEY = False

# 设置默认请求头
DEFAULT_REQUEST_HEADERS = {
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
    "Accept-Language": "en",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36 Edg/125.0.0.0"
}

4. 两种运行方式

  1. 终端运行:
scrapy crawl example
  1. Python脚本运行:
from scrapy import cmdline

if __name__ == '__main__':
    cmdline.execute("scrapy crawl example".split())
    # 不输出提示信息
    # cmdline.execute("scrapy crawl example --nolog".split())

五、数据提取与翻页

1. 数据提取示例

def parse(self, response):
    ol_list = response.xpath('//ol[@class="grid_view"]/li')
    for ol in ol_list:
        item = {}
        item['title'] = ol.xpath('.//div[@class="hd"]/a/span[1]/text()').extract_first()
        item['rating'] = ol.xpath('.//div[@class="bd"]/div/span[2]/text()').extract_first()
        item['quote'] = ol.xpath('.//div[@class="bd"]//p[@class="quote"]/span/text()').extract_first()
        print(item)

2. 翻页处理两种方式

方式一:使用callback回调

def parse(self, response):
    # ...数据提取代码...
    if response.xpath("//a[text()='后页>']/@href").extract_first() is not None:
        next_url = response.urljoin(response.xpath("//a[text()='后页>']/@href").extract_first())
        yield scrapy.Request(url=next_url, callback=self.parse)

方式二:重写start_requests方法

def start_requests(self):
    for i in range(0, 5):
        url = 'https://movie.douban.com/top250?start={}&filter='.format(i * 25)
        yield scrapy.Request(url)

六、Scrapy Item使用

1. 定义Item

import scrapy

class ScrapyDemoItem(scrapy.Item):
    title = scrapy.Field()
    rating = scrapy.Field()
    quote = scrapy.Field()

2. 使用Item

from scrapy_demo.items import ScrapyDemoItem

def parse(self, response):
    ol_list = response.xpath('//ol[@class="grid_view"]/li')
    for ol in ol_list:
        item = ScrapyDemoItem()
        item['title'] = ol.xpath('.//div[@class="hd"]/a/span[1]/text()').extract_first()
        item['rating'] = ol.xpath('.//div[@class="bd"]/div/span[2]/text()').extract_first()
        item['quote'] = ol.xpath('.//div[@class="bd"]//p[@class="quote"]/span/text()').extract_first()
        yield item

七、数据存储Pipeline

1. MySQL存储示例

import pymysql
from itemadapter import ItemAdapter

class MysqlPipeline:
    def __init__(self):
        self.connection = pymysql.connect(
            user='root',
            password='root',
            db='scrapy_demo',
        )
        self.cursor = self.connection.cursor()
        self.create_table()

    def create_table(self):
        table = """
        CREATE TABLE IF NOT EXISTS douban (
            id INT AUTO_INCREMENT PRIMARY KEY,
            title VARCHAR(255) NOT NULL,
            rating FLOAT NOT NULL,
            quote TEXT
        )CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
        """
        self.cursor.execute(table)
        self.connection.commit()

    def process_item(self, item, spider):
        try:
            self.cursor.execute("INSERT INTO douban(id,title, rating, quote) VALUES (%s,%s, %s, %s)",
                              (0, item['title'], item['rating'], item['quote']))
            self.connection.commit()
        except pymysql.MySQLError as e:
            spider.logger.error(f"Error saving item: {e}")
            print(e)
        return item

    def close_spider(self, spider):
        self.cursor.close()
        self.connection.close()

2. 启用Pipeline

在settings.py中:

ITEM_PIPELINES = {
    "scrapy_demo.pipelines.MysqlPipeline": 300,
}

八、Scrapy中间件

1. 下载中间件基础

from feapder.network import user_agent

class ScrapyDemoDownloaderMiddleware:
    def process_request(self, request, spider):
        request.headers['User-Agent'] = user_agent.get()
        return None

2. 设置代理

def process_request(self, request, spider):
    request.headers['User-Agent'] = user_agent.get()
    request.meta['proxy'] = "http://127.0.0.1:7890"
    return None

3. 中间件权重

在settings.py中:

DOWNLOADER_MIDDLEWARES = {
    "scrapy_demo.middlewares.OneMiddleware": 543,
    "scrapy_demo.middlewares.TwoMiddleware": 544
}

九、Scrapy-Redis分布式爬虫

1. 安装

pip install scrapy-redis

注意:Scrapy版本需要替换成2.9.0版本或者2.0.0以下

2. 配置

在settings.py中:

# 设置Redis主机和端口
REDIS_URL = 'redis://127.0.0.1:6379/0'

# 使用Scrapy-Redis的调度器
SCHEDULER = "scrapy_redis.scheduler.Scheduler"

# 使用Scrapy-Redis的去重器
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"

# 开启redis管道
ITEM_PIPELINES = {
    "scrapy_redis.pipelines.RedisPipeline": 301
}

3. 编写Redis爬虫

from scrapy_redis.spiders import RedisSpider

class RedisDemoSpider(RedisSpider):
    name = "redis_demo"
    redis_key = "redis_demo:start_urls"  # redis key

    def parse(self, response):
        ol_list = response.xpath('//ol[@class="grid_view"]/li')
        for ol in ol_list:
            item = {}
            item['title'] = ol.xpath('.//div[@class="hd"]/a/span[1]/text()').extract_first()
            item['rating'] = ol.xpath('.//div[@class="bd"]/div/span[2]/text()').extract_first()
            item['quote'] = ol.xpath('.//div[@class="bd"]//p[@class="quote"]/span/text()').extract_first()
            print(item)
            yield item

4. 添加URL到Redis队列

import redis

r = redis.Redis(db=0)
r.lpush('redis_demo:start_urls', "https://movie.douban.com/top250")

5. 持久化存储

在settings.py中:

SCHEDULER_PERSIST = True  # 持久化爬取状态

6. 分布式配置

在settings.py中修改Redis连接:

REDIS_URL = '远程电脑ip地址'

十、关键对象说明

1. Request对象参数

参数 描述
url 请求的URL
callback 用于处理该请求的回调函数,默认是parse方法
method HTTP请求方法,如'GET','POST'等,默认为'GET'
headers 请求头信息
body 请求体,通常在POST请求中使用
cookies 请求携带的Cookies
meta 该请求的元数据字典,用于在不同请求之间传递数据
encoding 请求的编码格式,默认为'utf-8'
priority 请求的优先级,默认值为0

2. Response对象参数

参数 描述
url 响应的URL
status HTTP响应状态码
headers 响应头信息
body 响应体内容,二进制格式
flags 响应的标志列表
request 生成此响应的请求对象
meta 该请求的元数据字典
encoding 响应的编码格式
text 响应体内容,解码为字符串格式
css CSS选择器
xpath XPath选择器
json 解析JSON响应体并返回字典或列表

十一、最佳实践建议

  1. 遵守robots协议:除非必要,否则应遵守目标网站的robots.txt规则
  2. 设置合理的请求间隔:避免对目标网站造成过大压力
  3. 处理异常情况:网络错误、页面解析失败等情况应有相应处理
  4. 日志记录:记录爬取过程中的关键信息,便于排查问题
  5. 数据去重:使用Scrapy-Redis或其他方式实现数据去重
  6. 分布式部署:对于大规模爬取任务,考虑使用分布式架构
  7. 遵守法律法规:确保爬取行为符合相关法律法规和网站使用条款
Scrapy爬虫框架全面教学文档 一、Scrapy简介 Scrapy是一个用于爬取网站并提取结构化数据的强大且灵活的开源框架。它具有以下特点: 提供简单易用的工具和组件 支持定义爬虫、调度请求、处理响应并存储提取的数据 具有高效的异步处理能力 支持分布式爬取 通过中间件和扩展机制可以方便地定制和扩展功能 广泛应用于数据挖掘、信息聚合和自动化测试等领域 二、Scrapy工作流程 启动爬虫 :Scrapy启动并激活爬虫,从初始URL开始爬取 调度请求 :爬虫生成初始请求,并将其发送给调度器 下载页面 :调度器将请求发送给下载器,下载器从互联网获取页面 处理响应 :下载器将响应返回给引擎,传递给爬虫 提取数据 :爬虫从响应中提取数据(items)和更多的URL(新的请求) 处理数据 :提取的数据通过项目管道进行处理,清洗并存储 继续爬取 :新的请求被调度器处理,继续下载和提取数据,直到所有请求处理完毕 三、Scrapy安装与项目创建 1. 安装Scrapy 2. 创建新项目 3. 创建爬虫模板 4. 项目结构说明 四、Scrapy基本使用 1. 编写基础爬虫 2. 运行爬虫 3. 解决403问题和robots协议 在settings.py中修改: 4. 两种运行方式 终端运行: Python脚本运行: 五、数据提取与翻页 1. 数据提取示例 2. 翻页处理两种方式 方式一:使用callback回调 方式二:重写start_ requests方法 六、Scrapy Item使用 1. 定义Item 2. 使用Item 七、数据存储Pipeline 1. MySQL存储示例 2. 启用Pipeline 在settings.py中: 八、Scrapy中间件 1. 下载中间件基础 2. 设置代理 3. 中间件权重 在settings.py中: 九、Scrapy-Redis分布式爬虫 1. 安装 注意:Scrapy版本需要替换成2.9.0版本或者2.0.0以下 2. 配置 在settings.py中: 3. 编写Redis爬虫 4. 添加URL到Redis队列 5. 持久化存储 在settings.py中: 6. 分布式配置 在settings.py中修改Redis连接: 十、关键对象说明 1. Request对象参数 | 参数 | 描述 | |------|------| | url | 请求的URL | | callback | 用于处理该请求的回调函数,默认是parse方法 | | method | HTTP请求方法,如'GET','POST'等,默认为'GET' | | headers | 请求头信息 | | body | 请求体,通常在POST请求中使用 | | cookies | 请求携带的Cookies | | meta | 该请求的元数据字典,用于在不同请求之间传递数据 | | encoding | 请求的编码格式,默认为'utf-8' | | priority | 请求的优先级,默认值为0 | 2. Response对象参数 | 参数 | 描述 | |------|------| | url | 响应的URL | | status | HTTP响应状态码 | | headers | 响应头信息 | | body | 响应体内容,二进制格式 | | flags | 响应的标志列表 | | request | 生成此响应的请求对象 | | meta | 该请求的元数据字典 | | encoding | 响应的编码格式 | | text | 响应体内容,解码为字符串格式 | | css | CSS选择器 | | xpath | XPath选择器 | | json | 解析JSON响应体并返回字典或列表 | 十一、最佳实践建议 遵守robots协议 :除非必要,否则应遵守目标网站的robots.txt规则 设置合理的请求间隔 :避免对目标网站造成过大压力 处理异常情况 :网络错误、页面解析失败等情况应有相应处理 日志记录 :记录爬取过程中的关键信息,便于排查问题 数据去重 :使用Scrapy-Redis或其他方式实现数据去重 分布式部署 :对于大规模爬取任务,考虑使用分布式架构 遵守法律法规 :确保爬取行为符合相关法律法规和网站使用条款