**豆瓣项目已完结!项目源码:
链接:https://pan.baidu.com/s/1DOnXwXZKiBcJbzHwDJuw5A
提取码:u8xi
**

1.昨天简单爬取了豆瓣Top250电影的一些信息。今天,咱又来尝试搞到每个电影的简介信息。顺便看看Scrapy shell和Scrapy选择器以及scrapy.spider。

(1)第一步:配对成功我们所想要的每个电影的简介信息:

1.First:观察网页可知,我们要想要获取到每个电影的简介信息。首先要获取到每个电影的包含它简介信息的url。

学习爬虫之Scrapy框架学习(3)---豆瓣top250电影完整版信息获取及如何存储到mysql数据库;Scrapy shell和Scrapy选择器;使用到日志的学习!_python

学习爬虫之Scrapy框架学习(3)---豆瓣top250电影完整版信息获取及如何存储到mysql数据库;Scrapy shell和Scrapy选择器;使用到日志的学习!_编程_02
学习爬虫之Scrapy框架学习(3)---豆瓣top250电影完整版信息获取及如何存储到mysql数据库;Scrapy shell和Scrapy选择器;使用到日志的学习!_编程语言_03
学习爬虫之Scrapy框架学习(3)---豆瓣top250电影完整版信息获取及如何存储到mysql数据库;Scrapy shell和Scrapy选择器;使用到日志的学习!_python_04
学习爬虫之Scrapy框架学习(3)---豆瓣top250电影完整版信息获取及如何存储到mysql数据库;Scrapy shell和Scrapy选择器;使用到日志的学习!_编程_05

Second:在爬虫文件中加入此成功的代码,并且,我们所获取到的是request请求,而Scrapy框架里一切请求都要交给引擎,所以我们要将此request请求yield返回给引擎,让引擎进行一系列处理。最后,引擎处理完之后,要将处理过后的数据再交给爬虫文件进行数据解析及获取,而这就需要我们在爬虫文件中定义一个专门解析与获取电影简介信息的函数(注意:这个函数一定要包含response参数用于接收引擎交给爬虫文件的数据)

#将下面代码加到爬虫文件中parse函数的循环的最下面:
                detail_url=node.xpath('./div/a/@href').extract()[0]
                yield scrapy.Request(detail_url,callback=self.get_detail)
#将下面函数加入爬虫文件:
    def get_detail(self,response):
        pass

Third:现在,我们就要使用我们自定义的函数get_detail()处理引擎处理过后交给我们的response了。这给咱的是个response,咱继续分析这个response的网页源码,使用xpath匹配到我们所需的电影的简介信息即可!学习爬虫之Scrapy框架学习(3)---豆瓣top250电影完整版信息获取及如何存储到mysql数据库;Scrapy shell和Scrapy选择器;使用到日志的学习!_编程语言_06学习爬虫之Scrapy框架学习(3)---豆瓣top250电影完整版信息获取及如何存储到mysql数据库;Scrapy shell和Scrapy选择器;使用到日志的学习!_python_07

学习爬虫之Scrapy框架学习(3)---豆瓣top250电影完整版信息获取及如何存储到mysql数据库;Scrapy shell和Scrapy选择器;使用到日志的学习!_编程语言_08将此代码加入到我们写的get_detail()函数里即可:

    def get_detail(self,response):
        #获取电影简介信息
        description=response.xpath('//div[@id="link-report"]/span/span[@property="v:summary"]/text()').extract()[0].strip()

注意:我们在进行测试的时候,发现有个电影的简介信息是个特例,它放的标签结构与众不同,所以咱改下爬虫文件中的get_detail()函数:

    def get_detail(self,response):
        #获取电影简介信息
        description=response.xpath('//div[@id="link-report"]//span[@property="v:summary"]/text()').extract()[0].strip()

学习爬虫之Scrapy框架学习(3)---豆瓣top250电影完整版信息获取及如何存储到mysql数据库;Scrapy shell和Scrapy选择器;使用到日志的学习!_Scrapy框架详解_09

(2)第二步:将每个电影的简介信息放在每个电影的信息里进行存储:

1.按咱习惯性的思路:步骤如下

(1)首先:在items.py文件中创建一个用于存储电影简介信息的字段

    description=scrapy.Field()

(2)settings.py文件中开启管道;并设置延时
(3)在爬虫文件中将电影简介信息对应到字段里,并将其返回给管道pipelines.py文件。

    def get_detail(self,response):
        #获取电影简介信息
        item=DoubanItem()
        description=response.xpath('//div[@id="link-report"]//span[@property="v:summary"]/text()').extract()[0].strip()
        item['description']=description
        yield item

