20200227 scrapy框架

时间:2020-03-11
本文章向大家介绍20200227 scrapy框架,主要包括20200227 scrapy框架使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

昨日回顾

# 1 xpath

/    //和能看懂    

用:去copy      

## 2 selenium

驱动浏览器,模拟浏览器行为(为解决js执行的问题)

page_source 

查找标签:点击,键盘输入,清空,写文字

执行js:打开标签,滑动屏幕

cookie(重要):可以手动通过selenium登陆进去,取到cookie,搭建cookie池

动作链:很炫,基本用处很少

## 3 抓包工具的使用

抓手机包:移动开发的后端(postman),抓包工具

移动开发人员在你手机上装一个连接你机器的app

app--resful接口-》10.0.0.1  

app-------抓包工具(可以看到发送和接受到的数据什么样)----------->你电脑的ip(跑着项目),在你电脑上加断点

scrapy框架

1.介绍

Scrapy 是一个基于 Twisted 的异步处理框架,是纯 Python 实现的爬虫框架,其架构清晰,模块之间的耦合程度低,可扩展性极强,可以灵活完成各种需求。我们只需要定制开发几个模块就可以轻松实现一个爬虫。

1.1 框架的生命周期

它可以分为如下的几个部分。

  • Engine,引擎,用来处理整个系统的数据流处理,触发事务,是整个框架的核心。
  • Item,项目,它定义了爬取结果的数据结构,爬取的数据会被赋值成该对象。
  • Scheduler, 调度器,用来接受引擎发过来的请求并加入队列中,并在引擎再次请求的时候提供给引擎。
  • Downloader,下载器,用于下载网页内容,并将网页内容返回给蜘蛛。
  • Spiders,蜘蛛,其内定义了爬取的逻辑和网页的解析规则,它主要负责解析响应并生成提取结果和新的请求。
  • Item Pipeline,项目管道,负责处理由蜘蛛从网页中抽取的项目,它的主要任务是清洗、验证和存储数据。
  • Downloader Middlewares,下载器中间件,位于引擎和下载器之间的钩子框架,主要是处理引擎与下载器之间的请求及响应。
  • Spider Middlewares, 蜘蛛中间件,位于引擎和蜘蛛之间的钩子框架,主要工作是处理蜘蛛输入的响应和输出的结果及新的请求。

1.1 框架流程

Scrapy 中的数据流由引擎控制,其过程如下:

  • Engine 首先打开一个网站,找到处理该网站的 Spider 并向该 Spider 请求第一个要爬取的 URL。
  • Engine 从 Spider 中获取到第一个要爬取的 URL 并通过 Scheduler 以 Request 的形式调度。
  • Engine 向 Scheduler 请求下一个要爬取的 URL。
  • Scheduler 返回下一个要爬取的 URL 给 Engine,Engine 将 URL 通过 Downloader Middlewares 转发给 Downloader 下载。
  • 一旦页面下载完毕, Downloader 生成一个该页面的 Response,并将其通过 Downloader Middlewares 发送给 Engine。
  • Engine 从下载器中接收到 Response 并通过 Spider Middlewares 发送给 Spider 处理。
  • Spider 处理 Response 并返回爬取到的 Item 及新的 Request 给 Engine。
  • Engine 将 Spider 返回的 Item 给 Item Pipeline,将新的 Request 给 Scheduler。
  • 重复第二步到最后一步,直到 Scheduler 中没有更多的 Request,Engine 关闭该网站,爬取结束。

通过多个组件的相互协作、不同组件完成工作的不同、组件对异步处理的支持,Scrapy 最大限度地利用了网络带宽,大大提高了数据爬取和处理的效率。

五大组件

引擎:大总管,总的控制数据流动

调度器:去重,加入队列

下载器:负责下载,加载数据

爬虫:咱们主要在这写,解析response和重新发起请求

项目管道:持久化相关

二大中间件

爬虫中间件:爬虫和引擎之间(用的少)

下载中间件:引擎和下载器之间(加代理,加cookie,修改user-agent,集成selenium)

2.安装

mac/Linux: 
    pip install scrapy


windows:    (两种方式)  
    1. pip install scrapy
    
    2. 如果报错,以下
        -pip install wheel  (xxx.whl文件安装模块)
        -下载pywin32  
            -pip install pywin32  或者 下载.exe文件安装https://sourceforge.net/projects/pywin32/files/pywin32/
         -下载twisted的wheel文件
         - 执行pip iinstall 下载目录\Twisted-17.9.0-cp36-cp36m-win_amd64.whl(可以直接手动拖放至控制台)

3.创建项目

通过命令行

# 创建项目
scrapy startproject 项目名


# 创建爬虫
    #(django中创建app)在spiders文件夹下创建一个py文件,一个py文件就是一个爬虫(不要注册,没有注册一说)
scrapy genspider 爬虫名 爬取的地址
scrapy genspider chouti dig.chouti.com

# 打开项目,pycharm打开

运行爬虫

# 命令行运行
scrapy crawl 爬虫名
scrapy crawl 爬虫名 --nolog    # 不打印日志
    或者更改log级别: LOG_LEVEL='ERROR'    # 也可不打印日志
    
    
    
