Python库 - Scrapy

Scrapy 是一个用于爬取网站数据、提取结构性数据的开源和协作框架。它最初是为网页抓取设计的,但也可以用于获取 API 提供的数据或作为通用的网络爬虫。


文章目录

      • 主要特性
      • 主要组件
      • 使用流程
      • 1. 安装 Scrapy
      • 2. 创建 Scrapy 项目
      • 3. 定义 Item(数据)
      • 4. 创建和编写 Spiders 文件
      • 5. 修改 settings.py 文件
      • 6. 运行 Scrapy 爬虫
      • 运行项目生成文件说明
        • 1. `scrapy.cfg`
        • 2. `myproject/`
          • a. `__init__.py`
          • b. `items.py`
          • c. `middlewares.py`
          • d. `pipelines.py`
          • e. `settings.py`
        • 3. `myproject/spiders/`
          • a. `__init__.py`
        • b. `myspider.py`
      • 数据存储
      • 1. 文件存储
        • a. JSON 文件
        • b. CSV 文件
      • 2. 数据库存储
        • a. SQLite
        • b. MySQL
        • c. MongoDB
      • 3. 其他存储方式
        • a. Elasticsearch
        • b. Amazon S3


主要特性

  1. 异步处理:Scrapy 使用 Twisted 异步网络库,可以高效处理多个并发请求。
  2. 内置支持选择器:Scrapy 内置支持 XPath 和 CSS 选择器来提取数据。
  3. 数据管道:提供数据处理管道,可以对抓取的数据进行清洗、验证和存储。
  4. 中间件:支持下载中间件和爬虫中间件,可以在请求和响应处理过程中插入自定义逻辑。
  5. 扩展性:可以通过编写扩展和中间件来扩展 Scrapy 的功能。
  6. 支持多种输出格式:可以将抓取的数据导出为 JSON、CSV、XML 等格式。
  7. 自动限速:内置支持自动限速,可以防止对目标网站造成过大压力。

主要组件

  1. Spider(爬虫):定义如何抓取某个网站或一组网站,包括如何执行抓取(即跟进链接)以及如何从页面中提取结构化数据。
  2. Item(项目):定义抓取的数据结构,类似于 Python 中的字典,但提供了更强的类型检查和验证。
  3. Item Pipeline(项目管道):负责处理被抓取的项目,通常包括数据清洗、验证和存储。
  4. Downloader Middleware(下载中间件):处理请求和响应的钩子框架,可以用于修改、丢弃或重试请求。
  5. Spider Middleware(爬虫中间件):处理爬虫的输入(响应)和输出(请求和项目)的钩子框架。

使用流程

Scrapy 是一个强大的 Python 爬虫框架,用于从网站中提取数据。以下是从创建项目到运行爬虫的详细步骤:

1. 安装 Scrapy

首先,需要安装 Scrapy。可以使用 pip 进行安装:

pip install scrapy

2. 创建 Scrapy 项目

使用以下命令创建一个新的 Scrapy 项目:

scrapy startproject myproject

这将在当前目录下创建一个名为 myproject 的文件夹,包含 Scrapy 项目的结构。

3. 定义 Item(数据)

Item 是用来定义要从网页中提取的数据结构。在 myproject/items.py 文件中定义 Item:

import scrapy

class MyItem(scrapy.Item):
    # 定义字段
    name = scrapy.Field()
    description = scrapy.Field()

4. 创建和编写 Spiders 文件

Spider 是 Scrapy 中用于定义如何抓取网站的类。在 myproject/spiders 目录下创建一个新的 Spider 文件,例如 myspider.py

import scrapy
from myproject.items import MyItem

class MySpider(scrapy.Spider):
    name = "myspider"
    start_urls = [
        'http://example.com',
    ]

    def parse(self, response):
        for item in response.css('div.item'):
            my_item = MyItem()
            my_item['name'] = item.css('h1::text').get()
            my_item['description'] = item.css('p::text').get()
            yield my_item

5. 修改 settings.py 文件

myproject/settings.py 文件中,可以配置 Scrapy 的各种设置,例如 USER_AGENT、ROBOTSTXT_OBEY 等:

BOT_NAME = 'myproject'

SPIDER_MODULES = ['myproject.spiders']
NEWSPIDER_MODULE = 'myproject.spiders'

USER_AGENT = 'Mozilla/5.0 (compatible; MyProject/1.0; +http://example.com)'

ROBOTSTXT_OBEY = True

6. 运行 Scrapy 爬虫

使用以下命令运行的 Spider:

scrapy crawl myspider

这将启动 myspider 并开始抓取数据。


