猫哥教你写爬虫 047--scrapy框架

以前我们写爬虫,要导入和操作不同的模块,比如requests模块、gevent库、pymysql模块等。而在Scrapy里,你不需要这么做,因为很多爬虫需要涉及的功能,比如麻烦的异步,在Scrapy框架都自动实现
我们之前编写爬虫的方式,相当于在一个个地在拼零件,拼成一辆能跑的车。而Scrapy框架则是已经造好的、现成的车,我们只要踩下它的油门,它就能跑起来。这样便节省了我们开发项目的时间

Scrapy的结构

Scheduler(调度器)部门主要负责处理引擎发送过来的requests对象(即网页请求的相关信息集合,包括params,data,cookies,request headers…等),会把请求的url以有序的方式排列成队,并等待引擎来提取(功能上类似于gevent库的queue模块)。
Downloader(下载器)部门则是负责处理引擎发送过来的requests,进行网页爬取,并将返回的response(爬取到的内容)交给引擎。它对应的是爬虫流程【获取数据】这一步。
Spiders(爬虫)部门是公司的核心业务部门,主要任务是创建requests对象和接受引擎发送过来的response(Downloader部门爬取到的内容),从中解析并提取出有用的数据。它对应的是爬虫流程【解析数据】和【提取数据】这两步。
Item Pipeline(数据管道)部门则是公司的数据部门,只负责存储和处理Spiders部门提取到的有用数据。这个对应的是爬虫流程【存储数据】这一步。
Downloader Middlewares(下载中间件)的工作相当于下载器部门的秘书,比如会提前对引擎大boss发送的诸多requests做出处理。
Spider Middlewares(爬虫中间件)的工作则相当于爬虫部门的秘书,比如会提前接收并处理引擎大boss发送来的response,过滤掉一些重复无用的东西。

scrapy 工作原理

在Scrapy爬虫公司里,每个部门都各司其职,形成了很高效的运行流程

Scrapy中的程序全部都是异步模式,所有的请求或返回的响应都由引擎自动分配去处理

Scrapy的用法(豆瓣读书top250)

book.douban.com/top250

分析分页...

分析元素...

我们只要取出元素下元素的title属性的值、

元素、元素,就能得到书名、出版信息和评分的数据。

代码实现——创建项目

安装scrapy, pip install scrapy

解决方案1: 安装vc++运行库集合
pan.baidu.com/s/16jVqbrHA… u2v6

方案2: 直接下载whl库进行安装,简单, 最近需要, 不知道以后怎样...

方案3: 安装vc++2015, 对应14版本,试了,不管用, 你就别试了...

创建爬虫项目
跳转到你想创建爬虫项目的路径

创建爬虫项目

项目结构

Scrapy项目里每个文件都有特定的功能,settings.py 是scrapy里的各种设置。items.py是用来定义数据的,pipelines.py是用来处理数据的,它们对应的就是Scrapy的结构中的Item Pipeline(数据管道)middlewares.py是中间件

代码实现——编辑爬虫

如前所述,spiders是放置爬虫的目录。我们可以在spiders这个文件夹里创建爬虫文件。我们来把这个文件,命名为top250。后面的大部分代码都需要在这个top250.py文件里编写。

E:\helloSpider\douban\douban\spiders\top250.py
import scrapy
import bs4
# 定义一个爬虫类DoubanSpider。就像我刚刚讲过的那样,DoubanSpider类继承自scrapy.Spider类。
class DoubanSpider(scrapy.Spider):
    # name是定义爬虫的名字,这个名字是爬虫的唯一标识。name = 'douban'意思是定义爬虫的名字为douban。等会我们启动爬虫的时候,要用到这个名字。
    name = 'douban'
    # allowed_domains是定义允许爬虫爬取的网址域名(不需要加https://)。如果网址的域名不在这个列表里,就会被过滤掉。
    allowed_domains = ['book.douban.com']
    # start_urls是定义起始网址,就是爬虫从哪个网址开始抓取。在此,allowed_domains的设定对start_urls里的网址不会有影响。
    start_urls = ['https://book.douban.com/top250?start=0']
    # parse是Scrapy里默认处理response的一个方法
    def parse(self,response):
        print(response.text)
复制代码
之前分析过页面规律

十页变一页...

修改代码...
import scrapy
import bs4
# 定义一个爬虫类DoubanSpider。就像我刚刚讲过的那样,DoubanSpider类继承自scrapy.Spider类。
class DoubanSpider(scrapy.Spider):
    # name是定义爬虫的名字,这个名字是爬虫的唯一标识。name = 'douban'意思是定义爬虫的名字为douban。等会我们启动爬虫的时候,要用到这个名字。
    name = 'douban'
    # allowed_domains是定义允许爬虫爬取的网址域名(不需要加https://)。如果网址的域名不在这个列表里,就会被过滤掉。
    allowed_domains = ['book.douban.com']
    # start_urls是定义起始网址,就是爬虫从哪个网址开始抓取。在此,allowed_domains的设定对start_urls里的网址不会有影响。
    start_urls = []
    for x in range(3):
        url = 'https://book.douban.com/top250?start='+str(x*25)
        start_urls.append(url)
    # parse是Scrapy里默认处理response的一个方法
    def parse(self,response):
        print(response.text)
