爬虫进阶之人见人爱的Scrapy框架--Scrapy入门

不要重复造轮子,这是学习Python以来听得最多的一句话,无非就是叫我们要灵活运用现有的库,毕竟Python的一大特点就是拥有功能强大强大而种类丰富的库。那么在爬虫领域要灵活使用哪个轮子呢?--当然是目前最火的爬虫框架Scrapy。笔者通过慕课网免费课程《Python最火爬虫框架Scrapy入门与实践》+书籍《精通Scrapy网络爬虫》+ 度娘+CSDN完成自学,其中遇到诸多困难(要么太深入没看懂,要么太浅出没收获)。以此文将个中曲折记录下来(其实是怕自己以后忘代码)。
其中涉及到Linux的基本操作(cmd的命令行?),完全不懂,现学现卖。
其中还讲述了Scrapy框架的组成结构和组件的描述,这玩意只可意会不可言传(其实就是没看懂),我复制粘贴在此,看看就好。
---------------------------------复制粘贴分割线----------------------------------------


1.PNG

Engine:引擎负责控制系统所有组件之间的数据流,并在发生某些操作时触发事件。
Scheduler:调度程序接收来自引擎的请求,并将它们排入队列,并在之后,当Engine需要的时候,将requests发送给engine。
Downloader:下载器负责提取网页并将它们馈送到引擎,然后引擎将其发送给spider。
Spiders:蜘蛛是Scrapy用户编写的自定义类,用于解析响应并从中提取item项目(也称为抓取的项目)或追加的其他请求。详情已经在上一篇文章中介绍过了,这里就不重复了。
Item Pipeline:Item Pipeline负责处理被蜘蛛提取的item, 典型的任务包括清理,验证和持久性(如将项目存储在数据库中)。 这一部分在上一篇文章中也详细的介绍过了。
Downloader middlewares:下载器中间件是位于引擎和下载器之间的特定的钩子,当它们从引擎传递到下载器时处理请求,以及从下载器传递到引擎的响应。使用下载中间件可以达成如下的目的:
•在将请求发送到下载器之前处理请求(即在Scrapy将请求发送到网站之前)。在传递给蜘蛛之前改变接收到的响应;在传递给蜘蛛之前改变接收到的响应;
•发送新的请求,而不是将接收到的响应传递给蜘蛛;
•发送新的请求,而不是将接收到的响应传递给蜘蛛;向蜘蛛传递响应而不需要获取网页;

---------------------------------复制粘贴分割线----------------------------------------

话不多说,直接上我的分解步骤。甭管那么多理论框架,能做出来好爬虫,就是一个好的爬虫工程师。

  1. Scrapy的安装:
    打开命令行(今后统一简写cmd)
    输入:pip3 install scrapy(安装库的常用命令,之前requests库,美丽的汤也是如此安装,后面用到的lxml亦同)
    cmd: pip install scrapy

安装完成后可以通过 cmd:scrapy 查看详情,确认是否安装成功。如下:

1.PNG

同时视频要求安装 MangoDB(一个数据库),这个真的是要了我的老命了,光是查找下载link和安装教程就花了我一个晚上。MangoDB的故事我们以后在慢慢说,先把Scrapy给理顺了。

  1. 创建Scrapy项目
    反复观看视频,学了一个创建Scrapy project的快捷方式,非常好用。
    cmd:scrapy startproject name 其中name为自定义的项目名称。
    通过这个命令可以直接把整个project和其下所有的py文件/Class/函数全部创建好,意识就是说默认的模板已经有了,我们直接往里面填内容就好了。
    原来这就是先辈们给我们造好的轮子。比心心!
    创建好后,在Pycharm里打开整个project,可以发现如下文件:


    1.PNG

