Scrapy

作者: 岸与海 | 来源:发表于2019-01-05 15:39 被阅读0次

scrapy 框架

  • Scrapy是用纯Python实现一个为了爬取网站数据、提取结构性数据而编写的应用框架,用途非常广泛。

  • 框架的力量,用户只需要定制开发几个模块就可以轻松的实现一个爬虫,用来抓取网页内容以及各种图片,非常之方便。

  • Scrapy 使用了 Twisted['twɪstɪd] 异步网络框架来处理网络通讯,可以加快我们的下载速度,不用自己去实现异步框架,并且包含了各种中间件接口,可以灵活的完成各种需求。

Scrapy架构图

scrapy.PNG
  • Scrapy Engine(引擎): 负责Spider、ItemPipeline、Downloader、Scheduler中间的通讯,信号、数据传递等。

  • Scheduler(调度器): 它负责接受引擎发送过来的Request请求,并按照一定的方式进行整理排列,入队,当引擎需要时,交还给引擎。

  • Downloader(下载器):负责下载Scrapy Engine(引擎)发送的所有Requests请求,并将其获取到的Responses交还给Scrapy Engine(引擎),由引擎交给Spider来处理,

  • Spider(爬虫):它负责处理所有Responses,从中分析提取数据,获取Item字段需要的数据,并将需要跟进的URL提交给引擎,再次进入Scheduler(调度器),

  • Item Pipeline(管道):它负责处理Spider中获取到的Item,并进行进行后期处理(详细分析、过滤、存储等)的地方.

  • Downloader Middlewares(下载中间件):你可以当作是一个可以自定义扩展下载功能的组件。

  • Spider Middlewares(Spider中间件):你可以理解为是一个可以自定扩展和操作引擎和Spider中间通信的功能组件(比如进入Spider的Responses;和从Spider出去的Requests)

Scrapy的使用

  1. 创建项目

scrapy startproject 项目名

  1. 创建爬虫文件

scrapy genspider 爬虫名 域名

Scrapy Item pipeline(管道文件)使用

当Item在Spider中被收集之后,它将会被传递到Item Pipeline,这些Item Pipeline组件按定义的顺序处理Item。

每个Item Pipeline都是实现了简单方法的Python类,比如决定此Item是丢弃而存储。以下是item pipeline的一些典型应用:

验证爬取的数据(检查item包含某些字段,比如说name字段)
查重(并丢弃)
将爬取结果保存到文件或者数据库中

下载项目图片

使用图片管道 当使用 ImagesPipeline :

在一个爬虫里,你抓取一个项目,把其中图片的URL放入 image_urls 组内。
项目从爬虫内返回,进入项目管道。
当项目进入 ImagesPipeline,image_urls 组内的URLs将被Scrapy的调度器和下载器(这意味着调度器和下载器的中间件可以复用)安排下载,当优先级更高,会在其他页面被抓取前处理。项目会在这个特定的管道阶段保持“locker”的状态,直到完成图片的下载(或者由于某些原因未完成下载)。
当图片下载完,另一个组(images)将被更新到结构中。这个组将包含一个字典列表,其中包括下载图片的信息,比如下载路径、源抓取地址(从 image_urls 组获得)和图片的校验码。 images 列表中的图片顺序将和源 image_urls 组保持一致。如果某个图片下载失败,将会记录下错误信息,图片也不会出现在 images 组中。

爬虫数据持久化保存

step1: items.py文件:自定义字段,确定要爬取的目标网站数据
step2:spiders/douban.py 文件: 爬虫文件,在这里编写爬虫代码,解析数据,获取新的url
step3:数据持久化

方式一:将数据存入mongodb
settings.py文件: 设置文件,在这里设置User-Agent,激活管道文件
ITEM_PIPELINES = {
    'XXXXXXXXXXX': 300,
}

MONGODB 主机名
MONGODB_HOST = '127.0.0.1'
MONGODB 端口号
MONGODB_PORT= 27017
数据库名称
MONGODB_DBNAME = "XXX"
存储数据的表名称
MONGODB_SHEETNAME= "xxxx"

pipelines.py管道:这里进行数据的清洗和持久化
import pymongo
from scrapy.conf import settings

class DoubanPipeline(object):

    # 将数据存储在mongodb中
    def __init__(self,host,port,dbname,sheetname):
        # 创建MONGODB数据库链接
        client = pymongo.MongoClient(host=host, port=port)
        # 指定数据库
        mydb = client[dbname]
        # 存放数据的集合名称
        self.mysheet = mydb[sheetname]

    @classmethod
    def from_crawler(cls, crawler):
        host = crawler.settings["MONGODB_HOST"]
        port = crawler.settings["MONGODB_PORT"]
        dbname = crawler.settings["MONGODB_DBNAME"]
        sheetname = crawler.settings["MONGODB_SHEETNAME"]
    
        return cls(host,port,dbname,sheetname)

    def process_item(self,item,spider):
        data = dict(item)
        # mongodb数据插入语句,使用save保存数据的效率会很慢,因为它需要循环便利,操作费时
        self.mysheet.insert(data)
        return item
方式二:将数据存入mysql数据库
settings.py文件: 设置文件,在这里设置User-Agent,激活管道文件

ITEM_PIPELINES = {
    'xxxxxxxxxxxxxxxxx': 300,
}

#关于数据库的相关配置
MYSQL_HOST = '127.0.0.1'
MYSQL_PORT = 3306
MYSQL_USER = ''
MYSQL_PWD = ''
MYSQL_DB = ''

pipelines.py管道文件
import pymysql
class DoubanPipeline(object):

#     将数据存储值mysql数据库
#     _mysql_exceptions.OperationalError: (1366, 是因为数据库中的字符集与charset="utf8"不符合

    def __init__(self,host,port,user,pwd,db,charset):
        self.client = pymysql.Connect(host,user,pwd,db,port,charset='utf8')
        self.cursor = self.client.cursor()
    
    @classmethod
    def from_crawler(cls,crawler):
        host = crawler.settings['MYSQL_HOST']
        port = crawler.settings['MYSQL_PORT']
        user = crawler.settings['MYSQL_USER']
        pwd = crawler.settings['MYSQL_PWD']
        db = crawler.settings['MYSQL_DB']

        return cls(host,port,user,pwd,db,charset)

    def process_item(self,item,spider):
        insert_sql = """
               insert into doubanmovie(title, playable, content, star, commentnum, inq)
               VALUE (%s, %s, %s, %s, %s, %s)
        """
        try:
            self.cursor.execute(insert_sql, (item['title'],  item['content'], item['score'], item['info']))
            self.client.commit()
        except Exception as err:
            print(err)
            self.client.rollback()
        return item

将sql语句和要插入的数据在item中定义一个方法返回,通过item调用,然后返回

class XxxxItem(scrapy.Item):

    #名称
    title = scrapy.Field()

    def insert_data_to_db(self,dataDict):
        sql = """
        INSERT INTO caipu (%s)
        VALUES (%s)
        """ % (','.join(dataDict.keys()),','.join(['%s']*len(dataDict)))

        data = list(dataDict.values())

        return sql,data
mysql数据异步插入
#twisted是一个异步的网络框架,这里可以帮助我们实现异步将数据插入数据库

#adbapi里面的子线程会去执行数据库的阻塞操作,当一个线程执行完毕之后,同时,原始线程能继续进行正常的工作,服务其他请求。
import pymysql
from twisted.enterprise import adbapi

#异步插入数据库
class DoubanPipeline(object):

    def __init__(self,dbpool):
        self.dbpool = dbpool

    #使用这个函数来应用settings配置文件。
    @classmethod
    def from_crawler(cls, crawler):
        parmas = {
        'host':crawler.settings['MYSQL_HOST'],
        'user':crawler.settings['MYSQL_USER'],
        'passwd':crawler.settings['MYSQL_PASSWD'],
        'db':crawler.settings['MYSQL_DB'],
        'port':3306,
        'charset':'utf8',
        }

        # **表示字典,*tuple元组,
        # 使用ConnectionPool,起始最后返回的是一个ThreadPool
        dbpool = adbapi.ConnectionPool(
            'pymysql',
            **parmas
        )
        return cls(dbpool)

    def process_item(self, item, spider):
        #这里去调用任务分配的方法
        query = self.dbpool.runInteraction(
            self.insert_data_todb,
            item,
            spider
        )
        #数据插入失败的回调
        query.addErrback(
            self.handle_error,
            item
        )

        #执行数据插入的函数
        def insert_data_todb(self,cursor,item,spider):
            insert_str,parmas = item.insertdata()
            cursor.execute(insert_str,parmas)
            print('插入成功')

    def handle_error(self,failure,item):
        print(failure)
        print('插入错误')
        #在这里执行你想要的操作

    def close_spider(self, spider):
        self.pool.close()

Scrapy Shell 的使用

Scrapy终端是一个交互终端,我们可以在未启动spider的情况下尝试及调试代码,也可以用来测试XPath或CSS表达式,查看他们的工作方式,方便我们爬取的网页中提取的数据。

启动Scrapy Shell

scrapy shell " "
scrapy shell -s USER_AGENT=" "

尝试使用Selector

返回 xpath选择器对象列表

response.xpath('')

使用 extract()方法返回 Unicode字符串列表(打印列表第一个元素,终端编码格式显示)

response.xpath(' ').extract()[0]

返回 xpath选择器对象列表

response.xpath('//title/text()')[0].extract()

Scrapy Spider文件介绍

scrapy.Spider是最基本的类,所有编写的爬虫必须继承这个类

主要用到的函数及调用顺序为:
init() : 初始化爬虫名字和start_urls列表

start_requests() 调用make_requests_from url():生成Requests对象交给Scrapy下载并返回response

parse():

解析response,并返回Item或Requests(需指定回调函数)。
Item传给Item pipline持久化 , 而Requests交由Scrapy下载,并由指定的回调函数处理(默认parse()),一直进行循环,直到处理完所有的数据为止。

Scrapy CrawlSpiders介绍和使用

CrawlSpider它是Spider的派生类,Spider类的设计原则是只爬取start_url列表中的网页,而CrawlSpider类定义了一些规则Rule来提供跟进链接的方便的机制,从爬取的网页结果中获取链接并继续爬取的工作

#######rules
CrawlSpider使用rules属性来决定爬虫的爬取规则,并将匹配后的url请求提交给引擎,完成后续的爬取工作。

在rules中包含一个或多个Rule对象,每个Rule对爬取网站的动作定义了某种特定操作,比如提取当前相应内容里的特定链接,是否对提取的链接跟进爬取,对提交的请求设置回调函数等。

LinkExtractors (目的提取链接)
主要参数:

allow:满足括号中“正则表达式”的URL会被提取,如果为空,则全部匹配。
deny:满足括号中“正则表达式”的URL一定不提取(优先级高于allow)。
allow_domains:会提取的链接的domains。
deny_domains:一定不会被提取链接的domains。
restrict_xpaths:使用xpath表达式,和allow共同作用过滤链接。

Scrapy Request和Response相关参数介绍

Request先关参数介绍

url: 就是需要请求,并进行下一步处理的url

callback: 指定该请求返回的Response,由那个函数来处理。

method: 请求一般不需要指定,默认GET方法,可设置为"GET", "POST", "PUT"等,且保证字符串大写

headers: 请求头

cookies: cookies,模拟用户登录需要指定用户的cookies,字典dict型

meta: 比较常用,在不同的请求之间传递数据使用的。字典dict型

encoding: 编码类型,使用默认的 'utf-8' 就行。

dont_filter: 表明该请求不由调度器过滤。这是当你想使用多次执行相同的请求,忽略重复的过滤器。默认为False。

errback: 指定错误处理函数

Response相关参数介绍

status: 响应码
body: 响应体
url:响应url
self.request (request对象)
self.headers (响应头)

Scrapy DOWNLOADER_MIDDLEWARE 的使用

通常防止爬虫被反主要有以下几个策略

  • 动态设置User-Agent(随机切换User-Agent,模拟不同用户的浏览器信息)

*禁用Cookies(前提是爬取的网站不需要cookies参数)(也就是不启用cookies middleware,不向Server发送cookies,有些网站通过cookie的使用发现爬虫行为)

使用cookies池,自定义中间件

除非特殊需要,否则禁用cookies,防止某些网站根据Cookie来封锁爬虫。

COOKIES_ENABLED = False
设置延迟下载(降低访问网站的频率)(设置为2秒或更高)
DOWNLOAD_DELAY = 2
使用IP代理地址池:VPN和代理IP,现在大部分网站都是根据IP来反爬的。

相关文章

  • 简单 Scrapy 使用小结

    Scrapy 安装Scrapy pip install scrapy Scrapy Doc 查看Scrapy的文档...

  • scrapy框架

    一、scrapy简介 二、scrapy原理 三、scrapy工作流程 四、scrapy框架的创建 五、scrapy...

  • Scrapy笔记

    Scrapy笔记 安装scrapy框架: 安装scrapy:通过pip install scrapy即可安装。 如...

  • scrapy笔记

    1 scrapy的运行原理 参考:Learning Scrapy笔记(三)- Scrapy基础Scrapy爬虫入门...

  • Scrapy基础(一): 安装和使用

    安装 新建scrapy项目 目录 scrapy模板 使用pycharm调试scrapy执行流程 scrapy 终端...

  • python爬虫13:scrapy

    scrapy的结构 scrapy的工作原理 scrapy的用法

  • Scrapy笔记

    Scrapy笔记 pip 指定源安装模块 创建Scrapy项目 创建Scrapy爬虫程序 启动Scrapy爬虫 在...

  • PyCharm运行和调试Scrapy

    前言: PyCharm运行和调试Scrapy,首先需要安装Scrapy,安装Scrapy请点链接Scrapy的安装...

  • 11- Scrapy-Redis分布式

    Scrapy和Scrapy-Redis的区别 安装Scrapy-Redis Scrapy-Redis介绍 提供了下...

  • scrapy框架基本使用

    scrapy基本介绍 scrapy VS requests Mac安装 conda install scrapy ...

网友评论

      本文标题:Scrapy

      本文链接:https://www.haomeiwen.com/subject/lzirrqtx.html