# pycharm运行
设置
    在项目目录下创建一个py文件,假设叫main.py,点击右键执行即可执行爬虫,等同于命令
    from scrapy.cmdline import execute
    execute(['scrapy','crawl','chouti','--nolog'])

保存数据到本地文件

# 保存文件的指令
from scrapy.cmdline import execute
execute(['scrapy', 'crawl',  'lianjia', '-o', 'items.csv','--nolog'])

目录介绍

-scarpyfirst 项目名
    -scrapy.cfg          上线相关的(不用管)
    -scrapyfirst         文件夹
    -spiders文件夹         所有的爬虫写在这里面
        -chouti.py        一个py文件就是一个爬虫(类似于django的app)
        -items.py         :配合管道,做数据存储(类似于django中models.py 写一个个的模型类)
    -middlewares.py         :中间件(爬虫中间件,下载中间件都写在这里面)
    -pipelines.py           :管道,持久化相关,数据存储卸载这
    -settings.py            :配置文件相关

setting介绍

#配置文件全是大写
ROBOTSTXT_OBEY = True  #是否遵循爬虫协议,如果是true,基本上网站都爬不了,遵循要爬取网站的爬虫协议,一般设置成false
USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.122 Safari/537.36'
LOG_LEVEL='ERROR'   # 只打印错误信息

# 控制持久化的类执行顺序
ITEM_PIPELINES = {
   'mypachong.pipelines.MypachongMySQLPipeline': 100,  # 优先级,数值越小,优先级越高
   'mypachong.pipelines.MypachongPipeline': 300,        # 优先级,数值越小,优先级越高
}

使用--爬取天猫

自定义启动文件run.py

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

' 启动文件 '

__author__ = 'Fwzzz'

# 代替cmd的命令
from scrapy.cmdline import execute
execute(['scrapy','crawl','chouti','--nolog'])
# execute(['scrapy','crawl','chouti'])

爬虫文件

# -*- coding: utf-8 -*-
import scrapy
from urllib.parse import urlencode
from mypachong import items


# 爬取天猫



class ChoutiSpider(scrapy.Spider):
    # 爬虫名
    name = 'chouti'
    # 允许爬取的域名
    allowed_domains = ['www.tmall.com']
    # 初始请求  自行向域名发送get请求获取数据
    # start_urls = ['http://www.baidu.com/']


# 自定义初始请求

    # 实例化获取初始请求对象
    def __init__(self,*args,**kwargs):
        # 继承父类的属性
        super(ChoutiSpider,self).__init__(*args,**kwargs)
        # 定义接口的url
        self.api = 'http://list.tmall.com/search_product.htm?'
        # 定义搜索的接口参数     (通过urlencode拼接)
        self.param = {
                'q' :'女装大佬',
                'totalPage' :1,
                'jumpto' :1
        }

    # 想要自行发送定义请求,重写Spider类中的start_requests方法
    def start_requests(self):
        # 获取主页的url
        url = self.api + urlencode(self.param)
        # 搜索页发送请求
        # callback 回调函数,进行处理获取数据   并指定dont_filter=True 链接不去重
        yield scrapy.Request(url=url,callback=self.getpage,dont_filter=True)


    # 获取响应,进行数据的清洗(获取总页码)
    def getpage(self,response):
        # 进行解析
        page = response.css('[name="totalPage"]::attr(value)').extract_first()
        # print(page)   # 30
        # 将接口的url页数更换
        self.param['totalPage'] = int(page)
        # 发送新的请求,获取所有页面的数据
        # for i in range(1,self.param['totalPage']+1):
        for i in range(1,2):
            self.param['jumpto'] = i
            # 拼接url
            url = self.api + urlencode(self.param)
            # 发送请求到新的回调函数中去
            yield scrapy.Request(url,callback=self.get_info,dont_filter=True)


    # 解析页面中的数据
    def get_info(self, response):
        # 获取数据 价格,商品名,交易量,图片
        # 先获取当前页面的所有商品标签对象
        product_list = response.css('.product  ')
        for product in product_list:
            # 解析单数据
            good_title = product.css('.productTitle a::attr(title)').extract_first()
            good_price = product.css('.productPrice em::attr(title)').extract_first()
            good_img = product.css('.productImg img::attr(src)').extract_first()
            # 图片懒加载解决
            if not good_img:
                good_img = product.css('.productImg img::attr(data-ks-lazyload)').extract_first()
            # print(good_title,good_img,good_price)

            # 返回数据给items或者继续发送请求
            item = items.MypachongItem()    # 实例化获得items对象
            # 将数据封装成items对象
            item['good_title'] = good_title
            item['good_price'] = good_price
            item['good_img'] = good_img

            # 这里需要设置setting文件中的ITEM_PIPELINES,yield之后并触发pipelines
            yield item

items文件 控制接收持久化字段

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

# Define here the models for your scraped items
#
# See documentation in:
# https://docs.scrapy.org/en/latest/topics/items.html

import scrapy


