Scrapy框架入门学习(附实例)

0. 前言

这是我在imooc上学习Scrapy框架的笔记,还附上了一个我为校内课程写的大作业(很简略),并在最后加上了我自己实践中遇到的一些问题的解决方法,希望能对大家学习、入门Scrapy有所帮助。

课程网址:

https://www.icourse163.org/course/BIT-1001870001?tid=1450316449


1. Scrapy框架结构

在这里插入图片描述


首先,spiders把request通过engine发送给scheduler(在这里,request可以理解为网页的url),然后由scheduler安排爬取。

然后,scheduler把request通过engine发送给downloader,downloader是真实从网页爬取数据的。爬取获得数据后,返回response给spiders。

最后,spiders处理该response后,产生了两个数据类:item和request。item是数据项,request是新的爬取请求(如果网页上有其他我们感兴趣的内容)。spiders将这两个数据类发送给engine,engine把item发给item pipeline,把request发送给scheduler。

在这个结构中,engine,downloader,scheduler都是已有实现的。用户只需自己编写spiders(入口)和item pipeline(出口)。其中,spiders提供url并解析response,而item pipeline负责提取的数据的后处理。

2. Scrapy框架结构解析

2.1 Engine

  • 控制所有模块之间的数据流
  • 根据条件触发事件

2.2 Downloader

  • 根据请求下载网页

2.3 Scheduler

  • 对所有爬取请求进行调度管理

2.4 Spiders

  • 解析Downloader返回的响应(response)
  • 产生爬取项(scraped item)
  • 产生额外的爬取请求(request)

整个Scrapy框架的核心。负责提供url、解析数据……也是用户主要编写的部分。

2.5 Items Pipelines

  • 以流水线方式处理Spiders产生的爬取项
  • 由一组操作顺序组成,类似流水线,每个操作是一个Items Pipeline类型
  • 可能操作包括:清理、检验、查重爬取项中的HTML数据、将数据存储到数据库。

用户需要关心的是:我们希望对提取出来的item类型的数据怎么做?是存储?还是其它?

3. Scrapy常用命令

Scrapy命令行格式:

scrapy <command> [options] [args]

其中,command是Scrapy的命令。具体如下:

  • startproject

    创建一个新工程。格式:

    scrapy startproject <name> [dir]
    
  • genspider

    创建一个爬虫。格式:

    scrapy genspider [options] <name> <domain>
    
  • settings

    获得爬虫的配置信息。格式:

    scrapy settings [options]
    
  • crawl

    运行一个爬虫。格式:

    scrapy crawl <spider>
    
  • list

    列出工程中所有的爬虫。格式:

    scrapy list
    
  • shell

    启动url调试命令行。格式:

    scrapy shell [url]
    

4. Scrapy基本使用

4.1 yield关键字

要了解yield,就要先了解生成器的概念。什么是生成器?

  • 生成器是一个不断产生值的函数
  • 包含yield语句的函数是一个生成器
  • 生成器每次产生一个值(执行一个yield语句),函数被冻结,被唤醒后再产生一个值。

要注意的是,每次冻结之后唤醒生成器,代码还是从刚刚冻结的地方开始运行。这样,函数不停执行,就会源源不断地产生新的值。


生成器常和for循环搭配:

def gen(n):#生成小于n的数的平方
    for i in range(n):
		yield i**2
    
for i in gen(5):
    print(i, " ")

上述代码得到结果:

0 1 4 9 16

相比于直接用列表形式返回给上层调用函数,生成器的优势是:

  • 节省存储空间
  • 响应更加迅速
  • 使用更加灵活

实现同样的功能,列表形式需要存储许多的值。而生成器每次只产生存储一个值,再次调用时产生第二个值,所以只要一个值的存储空间。

4.2 简单实例

这里爬取的对象为中国天气网(上海未来多天的)天气信息。

第一步:

进入文件夹,创建项目:

scrapy startproject weather

创建完成!可以看到新生成的目录结构,有一个名字为weather的文件夹。该文件夹下,有以下文件或文件夹(这里挑选两个重点文件(夹)说明):

  • items.py

    Items代码模板

  • spiders/

    Spiders代码模板目录,存放爬虫。我们可以在这里生成爬虫。

第二步:

定义保存爬取内容的容器。在新建的WeatherItems.py里定义,当然,我们也可以直接在items.py里编写。