咱设置爬取首页25个电影的信息,运行爬虫之后,观察我们所获取到的数据:
学习爬虫之Scrapy框架学习(3)---豆瓣top250电影完整版信息获取及如何存储到mysql数据库;Scrapy shell和Scrapy选择器;使用到日志的学习!_爬虫_10会发现,电影信息和其简介信息非但没有放在一起,而且更严重的是,由于scrapy框架采取的是异步方式,所以底下得到的这25个电影的简介信息也是毫无顺序的。这就很头疼了!

2.既然习惯性的那个思路不行,那这个Scrapy这个这么牛批的框架的设计者肯定也考虑到这种问题了,所以这里就引入了meta参数。解决方法如下:

**
注意:这个参数贼牛。那咱如何来理解这个参数的作用:
1.在爬虫文件将包含电影简介信息的url请求发送给引擎的同时,会把meta里的参数也携带着;
2.在引擎处理完这个url请求之后会将处理后的response返回给爬虫文件中我们指定的callback=self.get_detail函数里的response参数,并且同时会携带着这个meta参数。
牛皮之处可见一斑,这就不是变相的将电影基本信息数据和电影简介信息给拼接到了一起了!!!
**

#修改爬虫文件里的parse函数中对应的代码:
                yield scrapy.Request(detail_url,callback=self.get_detail,meta={"info":item})
                

修改爬虫文件中咱写的解析电影简介信息的函数get_detail()

    def get_detail(self,response):
        item=DoubanItem()
        #获取电影简介信息
        #1.meta会跟随response一块返回  2.可以通过response.meta接收   3.通过updata可以添加到新的item对象
        info = response.meta["info"]        #接收电影的基本信息
        item.update(info)                   #把电影基本信息的字段加进去
        
        #将电影简介信息加入相应的字段里
        description=response.xpath('//div[@id="link-report"]//span[@property="v:summary"]/text()').extract()[0].strip()
        item['description']=description
        yield item

会发现可以很完美的搞到我们所想要的数据:

学习爬虫之Scrapy框架学习(3)---豆瓣top250电影完整版信息获取及如何存储到mysql数据库;Scrapy shell和Scrapy选择器;使用到日志的学习!_编程_11

现在咱又不满足于只保存在本地txt文本了,咱来试试存储到数据库mysql里怎么搞呢?(首先,要准备好mysql数据库以及navicat数据库可视化管理工具)

(1)分析:如果要同时存储在本地txt文本里以及mysql数据库里,那就需要咱再新建一个管道,并开启这个管道( settings里 管道类名添加 ),最后,使用pymysql连接数据库。

学习爬虫之Scrapy框架学习(3)---豆瓣top250电影完整版信息获取及如何存储到mysql数据库;Scrapy shell和Scrapy选择器;使用到日志的学习!_python_12

2.新建管道正确代码:

import pymysql
class DoubanSqlPipeline(object):
    # 1.连接数据库
    def open_spider(self,spider):
        data_config=spider.settings["DATABASE_CONFIG"]
        if data_config["type"]=="mysql":
            self.conn=pymysql.connect(**data_config["config"])
            self.cursor=self.conn.cursor()

    def process_item(self,item,spider):
        dict(item)
        sql='insert into filminfo (filmname,starname,score,description) values(%s,%s,%s,%s)'
        self.cursor.execute(sql,
                                (
                                    item["film_name"],
                                    item["star_name"],
                                    item["score"],
                                    item["description"],
                                )
                            )
        self.conn.commit()
        return item
    def close_spider(self,spider):
        self.cursor.close()
        self.conn.close()

3.settings.py文件中对连接mysql数据库的配置:

DATABASE_CONFIG={
    "type":"mysql",
    "config":{
        "host":"localhost",
        "port":3306,
        "user":"root",
        "password":"123456",
        "db":"doubanfilm",
        "charset":"utf8"
    }
}

4.settings.py文件中打开储存到Mysql数据库的管道:

学习爬虫之Scrapy框架学习(3)---豆瓣top250电影完整版信息获取及如何存储到mysql数据库;Scrapy shell和Scrapy选择器;使用到日志的学习!_爬虫_13

5.navicat创库建表:

创库:

学习爬虫之Scrapy框架学习(3)---豆瓣top250电影完整版信息获取及如何存储到mysql数据库;Scrapy shell和Scrapy选择器;使用到日志的学习!_编程语言_14

学习爬虫之Scrapy框架学习(3)---豆瓣top250电影完整版信息获取及如何存储到mysql数据库;Scrapy shell和Scrapy选择器;使用到日志的学习!_Scrapy框架详解_15