# 规定了items接受的那些对象
class MypachongItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    good_title = scrapy.Field()
    good_price = scrapy.Field()
    good_img = scrapy.Field()

pipelines.py 持久化存储

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

# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html

import pymysql


# 存数据 --文件保存方式
class MypachongPipeline(object):

    def open_spider(self,spider):
        '''爬虫打开时触发一次'''
        print('我打开了')
        self.f = open('a.txt','w')


    def process_item(self, item, spider):
        '''每次数据都会触发'''
        # print('在items后我被触发了')
        self.f.write(item['good_title']+item['good_price']+item['good_img'])
        self.f.write('\n')
        return item

    def close_spider(self,spider):
        '''爬虫关闭之后触发一次'''
        print('我关闭了')



# 存数据 --MySQL保存方式  需要去settings文件中设置ITEM_PIPELINES优先级
class MypachongMySQLPipeline(object):
    def open_spider(self,spider):
        self.conn = pymysql.connect(
            host='127.0.0.1',
            user='root',
            password='',
            database='tianmao',
            port=3306
        )
        print('我打开了mysql')

    def process_item(self, item, spider):
        cursor = self.conn.cursor()
        sql = "insert into article (title,price,img) values ('%s','%s','%s')"%(item['good_title'],item['good_price'],item['good_img'])
        # sql = f"insert into article (title,price,img) values ('{item['good_title']}','{item['good_price']}','{item['good_img']}')"
        cursor.execute(sql)
        # 提交
        self.conn.commit()


    def close_spider(self,spider):
        self.conn.close()
        print('我关闭了mysql')

settings.py

BOT_NAME = 'mypachong'



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



ROBOTSTXT_OBEY = False



# 控制持久化的类执行顺序
ITEM_PIPELINES = {
   'mypachong.pipelines.MypachongMySQLPipeline': 100,  # 优先级,数值越小,优先级越高
   'mypachong.pipelines.MypachongPipeline': 300,        # 优先级,数值越小,优先级越高
}

4. scrapy的数据解析(重点)

css选择器

res.css('[name="tag"]::text').extract_first()

    ::text      获取标签内文本
    ::attr(属性)  获取标签属性值
            
# 需要与下面的extract想配合获取内容

    .extract()      获取对象内容列表
    .extract_first()    获取第一个

5. scrapy的持久化存储(重点)

详细使用参见上面的爬取天猫案例

第一种,通过命令:scrapy crawl chout -o aa.csv  (用的比较少)
    需要在parser解析方法中返回列表套字典的格式
    
    
第二种:通过管道方式(文件,数据,redis,mongodb),同时支持以多种方式存储
    -1 在items.py中定义一个类,写属性(要存多少字段,就有多少属性)
    -2 在爬虫中中解析出数据,把数据放到这个类对象中,然后  yield item
    -3 在配置文件中配置:ChoutiPipeline对应pipelines.py中的类
    ITEM_PIPELINES = {
        'scrapyfirst.pipelines.ChoutiPipeline': 300,   # 数字表示优先级,数字越小,优先级越高
        }
  -4 pipelines.py中写ChoutiPipeline类
    -open_spider:开启时调用,打开文件,打开数据库连接
    -process_item:存数据
    -close_sapider:关闭时调用,关闭文件,关闭数据库连接
    
  -总结:ITEM_PIPELINES可以写多个,有优先级的,数字越小,优先级越大,一定要注意process_item一定要return ,                 否则后续就拿不到item了

补充

1 pycharm系列激活

http://idea.medeming.com/jet/

2 ide,开发工具

你用什么ide?

ide系列:

java:eclipse(免费),myeclips(收费),idea(大部分java都用它)

python:pycharm,vscode(微软出的,免费,go,c,python,java)

go:goland,vscode。。

开发安卓:eclipse+adt,谷歌爸爸花钱买了jetbrains公司的版权idea+adt=androidstatdio(免费)

java,当年已经有大量的java开发人员,java可以直接无缝转过去,java虚拟机

开发ios:必须买Mac,Xcode(黑苹果)

jetbrains公司全家桶系列:idea,pycharm,webstom,goland,php

python体系

python基础,mysql,前端,web框架,爬虫,数据分析,人工智能

java体系

javase:基础,可以做桌面开发(基本上没有)

学完基础+安卓相关包的学习

javaee:web相关

javame:手机开发(不是安卓,ios,很古老的java手机软件)

区别:jdk,jre,jvm

jdk:java软件开发工具包,java开发人员需要安装

jre:java运行环境,java软件才能运行

jvm:java虚拟机 (java程序运行在虚拟机之上),跨平台,一次编码到处运行

c/c++:如果想在windwos上运行,需要在window上编译  exe

go----》编译之后---》直接可以运行   跨平台编译:在windows平台可以编译出liunx下可执行的文件

java写了代码----》编译--》jar包和war包  不是编译成直接可以运行的二进制(中间态)---》需要操作系统装java虚拟机(java虚拟机,要跑起来,至少就得占500m内存)

原文地址:https://www.cnblogs.com/fwzzz/p/12460459.html