复制代码

提取元素....
书名是元素下元素的title属性的值;出版信息在

元素里;评分在元素里。

import scrapy
import bs4
from ..items import DoubanItem
# 定义一个爬虫类DoubanSpider。就像我刚刚讲过的那样,DoubanSpider类继承自scrapy.Spider类。
class DoubanSpider(scrapy.Spider):
    # name是定义爬虫的名字,这个名字是爬虫的唯一标识。name = 'douban'意思是定义爬虫的名字为douban。等会我们启动爬虫的时候,要用到这个名字。
    name = 'douban'
    # allowed_domains是定义允许爬虫爬取的网址域名(不需要加https://)。如果网址的域名不在这个列表里,就会被过滤掉。
    allowed_domains = ['book.douban.com']
    # start_urls是定义起始网址,就是爬虫从哪个网址开始抓取。在此,allowed_domains的设定对start_urls里的网址不会有影响。
    start_urls = []
    for x in range(3):
        url = 'https://book.douban.com/top250?start='+str(x*25)
        start_urls.append(url)
    # parse是Scrapy里默认处理response的一个方法
    def parse(self, response):
        bs = bs4.BeautifulSoup(response.text, 'html.parser')
        datas = bs.find_all('tr', class_='item')
        for data in datas:
            title = data.find_all('a')[1]['title']
            publish = data.find('p', class_="pl").text
            score = data.find('span', class_="rating_nums").text
            print([title, publish, score])
复制代码

代码实现——定义数据

在scrapy中,我们会专门定义一个用于记录数据的类。
我们会实例化一个对象,利用这个对象来记录数据。
每一次,当数据完成记录,它会离开spiders,来到Scrapy Engine(引擎),引擎将它送入Item Pipeline(数据管道)处理。
定义这个类的py文件,正是items.py
如何在items.py里定义这些数据。代码如下:
import scrapy
class DoubanItem(scrapy.Item):
    # 让数据能以类似字典的形式记录
    title = scrapy.Field()
    publish = scrapy.Field()
    score = scrapy.Field()
复制代码
修改douban250.py
import scrapy
import bs4
from ..items import DoubanItem
# 定义一个爬虫类DoubanSpider。就像我刚刚讲过的那样,DoubanSpider类继承自scrapy.Spider类。
class DoubanSpider(scrapy.Spider):
    # name是定义爬虫的名字,这个名字是爬虫的唯一标识。name = 'douban'意思是定义爬虫的名字为douban。等会我们启动爬虫的时候,要用到这个名字。
    name = 'douban'
    # allowed_domains是定义允许爬虫爬取的网址域名(不需要加https://)。如果网址的域名不在这个列表里,就会被过滤掉。
    allowed_domains = ['book.douban.com']
    # start_urls是定义起始网址,就是爬虫从哪个网址开始抓取。在此,allowed_domains的设定对start_urls里的网址不会有影响。
    start_urls = []
    for x in range(3):
        url = 'https://book.douban.com/top250?start='+str(x*25)
        start_urls.append(url)
    # parse是Scrapy里默认处理response的一个方法
    def parse(self, response):
        bs = bs4.BeautifulSoup(response.text, 'html.parser')
        datas = bs.find_all('tr', class_='item')
        for data in datas:
            item = DoubanItem()
            item['title'] = data.find_all('a')[1]['title']
            item['publish'] = data.find('p', class_="pl").text
            item['score'] = data.find('span', class_="rating_nums").text
            print(item)
            yield item  # 类似于return, 但是不会结束函数
复制代码

代码实操——设置

我们需要修改请求头...

ROBOTSTXT_OBEY=True改成ROBOTSTXT_OBEY=False,就是把遵守robots协议换成无需遵从robots协议,这样Scrapy就能不受限制地运行。

代码实操——运行
方法一: scrapy crawl douban(douban是我们爬虫的名字)
E:\helloSpider\douban> scrapy crawl douban
如果遇到...No module named win32api...
pip install pywin32

方法二: main.py

在最外层的大文件夹里新建一个main.py文件(与scrapy.cfg同级)
# 导入cmdline模块,可以实现控制终端命令行
from scrapy import cmdline
# 执行命令 "scrapy crawl douban"
cmdline.execute(['scrapy', 'crawl', 'douban'])
复制代码

了教学方便理解,先写了爬虫,再定义数据。但是,在实际项目实战中,常常顺序却是相反的——先定义数据,再写爬虫。所以,流程图应如下:

细心的你可能会发现,这一关的内容没有涉及到存储数据的步骤。

复习

存储到mysql

