Scrapy爬虫快速入门

一、Scrapy爬虫框架简介

Scrapy是一个用Python写的Crawler Framework,简单轻巧,并且非常方便。Scrapy使用Twisted这个异步网络库来处理网络通信,架构清晰,并且包含了各种中间件接口,可以灵活地完成各种需求。

二、Scrapy爬虫架构中的各大组件

1. Scrapy引擎 (Engine)

引擎负责控制数据流在系统的所有组件中流动,并在相应动作发生时触发事件。

2.调度器(Scheduler)

调度器从引擎接受Request并将它们入队,以便之后引擎请求request时提供给引擎。

3.下载器(Downloader)

下载器负责获取页面数据并提供给引擎,而后提供给Spider。

4.Spider

Spider是Scrapy用户编写用于分析Reponse并提取Item(即获取到的需要的数据)或额外跟进的URL的类。每一个Spider负责处理一个特定(或一些)网站。

5.Item Pipeline

Item Pipeline负责处理被Spider提取出来的Item。典型的处理有:清理验证及持久化(例如储存到数据库中)

6.下载器中间件(Downloader middlewares)

下载器中间件是在引擎及下载器之间的特定钩子,处理下载器传递给引擎的Response。其提供了一个简便的机制,通过插入自定义代码来扩展Scrapy功能。

7.Spider 中间件(Spider middlewares)。

Spider中间件是在引擎及Spider之间的特定钩子,吹了Spider的输入(response)和输出(Items和Requests)。其提供了一个简便的机制,通过插入自定义代码来扩展Scrapy功能。

三、数据流(Scrapy工作流程)

通过数据流的流向,我们可以清楚地看到Scrapy的工作流程。

Scrapy的工作流程由执行引擎(Engine)控制,其过程如下:

1.引擎打开一个网站,找到处理该网站的Spider并向该Spider请求第一个要爬取的URL

2.引擎把这个URL转化为Request对象,并把这个Request对象传递给调度器(Scheduler)

3.引擎调度器请求下一个要爬取的URL,并把该URL请求通过下载器中间件(Downloader middlewares)传递给下载器(Downloader)

4.等待网页下载完毕,下载器会生成一个Response对象,并将其通过下载器中间件返回引擎,引擎通过Spider中间件把该Response传递给Spider

5.Spider处理Response并提取出数据或者URL,生成Items和Requests并移交给引擎

6.引擎将Items传递给Item Pipeline,将Requests传递给调度器

7.重复3-7,直到调度器中没有更多的Request,引擎关闭该网站。

四、Scrapy项目结构

安装scrapy(Python 2.7)

pip install scrapy

windows系统还要安装pywin32

pip install pywin32

初始化项目

scrapy startproject demo

项目文件就会自动被创建和初始化

初始化项目后,项目的结构是这样的:


items.py 定义一些储存数据的类

middlewares.py 定义中间件(下载器中间件、Spider中间件)

pipelines.py 定义处理Items的类

settings.py 顾名思义,scrapy全局设置

spiders/ 文件夹下放爬虫文件,一个py文件就是一个spider

scrapy.cfg 一般不需要改

四、编写和启动爬虫

1.items.py 定义一条数据的结构

# -*- coding: utf-8 -*-

# Define here the models for your scraped items
#
# See documentation in:
# https://doc.scrapy.org/en/latest/topics/items.html

import scrapy


class FangItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    title = scrapy.Field()
    area = scrapy.Field()
    price = scrapy.Field()

2.pipelines.py

# -*- coding: utf-8 -*-

# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://doc.scrapy.org/en/latest/topics/item-pipeline.html


class DemoPipeline(object):
    def process_item(self, item, spider):
        self.cu.execute("INSERT INTO fang VALUES(NULL, ?, ?, ?)", (item['title'], item['price'], item['area']))
        self.conn.commit()
        return item

    def __init__(self):
        import sqlite3
        self.conn = sqlite3.connect('fang_data.db')
        self.cu = self.conn.cursor()
        self.cu.execute("CREATE TABLE fang (id INTEGER PRIMARY KEY AUTOINCREMENT ,"
                        "title TEXT, "
                        "price FLOAT, "
                        "area TEXT)")

3.settings.py

激活pipeline

# Configure item pipelines
# See https://doc.scrapy.org/en/latest/topics/item-pipeline.html
ITEM_PIPELINES = {
    'demo.pipelines.DemoPipeline': 300,
}

4.编写spider

spiders/fang.py

# coding=utf-8
import scrapy
from demo.items import FangItem

class FangSpider(scrapy.Spider):
    name = "fang" # 爬虫的名称
    allowed_domains = ["fang.com"] # 允许的域名
    start_urls = ["http://esf.nc.fang.com/"] # 首次爬取的URL

    def parse(self, response):
        # 处理首次爬取的结果
        areas = response.xpath("//div[@class='qxName']/a")
        areas = areas[1:]

        areaUrls = ['http://esf.nc.fang.com' + area.xpath("@href").extract()[0] for area in areas]
        print(areaUrls)
        print(len(areaUrls))

        for i, area in enumerate(areas):
            if i == 0:
                continue
            areaName = area.xpath("text()")[0].extract()
            areaUrl = area.xpath("@href")[0].extract()
            areaRequest = scrapy.Request('http://esf.nc.fang.com' + areaUrl, meta={'areaName': areaName}, callback=self.parse_area)
            yield areaRequest

    def parse_area(self, response):
        # 处理各个地区的页面
        nextPage = response.xpath("//a[@id='PageControl1_hlk_next']/@href")

        if nextPage:
            nextPage = nextPage[0].extract()
            nextPageRequest = scrapy.Request('http://esf.nc.fang.com' + nextPage, meta=response.meta, callback=self.parse_area)
            print(nextPage)
            yield nextPageRequest
        houseList = response.xpath("//div[@class='houseList']/dl")
        for house in houseList:
            title = house.xpath("//p[@class='title']/a/text()")[0].extract()
            price = house.xpath("//span[@class='price']/text()")[0].extract()
            item = FangItem(title=title, price=price, area=response.meta['areaName'])
            yield item



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值