Scrapy框架学习 - 使用Twisted框架实现异步存储数据到MySQL数据库中

概述

以爬取豆瓣读书Top250排行榜为例。

关键是使用Twisted框架的adbapi,创建数据库连接池对象,然后使用这个数据库连接池对象进行数据库操作,
这样就实现了数据存储的异步方案。

核心代码如下:
1.使用Twisted中的adbapi获取数据库连接池对象。
参数“pymsql”为使用的数据库引擎名字,params与直接使用pymsql.connect(params)连接数据库时相同
self.dbpool=adbapi.ConnectionPool('pymysql',**params)
2.使用数据库连接池对象进行数据库操作,自动传递cursor对象到数据库操作方法的第一个参数,
query=self.dbpool.runInteraction(self.do_insert,item)
也可以设置出错时的回调方法,自动传递出错消息对象failure到错误处理方法的第一个参数
query.addErrback(self.on_error,spider)

代码

items.py

class DoubanbookItem(scrapy.Item):
    # 图书详情页链接
    link=scrapy.Field()
    # 图书名称
    title=scrapy.Field()
    # 作者,出版信息,价格等信息
    info=scrapy.Field()
    # 豆瓣评分
    rating=scrapy.Field()
    # 引论
    quote=scrapy.Field()

spider

# !/usr/bin/env python
# -*- coding:utf-8 -*-

import scrapy
from myscrapy.items import DoubanbookItem

class DoubanbookSpider(scrapy.Spider):
    """
    豆瓣读书Top250爬虫
        学习使用Twisted异步框架的功能,实现异步保存数据到MySQL数据库中
    """
    name = 'doubanbook'
    allowed_domains=['book.douban.com']

    def start_requests(self):
        base_url='https://book.douban.com/top250?start='
        offset=0
        start_urls=[base_url+str((offset+x)*25) for x in range(10)]
        for start_url in start_urls:
            yield scrapy.Request(url=start_url,callback=self.parse)

    def parse(self, response):
        tr_nodes=response.xpath('//div[@class="indent"]//tr')

        for tr_node in tr_nodes:
            link=tr_node.xpath('.//div[@class="pl2"]/a/@href').extract_first()
            title=tr_node.xpath('.//div[@class="pl2"]/a/text()').re(r'\w+')[0]
            info=tr_node.xpath('.//p[@class="pl"]/text()').extract_first()
            rating=tr_node.xpath('.//span[@class="rating_nums"]/text()').extract_first()
            quote=tr_node.xpath('.//span[@class="inq"]/text()').extract_first()

            item=DoubanbookItem()
            item['link']=link
            item['title']=title
            item['info']=info
            item['rating']=rating
            item['quote']=quote
            yield item

pipelines.py

import pymysql
import scrapy
from twisted.enterprise import adbapi

class DoubanbookPipeline(object):
    """
    豆瓣读书Top250 Item Pipeline
        create table doubanbook250(
            id int primary key auto_increment,
            link varchar(100) not null,
            title varchar(200) not null,
            info varchar(500) not null,
            rating varchar(10) not null,
            quote varchar(200) not null);
    """

    def __init__(self,host,user,password,db):
        params=dict(
            host = host,
            user = user,
            password = password,
            db = db,
            charset = 'utf8',  # 不能用utf-8
            cursorclass = pymysql.cursors.DictCursor
        )
        # 使用Twisted中的adbapi获取数据库连接池对象
        self.dbpool=adbapi.ConnectionPool('pymysql',**params)

    @classmethod
    def from_crawler(cls,crawler):
        # 获取settings文件中的配置
        host=crawler.settings.get('HOST')
        user=crawler.settings.get('USER')
        password=crawler.settings.get('PASSWORD')
        db=crawler.settings.get('DB')
        return cls(host,user,password,db)

    def process_item(self,item,spider):
        # 使用数据库连接池对象进行数据库操作,自动传递cursor对象到第一个参数
        query=self.dbpool.runInteraction(self.do_insert,item)
        # 设置出错时的回调方法,自动传递出错消息对象failure到第一个参数
        query.addErrback(self.on_error,spider)
        return item

    def do_insert(self,cursor,item):
        sql='insert into doubanbook250(link,title,info,rating,quote) values(%s,%s,%s,%s,%s)'
        args=(item['link'],item['title'],item['info'],item['rating'],item['quote'])
        cursor.execute(sql,args)

    def on_error(self,failure,spider):
        spider.logger.error(failure)

settings.py

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

BOT_NAME = 'myscrapy'

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

# scrapy.downloadermiddlewares.robotstxt.RobotsTxtMiddleware
# Obey robots.txt rules
ROBOTSTXT_OBEY = False

# 配置下载延时
DOWNLOAD_DELAY = 1

DOWNLOADER_MIDDLEWARES = {
    'myscrapy.middlewares.UserAgentDownloaderMiddleware': 99,
}

ITEM_PIPELINES = {
    'myscrapy.pipelines.DoubanbookPipeline': 300,
}

# MySQL数据库参数
HOST = 'localhost'
USER = 'root'
PASSWORD = '123456'
DB = 'mydb'

运行结果

Scrapy框架学习 - 使用Twisted框架实现异步存储数据到MySQL数据库中_第1张图片

你可能感兴趣的:(爬虫)