存储数据需要修改pipelines.py文件, 不过我们需要先建立一个数据库
drop database if exists douban;
create database douban character set utf8;
use douban;
create table book(
	id int primary key auto_increment,
    title varchar(255) not null,
    publish varchar(255) not null,
    score decimal(2,1) not null
);
复制代码
mysql> desc book;
+---------+--------------+------+-----+---------+----------------+
| Field   | Type         | Null | Key | Default | Extra          |
+---------+--------------+------+-----+---------+----------------+
| id      | int(11)      | NO   | PRI | NULL    | auto_increment |
| title   | varchar(255) | NO   |     | NULL    |                |
| publish | varchar(255) | NO   |     | NULL    |                |
| score   | decimal(2,1) | NO   |     | NULL    |                |
+---------+--------------+------+-----+---------+----------------+
4 rows in set (0.01 sec)
复制代码
有了数据库, 我们开始写E:\helloSpider\douban\douban\pipelines.py
# -*- coding: utf-8 -*-
import pymysql
class DoubanPipeline(object):
    def __init__(self):
        # 创建数据库连接
        self.connection = pymysql.connect(
            host='localhost',
            port=3306,
            user='root',
            password='root',
            db='douban',
            charset='utf8'
        )
        self.cursor = self.connection.cursor()
    def process_item(self, item, third):
        # 拼接sql语句
        sql = "insert into book(title,publish,score) values({},{},{})".format(
            repr(item['title']), repr(item['publish']), item['score'])
        # 执行sql语句
        self.cursor.execute(sql)
        self.connection.commit()
复制代码
还有设置文件E:\helloSpider\douban\douban\settings.py

看一下最终效果...

快速跳转:

猫哥教你写爬虫 000--开篇.md
猫哥教你写爬虫 001--print()函数和变量.md
猫哥教你写爬虫 002--作业-打印皮卡丘.md
猫哥教你写爬虫 003--数据类型转换.md
猫哥教你写爬虫 004--数据类型转换-小练习.md
猫哥教你写爬虫 005--数据类型转换-小作业.md
猫哥教你写爬虫 006--条件判断和条件嵌套.md
猫哥教你写爬虫 007--条件判断和条件嵌套-小作业.md
猫哥教你写爬虫 008--input()函数.md
猫哥教你写爬虫 009--input()函数-人工智能小爱同学.md
猫哥教你写爬虫 010--列表,字典,循环.md
猫哥教你写爬虫 011--列表,字典,循环-小作业.md
猫哥教你写爬虫 012--布尔值和四种语句.md
猫哥教你写爬虫 013--布尔值和四种语句-小作业.md
猫哥教你写爬虫 014--pk小游戏.md
猫哥教你写爬虫 015--pk小游戏(全新改版).md
猫哥教你写爬虫 016--函数.md
猫哥教你写爬虫 017--函数-小作业.md
猫哥教你写爬虫 018--debug.md
猫哥教你写爬虫 019--debug-作业.md
猫哥教你写爬虫 020--类与对象(上).md
猫哥教你写爬虫 021--类与对象(上)-作业.md
猫哥教你写爬虫 022--类与对象(下).md
猫哥教你写爬虫 023--类与对象(下)-作业.md
猫哥教你写爬虫 024--编码&&解码.md
猫哥教你写爬虫 025--编码&&解码-小作业.md
猫哥教你写爬虫 026--模块.md
猫哥教你写爬虫 027--模块介绍.md
猫哥教你写爬虫 028--模块介绍-小作业-广告牌.md
猫哥教你写爬虫 029--爬虫初探-requests.md
猫哥教你写爬虫 030--爬虫初探-requests-作业.md
猫哥教你写爬虫 031--爬虫基础-html.md
猫哥教你写爬虫 032--爬虫初体验-BeautifulSoup.md
猫哥教你写爬虫 033--爬虫初体验-BeautifulSoup-作业.md
猫哥教你写爬虫 034--爬虫-BeautifulSoup实践.md
猫哥教你写爬虫 035--爬虫-BeautifulSoup实践-作业-电影top250.md
猫哥教你写爬虫 036--爬虫-BeautifulSoup实践-作业-电影top250-作业解析.md
猫哥教你写爬虫 037--爬虫-宝宝要听歌.md
猫哥教你写爬虫 038--带参数请求.md
猫哥教你写爬虫 039--存储数据.md
猫哥教你写爬虫 040--存储数据-作业.md
猫哥教你写爬虫 041--模拟登录-cookie.md
猫哥教你写爬虫 042--session的用法.md
猫哥教你写爬虫 043--模拟浏览器.md
猫哥教你写爬虫 044--模拟浏览器-作业.md
猫哥教你写爬虫 045--协程.md
猫哥教你写爬虫 046--协程-实践-吃什么不会胖.md
猫哥教你写爬虫 047--scrapy框架.md
猫哥教你写爬虫 048--爬虫和反爬虫.md
猫哥教你写爬虫 049--完结撒花.md

转载于:https://juejin.im/post/5cfc4ade51882541b24c3f23

你可能感兴趣的:(爬虫,python,数据库)