其中:1.项目名称为douban,是因为视频里实战项目是爬取豆瓣Top250的电影信息。我觉得这个实战确实挺250的。
2.spiders文件夹下的douban_spider.py文件原本没有,是我后面创建的。
3.douban文件夹下的main.py也没有,后面才创建。
到此,一个Scrapy项目便创建好了。

  1. 创建spider.py文件(实战:爬取豆瓣电影Top250):
    cmd:cd spiderfolderpath 其中spiderfolderpath为刚刚那个spider文件的所在路径。 不会进入路径的请度娘(我也是度娘出来的)。
    cmd(spiderfolderpathpath):scrapy genspider name_spider movie.douban.com
    其中:1.scrapy genspider ...... ...... 为固定命令
    2.name_spider 是文件名,即为我的douban_spider
    3.movie.douban.com 是爬虫允许的范围(作用域?)
    一个新的spider.py文件就老老实实的出现在spider文件夹下了。

  2. 设置spider.py文件,并检查response
    这个时候spider文件就要自己填写和补充了,它的顺序大致如下:
    4.1 先把该import的全部import进来再说

import scrapy
from douban.items import DoubanItem     # 从item.py中导入类

4.1 继承scrapy.Spider这个类:其实就是啥都不用做,因为它自己就继承好了
4.2 取名/设置允许域名/设置初始URL/设置解析函数prase。如下:

class DoubanSpiderSpider(scrapy.Spider):
    # 爬虫名称,该名称和项目名称不能重复!!!!!!
    name = 'douban_spider'

    # 允许的域名
    allowed_domains = ['movie.douban.com']

    # 初始URL,下一步经过Engine传到下载器
    start_urls = ['http://movie.douban.com/top250']

    def parse(self, response):              # 解析工具

        # print(response.text)       # 用于test response

其中:1. 爬虫名称和项目名称不能相同(我也不知道这是Why)。
2. 用print(response.text) 检查一下response是否OK
4.3 建立主函数文件main,方便实时查看反馈。
4.3.1 在主文件夹(douban)下新建main.py
4.3.2 敲入代码如下:其原理是将cmd运行的内容带入py,方便实时查看调试

from scrapy import cmdline
cmdline.execute('scrapy crawl douban_spider'. split())

直接复制粘贴吧,固定格式。
然后就OK了,后面调试的时候直接运行main就好了。
这个时候spider.py还没有设置完,我们要先停下手中的工作,完成sttting和items文件的设定。

  1. 设置setting文件
    setting文件当中有几个参数需要检查和设定。需要检查的是BOT_NAME,SPIDER_MODULES和NEWSPIDER_MODULE,确保它们的名字是正确的。
    在初级阶段中,需要设置的参数有USER_AGENT,ROBOTSTXT_OBEY和DOWNLOAD_DELAY ,分别设置如下(这里USER_AGENT是通过对网页发送请求和获取的):
BOT_NAME = 'douban'

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


# Crawl responsibly by identifying yourself (and your website) on the user-agent
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko'

# Obey robots.txt rules
ROBOTSTXT_OBEY = True

# Configure maximum concurrent requests performed by Scrapy (default: 16)
#CONCURRENT_REQUESTS = 32

# Configure a delay for requests for the same website (default: 0)
# See https://docs.scrapy.org/en/latest/topics/settings.html#download-delay
# See also autothrottle settings and docs
DOWNLOAD_DELAY = 0.5

Settings其实是一个深藏不露,非常厉害的文件,可以设置很多开关,包括各种中间件的设置(涉及反反爬虫等高级内容),cookies的设置,请求头(Headers)和Pipeline的设置等等,这些东西我现在也整不明白,争取在后面一点一点整理出来。

  1. Items文件的设置
    Items文件顾名思义,掌管着我们要爬取的内容的项目。以豆瓣电影Top250为例,我们要分别爬取它们的序号,电影名称,电影介绍,电影星级,电影评论和电影描述等等,这些都要在items进行设定。
    设定很简单,将以上全部定义为变量,调用scrapy库中Field()这个子类。用人话描述,就是固定格式,照搬就行。如下:
Class DoubanItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    # 序号
    serial_number = scrapy.Field()              # 固定格式,调用Field这个子类
    # 电影名称
    mobile_name = scrapy.Field()                 # 需要多少个数据就写多少次
    # 电影介绍
    introduction = scrapy.Field()
    # 电影星级
    star = scrapy.Field()
    # 电影评论
    evaluate = scrapy.Field()
    # 电影描述
    describe = scrapy.Field()
    pass
  1. 完成spider.dy文件中解析工具的设定
    这一步是最关键也是最需要手动操作的步骤,设定解析工具parse函数。
    通过网络节点获取工具找到具有电影信息的节点(movie_list)。我现在掌握的获取节点的方法有三种,分别是:
    美丽汤大法:requests + BeautifulSoup
    E树大法:lxml + xpath + etree
    Scrapy大法:Scrapy库中,reponse + xpath
    三种方法各有特色,这里主要是使用Scrapy大法。
    def parse(self, response):              # 解析工具

        # print(response.text)       # 用于test response
        # 使用xpath来确定节点(类似美丽的汤)
        # 注意xpath的语言,先确定class=article的div标签,再确定其下的class=grid_view的ol子标签,再其下的所有li标签
        # 因为多次用到引号,因此注意最外层"",内层''
        # //代表直接定位到后辈所有的标签,/代表标定位到子标签
        movie_list = response.xpath("//div[@class='article']/ol[@class='grid_view']/li")
        for i in movie_list:
            # print(i)
            douban_item = DoubanItem()
            # 注意起始位置必须加. ,表明在i这个path的根目录下进行节点定位
            # /text()表示取出子节点下的文字信息    get()/extract_first()表明在URL的字符串中选取我们有用的信息(第一个字符)
            douban_item['serial_number'] = i.xpath(".//em[@class = '']/text()").get()
            douban_item['mobile_name'] = i.xpath(".//span[@class = 'title']/text()").get()
            # 由于introduction存在大量的空格和空行,因此需要重新编辑格式
            content = i.xpath(".//p[@class = '']/text()").getall()                  # 使用getall()抓取所有数据
            for i_content in content:
                # 通过split分段空格,通过join函数连接字符串将其合并成一个字符串
                content_s = "".join(i_content.split())
                douban_item['introduction'] = content_s
            douban_item['star'] = i.xpath(".//span[@class = 'rating_num']/text()").get()
            douban_item['evaluate'] = i.xpath(".//div[@class = 'star']/span[4]/text()").get()     # div标签下的第4个span
            douban_item['describe'] = i.xpath(".//span[@class = 'inq']/text()").get()
            yield douban_item                                              # 把数据传入到pipeline中去

此章节涉及到xpath的语法规则和get()/getall()/extract_first()/extract()函数,后面再慢慢消化。

  1. 获取下一页的URL
    在完成当前页面的信息爬取之后,要准备获取下一页的URL,并设置起始/结束位置。
next_url = response.xpath("//span[@class = 'next']/link/@href").getall()   # 注意这里是get all,要抓取所有的link信息
        if next_url:                                                # 判断下一页是否存在,存在则返回页面URL
            next_url = next_url[0]
            # callback为回调函数//固定格式
            yield scrapy.Request("http://movie.douban.com/top250" + next_url, callback=self.parse)

到此,整个信息抓取部分就完成了。

  1. 保存文件
    数据抓取后当然是要输出并保存入文件了。官方教程是在cmd命令中设置,然而物品是个怕麻烦的人,便自学网上教程在pipeline中将其设了,设置如下(pupeline.dy文件中):
import json
import csv

class DoubanPipeline(object):

    def open_spider(self, spider):
        self.file = open('Douban.json', 'w')

    def process_item(self, item, spider):
        # 数据处理的主要方法,在这里面定义对数据的操作
        # 将item强转成字典
        dict_data = dict(item)
        # 将字典转换成json字符串
        str_data = json.dumps(dict_data, ensure_ascii=False) + ',\n'
        # 写入文件
        self.file.write(str_data)

        return item

    # 在爬虫停止的时候清理一些事情
    def close_spider(self, spider):
        self.file.close()

不要忘了在settings中启用pipeline:

# 打开douban.pipeline开关
# Configure item pipelines
# See https://docs.scrapy.org/en/latest/topics/item-pipeline.html
ITEM_PIPELINES = {
   'douban.pipelines.DoubanPipeline': 300,
}

到此,整个Scrapy框架的入门操作就这么多了,零零碎碎花了一个多星期的时间进行整理。

2019年10月30日 于杭州 云栖小镇

你可能感兴趣的:(爬虫进阶之人见人爱的Scrapy框架--Scrapy入门)