#引入文件
import scrapy

class WeatherItem(scrapy.Item):
    #日期
    date = scrapy.Field()
    #天气状况
    weather = scrapy.Field()
    #最高温度
    maxT = scrapy.Field()
    #最低温度
    minT = scrapy.Field()
    #风向
    direct = scrapy.Field()
    #风力
    wind = scrapy.Field()

第三步:

生产一个爬虫。

我们可以直接在spiders/文件夹下直接创建一个.py文件,也可以通过上述命令行格式来生成。生成的爬虫文件初始内容如下(这里我定义文件名为MySpider):

#引入文件
import scrapy

class MySpider(scrapy.Spider):
    #用于区别Spider,爬虫的名字
    name = "MySpider"
    #允许访问的域
    allowed_domains = [""]
    #爬取的地址
    start_urls = [""]
    #爬取方法,解析内容
    def parse(self, response):
        pass

第四步:

配置爬虫。

设置好要爬取网页的url. 设计爬取方法parse,parse()方法负责处理response并返回处理的数据以及跟进的url.


在parse()方法中,我们可以使用任意的HTML信息提取方法,比如:Beautiful Soup, lxml,XPath,CSS Selector.这里使用的是XPath.

import scrapy
#引入容器
from weather.WeatherItems import WeatherItem

class MySpider(scrapy.Spider):
    #设置name
    name = "MySpider"
    #设定域名
    #allowed_domains = [""]
    #填写爬取地址
    start_urls = ["http://www.weather.com.cn/weather15d/101020100.shtml"]
    #编写爬取方法
    def parse(self, response):
        item = WeatherItem()
        for box in response.xpath('//ul[@class="t clearfix"]/li'):
            #获取日期
            item['date'] = box.xpath('./span[@class="time"]/text()').extract()[0].strip()
            #获取天气信息
            item['weather'] = box.xpath('./span[@class="wea"]/text()').extract()[0].strip()
            #获取最高温度
            item['maxT'] = box.xpath('./span[@class="tem"]/em/text()').extract()[0].strip()
            #获取最低温度(这里因为网站上最低温度默认带了一个‘/’,所以去掉第零位,取字符串的第一位到最后一位)
            item['minT'] = box.xpath('./span[@class="tem"]/text()').extract()[0][1:]
            #获取风向
            item['direct'] = box.xpath('./span[@class="wind"]/text()').extract()[0].strip()
            #获取风力
            item['wind'] = box.xpath('./span[@class="wind1"]/text()').extract()[0].strip()

            yield item

第五步:


编写pipelines文件。我这里新建了一个名为MyPipelines.py的文件。也可以直接在pipelines.py文件下编写。spiders生成类似字典的键值对交由pipeline.把数据保存入data.json文件。

#引入文件
from scrapy.exceptions import DropItem
import json

class MyPipeline(object):
    def __init__(self):
        #打开文件
        self.file = open('data.json', 'w', encoding='utf-8')
    #该方法用于处理数据
    def process_item(self, item, spider):
        #读取item中的数据
        line = json.dumps(dict(item), ensure_ascii=False) + "\n"
        #写入文件
        self.file.write(line)
        #返回item
        return item
    #该方法在spider被开启时被调用。
    def open_spider(self, spider):
        pass
    #该方法在spider被关闭时被调用。
    def close_spider(self, spider):
        pass

注册pipeline,在settings.py里有被注释掉的部分,去掉注释:

#ITEM_PIPELINES = {
    
    
#    'scrapytest.pipelines.MyPipeline': 300,
#工程名+文件名+类名}

第六步:

运行爬虫。命令行输入:

scrapy crawl MySpider

在设置好的data.json文件中就能看到结果。


在这里插入图片描述


5. 常见问题

正常来说,成功爬取到数据时终端会显示以下信息:

在这里插入图片描述

但有时,我们会发现自己爬不到任何数据,比如:

在这里插入图片描述

还没有爬到数据,spider就close了!这时有很多可能的原因,很有可能是因为网站本身对数据进行了加密或者有反爬虫技术,而不是我们的代码有问题。不要急,我们可以在命令行里一步步调试找到错误原因。具体操作步骤可以参见这篇博客:

https://blog.csdn.net/weixin_44841312/article/details/95670015


猜你喜欢

转载自blog.csdn.net/weixin_44765402/article/details/110392957