学习爬虫之Scrapy框架学习(3)---豆瓣top250电影完整版信息获取及如何存储到mysql数据库;Scrapy shell和Scrapy选择器;使用到日志的学习!_编程_16

最后,运行爬虫即可。(注意:运行之前,一定要在Mysql里创建对应的数据库,表及字段)。运行之后navicat里效果:学习爬虫之Scrapy框架学习(3)---豆瓣top250电影完整版信息获取及如何存储到mysql数据库;Scrapy shell和Scrapy选择器;使用到日志的学习!_python_17

2.Scrapy shell的基操:

老是用到Scrapy shell,好奇心驱使着咱来瞅瞅它还能干啥子?
(1)什么是Scrapy shell?
用来调试Scrapy 项目代码的 命令行工具。
启动的时候预定义了Scrapy的一些对象
(2)它的作用是什么?
调试!!!

(1)设置shell:

Scrapy 的shell是基于运行环境中的python 解释器shell

本质上就是通过命令调用shell,并在启动的时候预定义需要使用的对象

scrapy允许通过在项目配置文件”scrapy.cfg”中进行配置来指定解释器shell

例如:
[settings]
shell = ipython

(2)启动shell:

启动Scrapy shell的命令语法格式如下:

scrapy shell [option] [url或者file]

url 就是你想要爬取的网址

注意:分析本地文件是一定要带上路径,scrapy shell默认当作url

(3)终端依此输入:

fetch(“https://movie.douban.com/top250”) 获取指定url的response对象

shelp() 这样是显示拿到数据之后的一些基操命令!

[s] Available Scrapy objects:
[s]   scrapy     scrapy module (contains scrapy.Request, scrapy.Selector, etc)		#scrapy模块
[s]   crawler    <scrapy.crawler.Crawler object at 0x0000023948A27A60>				#爬虫对象
[s]   item       {}		#item对象
[s]   request    <GET https://movie.douban.com/top250>			#请求对象
[s]   response   <200 https://movie.douban.com/top250>			#响应对象
[s]   settings   <scrapy.settings.Settings object at 0x0000023948A27250>			#配置文件
[s]   spider     <DbSpider 'db' at 0x23948efbf70> 								    #爬虫文件对象
[s] Useful shortcuts:#快捷键
[s]   fetch(url[, redirect=True]) Fetch URL and update local objects (by default, redirects are followed)
[s]   fetch(req)                  Fetch a scrapy.Request and update local objects   #获取url的response对象
[s]   shelp()           Shell help (print this help) 							    #显示基本命令
[s]   view(response)    View response in a browser								    #会将这个response页面以网页形式展示出来

3.Scrapy选择器

Scrapy提供基于lxml库的解析机制,它们被称为选择器。
因为,它们“选择”由XPath或CSS表达式指定的HTML文档的某部分。
Scarpy选择器的API非常小,且非常简单。

(1)构造selector选择器

Scrapy选择器是通过scrapy.Selector类,
通过传递文本或者TextResponse对象构造的实例。
(它会根据输入类型自动选择最佳解析规则
XML与HTML)

html_str="""
<div class="info">
                    <div class="hd">
                        <a href="https://movie.douban.com/subject/1292052/" class="">
                            <span class="title">肖申克的救赎</span>
                                    <span class="title">&nbsp;/&nbsp;The Shawshank Redemption</span>
                                <span class="other">&nbsp;/&nbsp;月黑高飞(港)  /  刺激1995(台)</span>
                        </a>


                            <span class="playable">[可播放]</span>
                    </div>
                    <div class="bd">
                        <p class="">
                            导演: 弗兰克·德拉邦特 Frank Darabont&nbsp;&nbsp;&nbsp;主演: 蒂姆·罗宾斯 Tim Robbins /...<br>
                            1994&nbsp;/&nbsp;美国&nbsp;/&nbsp;犯罪 剧情
                        </p>

                        
                        <div class="star">
                                <span class="rating5-t"></span>
                                <span class="rating_num" property="v:average">9.7</span>
                                <span property="v:best" content="10.0"></span>
                                <span>1983356人评价</span>
                        </div>

                            <p class="quote">
                                <span class="inq">希望让人自由。</span>
                            </p>
                    </div>
</div>
"""
#########################################第一部分:selector对象的构造
#(1)通过传递text文本构造一个selector对象
from scrapy.selector import Selector
sss=Selector(text=html_str)                #通过传递text文本构造一个selector对象

print("自动为我们补全:",sss.extract())            #注意:selector选择器会自动为我们补全,最外边加html标签和body标签

#下面两种效果一样,我们可以在selector对象上直接使用xpath进行匹配
print("使用文本构造selector对象的使用1:",sss.xpath('./body/div/div/a/span[1]/text()').extract()[0])
print("使用文本构造selector对象的使用2:",sss.xpath('./body/div/div/a/span[1]/text()').extract_first())




#(2)通过response构建selector对象
from scrapy.http import HtmlResponse
response=HtmlResponse(url="http://www.spider.com",body=html_str.encode())  #通过响应构建response对象

#以下共三种方法让我们可以使用selector对象上的xpath进行匹配。效果一样!
print("使用响应构造selector对象的使用1:",Selector(response=response).xpath('./body/div/div/a/span[1]/text()').extract()[0])
print("使用响应构造selector对象的使用2:",response.selector.xpath('./body/div/div/a/span[1]/text()').extract()[0])
print("使用响应构造selector对象的使用3:",response.xpath('./body/div/div/a/span[1]/text()').extract()[0])



######################################第二部分:使用选择器!!!
'''     
选择器提供2个方法来提取标签:
(1)xpath()   基于xpath的语法规则 
(2)css()     基于css选择器的语法规则

使用方法:(快捷方式)
response.xpath()
response.css()

它们返回的是选择器列表
提取文本:
selector.extract()       返回文本列表
selector.extract_first()或者selector.extract()[0] 返回第一个selector的文本,第一个方法没有返回None;但是第二个方法没有会报错!
'''
#1.使用css方法:
print("使用css方法:",response.css("a"))
#2.使用xpath方法:
print("使用xpath方法:",response.xpath('./body/div/div/a/span[1]/text()'))
#3.嵌套选择器的使用:            注意:一定要是selector对象才能混合使用!
print("嵌套选择器的使用:",response.css("a").xpath('./span[@class="title"]/text()').extract()[0])         #先使用css方法选择所有的a标签,再使用xpath匹配。嵌套选择

'''拓展:
Selector还有一个.re()方法使用正则表达式提取数据的方法。
它返回字符串。
它一般使用在xpath(),css()方法之后,用来过滤文本数据。
re_first()用来返回第一个匹配的字符串。
'''
print("结合使用re:",response.css("a").xpath('./span[@class="title"]/text()').re("的(..)"))         #结合re使用
print("结合使用re的一个快捷方法:",response.css("a").xpath('./span[@class="title"]/text()').re_first("的(..)"))   #从列表中取出第一个,如果没有返回None而不会报错;但是如果用索引取值的话,没有获取到就会报错!

学习爬虫之Scrapy框架学习(3)---豆瓣top250电影完整版信息获取及如何存储到mysql数据库;Scrapy shell和Scrapy选择器;使用到日志的学习!_编程_18

学习爬虫之Scrapy框架学习(3)---豆瓣top250电影完整版信息获取及如何存储到mysql数据库;Scrapy shell和Scrapy选择器;使用到日志的学习!_编程语言_19

4.Scrapy.spider类

学习爬虫之Scrapy框架学习(3)---豆瓣top250电影完整版信息获取及如何存储到mysql数据库;Scrapy shell和Scrapy选择器;使用到日志的学习!_Scrapy框架详解_20

(1)spider的名称 (name)

一个字符串,用于定义此蜘蛛的名称。蜘蛛名称是Scrapy如何定位(并实例化)蜘蛛,因此它必须是唯一的。这是最重要的蜘蛛属性,它是必需的。

(2)起始urls (start_urls)

蜘蛛将开始爬取的URL列表。因此,下载的第一页将是此处列出的页面。后续Request将从起始URL中包含的数据连续生成。

(3)自定义设置 (customer_settings)

运行此蜘蛛时将覆盖项目范围的设置。必须将其定义为类属性,因为在实例化之前更新了设置。会覆盖settings.py文件里的设置!

学习爬虫之Scrapy框架学习(3)---豆瓣top250电影完整版信息获取及如何存储到mysql数据库;Scrapy shell和Scrapy选择器;使用到日志的学习!_python_21

(4)日志器 (logger)

使用Spider创建的Python日志器。您可以使用它来发送日志消息。
源码:
学习爬虫之Scrapy框架学习(3)---豆瓣top250电影完整版信息获取及如何存储到mysql数据库;Scrapy shell和Scrapy选择器;使用到日志的学习!_编程语言_22

(1)第一种使用方法:Scrapy logger 在每个Spider实例中提供了一个可以访问和使用的实例(直接在爬虫文件中使用!)

学习爬虫之Scrapy框架学习(3)---豆瓣top250电影完整版信息获取及如何存储到mysql数据库;Scrapy shell和Scrapy选择器;使用到日志的学习!_爬虫_23

在本项目中使用:
学习爬虫之Scrapy框架学习(3)---豆瓣top250电影完整版信息获取及如何存储到mysql数据库;Scrapy shell和Scrapy选择器;使用到日志的学习!_爬虫_24

(2)第二种使用方法:(在其他组件中使用!)

也可以通过python的logging来记录。比如:logging.warning(‘This is a warning!’)
但是为了后期维护方面,我们可以创建不同的记录器来封装消息。
并且使用组件或函数的名称进行命名

(此方法在CrawlSpider的使用时进行了使用)
学习爬虫之Scrapy框架学习(3)---豆瓣top250电影完整版信息获取及如何存储到mysql数据库;Scrapy shell和Scrapy选择器;使用到日志的学习!_Scrapy框架详解_25

(3)第三种使用方法:(在settings.py配置文件中进行配置!)

##################################日志的使用:
LOG_FILE='db.log'           #日志写入到文件
LOG_ENABLED=False           #表示日志是否输出到控制台。False为不输出;True为输出。
LOG_ENCODING="utf-8"        #日志编码。
LOG_LEVEL="ERROR"           #如果写INFO,只有大于等于该等级的才会写入日志。

'2020-04-25 10:57:52 [scrapy.utils.log] INFO: Versions: lxml 4.5.0.0, libxml2 2.9.5, cssselect 1.1.0, parsel 1.5.2, w3lib 1.21.0, Twisted 20.3.0, Python 3.8.2 (tags/v3.8.2:7b3ab59, Feb 25 2020, 23:03:10) [MSC v.1916 64 bit (AMD64)], pyOpenSSL 19.1.0 (OpenSSL 1.1.1f  31 Mar 2020), cryptography 2.9, Platform Windows-10-10.0.18362-SP0'
#             时间    模块/组件名字  日志级别     日志信息
LOG_FORMAT='%(asctime)s [%(name)s] %(levelname)s: %(message)s'
LOG_DATEFORMAT='%Y-%m-%d %H:%M:%S'

LOG_STDOUT=False
LOG_SHORT_NAMES=False

'''下面这些设置可用于配置日志记录:

LOG_FILE		日志输出文件,如果为None,就打印在控制台
LOG_ENABLED	    是否启用日志,默认True
LOG_ENCODING   	日志编码,默认utf-8
LOG_LEVEL	    日志等级,默认debug。    DEBUG(调试信息)<INFO(一般信息)<WARNING(警告)<ERROR(一般错误)<CRITICAL(严重错误)
LOG_FORMAT	    日志格式
LOG_DATEFORMAT	日志日期格式
LOG_STDOUT	    日志标准输出,默认False,如果True所有标准输出(比如:print)都将写入日志中
LOG_SHORT_NAMES 短日志名,默认为False,如果True将不输出组件名

项目中一般设置:
LOG_FILE = 'logfile_name'
LOG_LEVEL = 'INFO'

'''

效果:

学习爬虫之Scrapy框架学习(3)---豆瓣top250电影完整版信息获取及如何存储到mysql数据库;Scrapy shell和Scrapy选择器;使用到日志的学习!_编程_26

(5)拓展看看一些源码:

1.创建spider的类方法 (from_crawler)

这是Scrapy用于创建spider的类方法。一般不用覆盖。
学习爬虫之Scrapy框架学习(3)---豆瓣top250电影完整版信息获取及如何存储到mysql数据库;Scrapy shell和Scrapy选择器;使用到日志的学习!_python_27

2.开始请求 (start_requests())

此方法必须返回一个iterable,其中包含第一个要爬网的请求。它只会被调用一次
学习爬虫之Scrapy框架学习(3)---豆瓣top250电影完整版信息获取及如何存储到mysql数据库;Scrapy shell和Scrapy选择器;使用到日志的学习!_Scrapy框架详解_28

3.默认回调函数 (parse(response))

这是Scrapy在其请求未指定回调时处理下载的响应时使用的默认回调。
学习爬虫之Scrapy框架学习(3)---豆瓣top250电影完整版信息获取及如何存储到mysql数据库;Scrapy shell和Scrapy选择器;使用到日志的学习!_编程_29

4.关闭spider

spider关闭时调用。
学习爬虫之Scrapy框架学习(3)---豆瓣top250电影完整版信息获取及如何存储到mysql数据库;Scrapy shell和Scrapy选择器;使用到日志的学习!_爬虫_30