运行项目生成文件说明

1. scrapy.cfg

这是项目的配置文件,通常位于项目的根目录下。它主要用于定义项目的部署配置。

[settings]
default = myproject.settings

[deploy]
#url = http://localhost:6800/
project = myproject
2. myproject/

这是项目的主目录,包含了项目的所有代码和配置文件。

a. __init__.py

这是一个空文件,用于标识 myproject 目录是一个 Python 包。

b. items.py

这个文件用于定义爬虫抓取的数据结构,即 Item。Item 类似于数据库中的表结构,用于存储爬取到的数据字段。

import scrapy

class MyItem(scrapy.Item):
    name = scrapy.Field()
    description = scrapy.Field()
c. middlewares.py

这个文件用于定义自定义的中间件。中间件可以用于处理请求和响应,例如添加自定义的 HTTP 头、处理重定向等。

class MyCustomMiddleware(object):
    def process_request(self, request, spider):
        request.headers['User-Agent'] = 'MyCustomUserAgent'
        return None
d. pipelines.py

这个文件用于定义数据处理管道。管道用于在数据被爬取后进行处理,例如清洗数据、验证数据、存储数据等。

class MyPipeline(object):
    def process_item(self, item, spider):
        # 处理 item 的逻辑
        return item
e. settings.py

这个文件包含了项目的所有配置。可以在这里设置爬虫的行为,例如设置 User-Agent、启用中间件、配置管道等。

BOT_NAME = 'myproject'

SPIDER_MODULES = ['myproject.spiders']
NEWSPIDER_MODULE = 'myproject.spiders'

USER_AGENT = {}
ROBOTSTXT_OBEY = True

ITEM_PIPELINES = {
    'myproject.pipelines.MyPipeline': 300,
}
3. myproject/spiders/

这个目录用于存放爬虫的代码。可以在这里创建多个爬虫文件,每个文件定义一个爬虫。

a. __init__.py

这是一个空文件,用于标识 spiders 目录是一个 Python 包。

b. myspider.py

这是一个示例爬虫文件,用于定义如何抓取网站的数据。

import scrapy

class MySpider(scrapy.Spider):
    name = "myspider"
    start_urls = [
        'http://example.com',
    ]

    def parse(self, response):
        for item in response.css('div.item'):
            yield {
                'name': item.css('h1::text').get(),
                'description': item.css('p::text').get(),
            }

数据存储

1. 文件存储

a. JSON 文件

JSON 是一种轻量级的数据交换格式,易于阅读和编写。

import json

def process_item(item):
    with open('data.json', 'a') as f:
        line = json.dumps(dict(item)) + "\n"
        f.write(line)
    return item
b. CSV 文件

CSV 文件是一种简单的表格数据存储格式。

import csv

def process_item(item):
    with open('data.csv', 'a', newline='') as f:
        writer = csv.writer(f)
        writer.writerow(item.values())
    return item

2. 数据库存储

a. SQLite

SQLite 是一种嵌入式数据库,适合小型项目。

import sqlite3

def process_item(item):
    conn = sqlite3.connect('data.db')
    c = conn.cursor()
    c.execute("INSERT INTO items VALUES (?, ?)", (item['name'], item['description']))
    conn.commit()
    conn.close()
    return item
b. MySQL

MySQL 是一种流行的关系型数据库,适合大型项目。

import mysql.connector

def process_item(item):
    conn = mysql.connector.connect(user='user', password='password', host='host', database='database')
    c = conn.cursor()
    c.execute("INSERT INTO items (name, description) VALUES (%s, %s)", (item['name'], item['description']))
    conn.commit()
    conn.close()
    return item
c. MongoDB

MongoDB 是一种 NoSQL 数据库,适合存储非结构化数据。

from pymongo import MongoClient

def process_item(item):
    client = MongoClient('localhost', 27017)
    db = client['mydatabase']
    collection = db['items']
    collection.insert_one(dict(item))
    return item

3. 其他存储方式

a. Elasticsearch

Elasticsearch 是一个基于 Lucene 的搜索引擎,适合存储和搜索大量数据。

from elasticsearch import Elasticsearch

def process_item(item):
    es = Elasticsearch()
    es.index(index='items', doc_type='item', body=dict(item))
    return item
b. Amazon S3

Amazon S3 是一种云存储服务,适合存储大量文件。

import boto3

def process_item(item):
    s3 = boto3.client('s3')
    s3.put_object(Bucket='mybucket', Key='data.json', Body=json.dumps(dict(item)))
    return item

上一篇:基于深度学习的组织病理学图像IDC检测方法