精华内容
下载资源
问答
  • 层次分析法昆明理工大学2013.12.17框架第一节 指标体系的建立第二节 指标权重的确定第三节 层析分析法的思想和原理第四节 层次分析法的模型和步骤第五节 层次分析法的应用第一节 指标体系的建立一.指标体系的建立应...
  • 根据卢辉老师的《数据挖掘与数据化运营实战》10.6的案例总结 数据摸底 1、 在一个大的项目中可以只选择一个类别进行分析,如找出某网站最有可能初次成交的卖家群体,就可以先找一个类目的商品进行分析,是模型的...

    根据卢辉老师的《数据挖掘与数据化运营实战》10.6的案例总结

    • 数据摸底
      1、 在一个大的项目中可以只选择一个类别进行分析,如找出某网站最有可能初次成交的卖家群体,就可以先找一个类目的商品进行分析,是模型的效果,考虑要不要推广到其他商品类目。
      2、 通过数据透视等方式查看有没有哪一个指标对于初次成交是“致命的”,比如说,每天上线10次以上的卖家数占所有完成初次成交的卖家数量的90%以上,那就可以只取每天上线10次以上的卖家的数据进行分析。这样做会在损失比较少的数据信息的基础上大大降低样本数量,减少噪声数据,提高模型的有效性。
      3、与业务方沟通确定潜在的分析字段和指标。(业务人员由于经验可能对数据指标有更高的灵敏度)
      4、通过对挑选出来的字段分析,必要时可增添一些衍生变量(对原始字段进行组合),即将有联系的字段通过数值计算生成新的字段。

    • 数据抽取和清洗
      1、数据抽取:按照合理的抽样方法确定训练集、测试集。
      2、熟悉数据的分布特征和基本统计指标。
      3、发现缺失值、异常值和与业务逻辑相矛盾的数据并处理。将类型变量(中文输入)转变为数字格式的分类变量。缺失值和异常值较少可以直接删除该样本,较多就要考虑更改或补充,方法:补充均值、众数、最小方差法或随即森林。

    • 相关性检验和共线性排查
      1、检验解释变量间的相关性,将相关性强的字段只留一个。
      2、分别检验解释变量与因变量的相关性,然后剔除相关性弱的变量,是变量筛选的思路之一。

    • 潜在自变量的分布转换
      数据离散化:分箱
      数据严重偏态:取对数

    • 筛选变量
      1、结合业务经验筛选出最关键的指标
      2、根据相关性将相关性强的留下一个
      3、卡方检验
      4、IV 和WOE(自变量是分类变量,因变量是二分类变量,自变量连续可以进行分箱)转换
      5、降维的方法

    • 搭建响应模型
      主要有决策树,逻辑回归,神经网络等方法

    • 确定冠军模型并得出主要的分析结论
      主要通过响应率,捕获率和lift 值来对比模型的有效性。注意,并不是这三个指标的值越高越好,如果逻辑回归和神经网络的结果相差不多,神经网络只是略高于逻辑回归,这时候选择逻辑回归更好,因为逻辑回归的可解释行和运算速度高于神经网络,更有助于我们通过数学公式得到想要的结论,有助于业务方落地应用。

    • 基于模型和分析结论确定运营方案
      以逻辑回归为例,可以得到每个样本达成目标的概率,将这个概率分数分组,对于前10%的样本,给予“临门一脚”的运营方案,给予更多的资源支持,从而有效促进样本达标。
      对于10%至40%的样本,深入分析其概率不高主要是哪个指标比较落后造成的,给予针对性的运营方案。
      对于后30-40%的样本,做好长期培育的心理准备,采取讲座,社区活动等方式引导该样本完善自己,

    • 模型应用落地效果跟踪反馈
      将运营之后的增长率和自然增长率进行对比,观察二者有无显著性差异。(假设检验,如t检验)

    展开全文
  • QT调试详细操作步骤案例分析

    千次阅读 2019-07-08 19:09:04
    目录QT调试详细操作步骤案例分析QT调试详细步骤1. 手动调试1.1 输入备调试的代码1.2 设置断点1.3 单步调试简单介绍1.4 调试案例1.4.1 纯C++代码的调试1.4.2 QT程序的调试2. 使用QDebug进行自动调试功能快捷键如何...

    QT调试详细操作步骤及案例分析

    第一次尝试写博客,我也会尽量写的详细一些…
    写博客的目的一个是将自己所学独立总结一下,方便以后自己回顾,另外也希望能给大家一些帮助~

    QT调试详细步骤

    1. 手动调试

    1.1 输入备调试的代码

    1.2 设置断点

    在行号左侧的空白处点击一下,产生一个“红圆点”,即设置断点。所谓断点,就是程序运行到该行代码时会暂停下来,从而可以查看一些信息,如变量值等。要取消断点,只要在那个断点上再点击一下就可以了。
    设置断点

    1.3 单步调试简单介绍

    • 单步跳过(F10)
      一次执行一条语句,遇到函数不进入,直接单步得到函数执行的结果。需要说明一下,对于QT程序,程序会跳转到QWidget类的x()函数的源码处
    • 单步进入(F11)
      按照顺序进入所在行调用的函数内部,一般使用单步进入后配合单步跳过 使用,查看函数内部逐条语句的执行情况以及各个变量值的变化。
    • 单步跳出(shift + F11)
      在函数运行完后,退出该函数,回到调用该函数的语句的下一步。需要说明一下,对于QT程序的类函数源码,按下“单步跳出”按钮可回到原来的断点处。

    在debugger的菜单栏中也有相应的图标,分别对应上述操作:
    调试button

    • 停止调试: 调试关闭,进入平常的编码模式;
    • 继续调试: 当计算器无法独立进行调试(比如需要键盘输入、弹出窗口等操作前调试无法正常进行),这时需要点击继续调试,使得调试正常进行;另外,当程序在断点处停了下来,按下继续按钮后,程序便会像正常运行一样,执行后面的代码,直到遇到下一个断点,或者程序结束。

    (左边为 继续调试 图标,右边为 停止调试 图标)
    调试button_2

    1.4 调试案例

    1.4.1 纯C++代码的调试

    下面是一个简单的纯C++代码的调试过程:

    源代码:

    #include <iostream>
    using namespace std;
    
    //从begin_num开始累加,加到第num个数字
    int function(int start,int num){
        int sum;
        for(int i=0;i<num;i++){
            sum += (start + i);
        }
        return sum;
    }
    
    int main(int argc, char *argv[])
    {
        int sum = 0;
    
        //从begin_num开始累加,加到第num个数字
        int begin_num = 4;
        int num = 5;
    
        for(int i=0;i<num;i++){
            sum += (begin_num + i);
        }
    
        int sum1 = function(begin_num,num);
    
        cout<<sum<<'\n'<<sum1<<endl;
        return 0;
    }
    

    运行结果:
    在这里插入图片描述
    明明是相同的代码为什么最后的运行结果不一样呢?一般这种逻辑错误都需要进行调试分析来找出错误所在;

    step1 我们先设置一个断点,在开始调试,在右侧我们可以看到当前mian函数中定义了的几个变量的值,当我们逐条语句进行时,就能看到他们随着语句执行值的变化。
    在这里插入图片描述
    step2 使用单步跳过
    当单步跳过两次,执行了两条赋值初始化语句后,begin_num与num的值发生变化;
    在这里插入图片描述
    接下来我们看在for循环语句中相应变量值的变化:
    第一次循环:
    在这里插入图片描述
    第二次循环:
    在这里插入图片描述

    第五次循环后的结果:
    在这里插入图片描述

    step3循环结束,此时我们用单步进入看看函数function()中语句执行情况:
    在这里插入图片描述
    在这里我们可以发现,sum在声明后并没有初始化,所以我们最后通过函数得到的sum1值比较奇怪。
    就是通过这样类似的操作,我们可以将运行过程中变量的值与我们预想中的值作对比,来找出程序中的逻辑错误。

    1.4.2 QT程序的调试

    源代码:

    #include <QApplication>
    #include <QWidget>
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
    
        QWidget widget;
        int x = widget.x();
        int y = widget.y();
    
        QRect geometry = widget.geometry();
        QRect frame = widget.frameGeometry();
        widget.show();
        
        return a.exec();
    }
    

    (1)然后开始调试:
    在这里插入图片描述
    注意:此时需要点击继续调试!(当继续调试图标亮着并且其他操作无效时,需要考虑点击继续调试),继续后直接跳到断点位置。
    在这里插入图片描述
    (2)点击单步跳过,发现x,y的值变为0,这是为什么呢?
    在这里插入图片描述
    现猜想可能是窗口没有显示的原因,那么就更改代码,让窗口先显示出来,再看这些值。如下图,此时窗口显示出来,x,y也有了相应的值。
    在这里插入图片描述

    2. 使用QDebug进行自动调试

    2.1 简单介绍

    一般在程序调试过程中很常用的是qDebug() 函数,它可以将调试信息直接输出到控制台,在Qt Creator中是输出到应用程序输出栏 。
    使用qDebug()函数进行调试,要现添加 #include <QDebug> 头文件。然后这里使用了两种输出方式:

    方式一:直接将字符串当做参数传给qDebug()函数,例如下面使用这种方法输出x和y的值。

    方式二:使用输出流的方式一次输出多个值,它们的类型可以不同。例如程序中输出geometry和frame的值。

    2.2 调试案例分析

    源代码:

    #include <QApplication>
    #include <QDebug>
    #include <QWidget>
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        QWidget widget;
        
        widget.resize(400, 300);       // 设置窗口大小
        widget.move(200, 100);         // 设置窗口位置
        widget.show();
        int x = widget.x();
        qDebug("x: %d", x);            // 输出x的值
        int y = widget.y();
        qDebug("y: %d", y);
        QRect geometry = widget.geometry();
        QRect frame = widget.frameGeometry();
        qDebug() << "geometry: " << geometry << "frame: " << frame;
        
        return a.exec();
    }
    
    

    在这里插入图片描述
    使用QDebug进行自动调试,其实就是我们通过函数把自变量的值输出,以供我们与预期值进行对比。

    总而言之,以上两种手动调试与自动调试都是让我们看到变量值的变化,随后我们将其与预期值对比,通过数据直观地测试我们的程序是否出错,并方便我们准确地找到bug所在的语句或语句块。

    展开全文
  • TransCAD交通规划实例详细步骤案例分析 一步步教你使用transcad
  • spss进行判别分析步骤_spss判别分析结果解释_spss判别分析案例详解 1.Discriminant Analysis判别分析主对话框 如图 1-1 所示 图 1-1 Discriminant Analysis 主对话框 (1)选择分类变量及其范围 在主对话框中...

    spss进行判别分析步骤_spss判别分析结果解释_spss判别分析案例详解

    1.Discriminant Analysis判别分析主对话框 如图 1-1 所示

    图 1-1 Discriminant Analysis 主对话框

    (1)选择分类变量及其范围

    在主对话框中左面的矩形框中选择表明已知的观测量所属类别的变量(一定是离散变量),
    按上面的一个向右的箭头按钮,使该变量名移到右面的Grouping Variable 框中。
    此时矩形框下面的Define Range 按钮加亮,按该按钮屏幕显示一个小对话框如图1-2 所示,供指定该分类变量的数值范围。

    图 1-2 Define Range 对话框

    在Minimum 框中输入该分类变量的最小值在Maximum 框中输入该分类变量的最大值。按Continue 按钮返回主对话框。

    (2)指定判别分析的自变量

    图 1-3 展开 Selection Variable 对话框的主对话框

    在主对话框的左面的变量表中选择表明观测量特征的变量,按下面一个箭头按钮。
    把选中的变量移到Independents 矩形框中,作为参与判别分析的变量。

    (3) 选择观测量

    图 1-4 Set Value 子对话框

    如果希望使用一部分观测量进行判别函数的推导而且有一个变量的某个值可以作为这些观测量的标识,
    则用Select 功能进行选择,操作方法是单击Select 按钮展开Selection Variable。选择框如图1-3 所示。
    并从变量列表框中选择变量移入该框中再单击Selection Variable 选择框右侧的Value按钮,
    展开Set Value(子对话框)对话框,如图1-4 所示,键入标识参与分析的观测量所具有的该变量值,
    一般均使用数据文件中的所有合法观测量此步骤可以省略。

    (4) 选择分析方法

    在主对话框中自变量矩形框下面有两个选择项,被选中的方法前面的圆圈中加有黑点。这两个选择项是用于选择判别分析方法的
    l Enter independent together 选项,当认为所有自变量都能对观测量特性提供丰富的信息时,使用该选择项。选择该项将不加选择地使用所有自变量进行判别分析,建立全模型,不需要进一步进行选择。
    l Use stepwise method 选项,当不认为所有自变量都能对观测量特性提供丰富的信息时,使用该选择项。因此需要判别贡献的大小,再进行选择当鼠标单击该项时Method 按钮加亮,可以进一步选择判别分析方法。

    2.Method对话框 如图 1-5 所示:

    图 1-5 Stepwise Method 对话框

    单击“Method”按钮展开Stepwise Method对话框。

    (1)Method 栏选择进行逐步判别分析的方法

    可供选择的判别分析方法有:
    l Wilks’lambda 选项,每步都是Wilk 的概计量最小的进入判别函数
    l Unexplained variance 选项,每步都是使各类不可解释的方差和最小的变量进入判别函数。
    l Mahalanobis’distance 选项,每步都使靠得最近的两类间的Mahalanobis 距离最大的变量进入判别函数
    l Smallest F ratio 选项,每步都使任何两类间的最小的F 值最大的变量进入判刑函数
    l Rao’s V 选项,每步都会使Rao V 统计量产生最大增量的变量进入判别函数。可以对一个要加入到模型中的变量的V 值指定一个最小增量。选择此种方法后,应该在该项下面的V-to-enter 后的矩形框中输入这个增量的指定值。当某变量导致的V值增量大于指定值的变量后进入判别函数。

    (2) Criteria 栏选择逐步判别停止的判据

    可供选择的判据有:
    l Use F value 选项,使用F值,是系统默认的判据当加人一个变量(或剔除一个变量)后,对在判别函数中的变量进行方差分析。当计算的F值大于指定的Entry 值时,该变量保留在函数中。默认值是Entry为3.84:当该变量使计算的F值小于指定的Removal 值时,该变量从函数中剔除。默认值是Removal为2.71。即当被加入的变量F 值为3.84 时才把该变量加入到模型中,否则变量不能进入模型;或者,当要从模型中移出的变量F值<2.71时,该变量才被移出模型,否则模型中的变量不会被移出.设置这两个值时应该注意Entry值〉Removal 值。 l Use Probability of F选项,用F检验的概率决定变量是否加入函数或被剔除而不是用F值。加入变量的F值概率的默认值是0.05(5%);移出变量的F 值概率是0.10(10%)。Removal值(移出变量的F值概率) >Entry值(加入变量的F值概率)。

    (3) Display栏显示选择的内容

    对于逐步选择变量的过程和最后结果的显示可以通过Display 栏中的两项进行选择:
    l Summary of steps 复选项,要求在逐步选择变量过程中的每一步之后显示每个变量的统计量。
    l F for Pairwise distances 复选项,要求显示两两类之间的两两F 值矩阵。

    3.Statistics对话框 指定输出的统计量如图1-6 所示:

    图 1-6 Statistics 对话框

    可以选择的输出统计量分为以下3 类:

    (l) 描述统计量
    在 Descriptives 栏中选择对原始数据的描述统计量的输出:
    l Means 复选项,可以输出各类中各自变量的均值MEAN、标准差std Dev 和各自变量总样本的均值和标准差。
    l Univariate ANOV 复选项,对各类中同一自变量均值都相等的假设进行检验,输出单变量的方差分析结果。
    l Box’s M 复选项,对各类的协方差矩阵相等的假设进行检验。如果样本足够大,表明差异不显著的p 值表明矩阵差异不明显。

    (2) Function coefficients 栏:选择判别函数系数的输出形式
    l Fisherh’s 复选项,可以直接用于对新样本进行判别分类的费雪系数。对每一类给出一组系数。并给出该组中判别分数最大的观测量。
    l Unstandardized 复选项,未经标准化处理的判别系数。

    (3) Matrices 栏:选择自变量的系数矩阵
    l Within-groups correlation matrix复选项,即类内相关矩阵,
    它是根据在计算相关矩阵之前将各组(类)协方差矩阵平均后计算类内相关矩阵。
    l Within-groups covariance matrix复选项,即计算并显示合并类内协方差矩阵,
    是将各组(类)协方差矩阵平均后计算的。区别于总协方差阵。
    l Separate-groups covariance matrices复选项,对每类输出显示一个协方差矩阵。
    l Total covariance matrix复选项,计算并显示总样本的协方差矩阵。

    4.Classification 对话框指定分类参数和判别结果 如图1-7 所示

    图 1-7 Classification 对话框

    5.Save对话框,指定生成并保存在数据文件中的新变量。如图1-8 所示:

    图 1-8 Save 对话框数据分析培训

    6.选择好各选择项之后,点击“OK”按钮,提交运行Discriminant过程。

    转载于:https://www.cnblogs.com/amengduo/p/9587234.html

    展开全文
  • scrapy爬虫具体案例详细分析 scrapy,它是一个整合了的爬虫框架, 有着非常健全的管理系统. 而且它也是分布式爬虫, 它的管理体系非常复杂. 但是特别高效.用途广泛,主要用于数据挖掘、检测以及自动化测试。 本项目...

    scrapy爬虫具体案例详细分析

    scrapy,它是一个整合了的爬虫框架, 有着非常健全的管理系统. 而且它也是分布式爬虫, 它的管理体系非常复杂. 但是特别高效.用途广泛,主要用于数据挖掘、检测以及自动化测试。

    本项目实现功能:模拟登录、分页爬取、持久化至指定数据源、定时顺序执行多个spider

    一、安装

    首先需要有环境,本案例使用
    python 2.7,macOS 10.12,mysql 5.7.19

    下载scrapy

    pip install scrapy

    下载Twisted

    pip install Twisted

    下载MySQLdb

    pip install MySQLdb

    二、构建项目

    创建项目

    *****@localhost:~$ scrapy startproject scrapy_school_insurance

    在对应的目录下面就会生成如下目录格式

    scrapy_school_insurance/
        spiders/                        
            _init_.py
        _init_.py
        items.py                    ---- 实体(存储数据信息)
        middlewares.py          ---- 中间件(初级开发无需关心)
        pipelines.py                ---- 处理实体,页面被解析后的数据会发送到此(持久化、验证实体有效性,去重)
        setting.py             ---- 设置文件
    scrapy.cfg                  ---- configuration file

    在spiders下创建school_insurance_spider.py 编写具体爬取页面信息的代码

    三、spider

    首先,要做的是定义items,也就是你需要的数据项,数据存储的地方。

    定义Item非常简单,只需要继承scrapy.Item类,并将所有字段都定义为scrapy.Field类型即可。
    Field对象用来对每个字段指定元数据。

    定义子项目的items.py

    # -*- coding: utf-8 -*—
    
    import scrapy
    
    
    class ScrapySchoolInsuranceItem(scrapy.Item):
        # 班级名称
        classroom = scrapy.Field()
        # 学生身份证
        id_card = scrapy.Field()
        # 学生姓名
        student_name = scrapy.Field()
        # 家长姓名
        parent_name = scrapy.Field()
        # 练习电话
        phone = scrapy.Field()
        # 是否缴费
        is_pay = scrapy.Field()
        # 学校名称
        school_id = scrapy.Field()
        

    下面进行网络爬取步骤:
    school_insurance_spider.py 文件
    此类需要继承scrapy.Spider类
    先分析一下基本结构和工作流程:

    import scrapy
    
    
    class SchoolInsuranceSpider(scrapy.Spider):
        name = "school_insurance"
    
        def start_requests(self):
            urls = [
                'http://quotes.toscrape.com/page/1/',
                'http://quotes.toscrape.com/page/2/',
            ]
            for url in urls:
                yield scrapy.Request(url=url, callback=self.parse)
    
        def parse(self, response):
            pass

    这是spider最基本的结构:
    name:是你爬虫的名字,后面启动爬虫的时候使用就是这个参数。
    start_requests():是初始请求,爬虫引擎会自动调取。
    urls:是你定义需要爬取的url,可以是一个也可以是多个。
    parse():函数主要进行网页分析,爬取数据。当你的返回没有指定回调函数的时候,默认回调parse()函数;

    先来分析一下在迭代器中的这句话:

    yield scrapy.Request(url=url, callback=self.parse)

    yield 是一个python关键字,代表这个函数返回的是个生成器。

    理解yield,你必须理解:当你仅仅调用这个函数的时候,函数内部的代码并不立马执行,这个函数只是返回一个生成器对象。只有当你进行迭代此对象的时候才会真正的执行其中的代码,并且以后的迭代会从在函数内部定义的那个循环的下一次,再返回那个值,直到没有可以返回的。

    这里的start_requests函数就会被当做一个生成器使用,而scrapy引擎可以被看作是迭代器。scrapy会逐一获取start_requests方法中生成的结果,并判断该结果是一个什么样的类型。当返回Request时会被加入到调度队列中,当返回items时候会被pipelines调用。很显然,此时迭代返回的是request对象。

    引擎会将此请求发送到下载中间件,通过下载中间件下载网络数据。一旦下载器完成页面下载,将下载结果返回给爬虫引擎。引擎将下载器的响应(response对象)通过中间件返回给爬虫。此时request()使用了回调函数parse(),则response作为第一参数传入,进行数据被提取操作。

    当你直接使用scrapy.Request()方法时默认是get请求。

    而此项目是要爬取一个需要登录的网站,第一步要做的是模拟登录,需要post提交form表单。所以就要使用scrapy.FormRequest.from_response()方法:

    def start_requests(self):
            start_url = 'http://jnjybx.jnjy.net.cn/admin/login.aspx?doType=loginout'
            return [
                Request(start_url, callback=self.login)
            ]
            
    # 模拟用户登录
    def login(self, response):
            return scrapy.FormRequest.from_response(
                response,
                formdata={'username': ‘***’, 'password': ‘***’},
                meta={'school_id': ***},
                callback=self.check_login
            )
            
    

    访问网址后我们直接回调login方法,进行表单提交请求。表单结构需根据不同网站自己分析,此网站只需提交username和password,如果你需要传递自定义参数,可通过meta属性进行定义传递,回调函数中使用response.meta['school_id']就可以获取传递的参数了。一般网站登录成功之后会直接返回,登录后的页面的response,就可以直接回调数据爬取的方法进行爬取了。
    但此网站会单独返回一段json来告诉我是否登录成功,并且并不提供下一步的url,所以我这里多了一步check_login()方法,并在判断登录成功后的代码段里重新请求了登录成功后的url。(scrapy是默认保留cookie的!)

    模拟登录完整代码:

    #  -*- coding: utf-8 -*-
    import scrapy
    
    import json
    import logging
    from scrapy.http import Request
    
    from scrapy_school_insurance.items import ScrapySchoolInsuranceItem
    
    
    class SchoolInsuranceSpider(scrapy.Spider):
        name = "school_insurance"
    
        allowed_domains = ['jnjy.net.cn']
    
         # 在这里定义了登录成功后的url,供再次请求使用
        target_url = 'http://jnjybx.jnjy.net.cn/admin/index.aspx'
    
        def __init__(self, account, **kwargs):
            super(SchoolInsuranceSpider, self).__init__(**kwargs)
            self.account = account
    
        def start_requests(self):
            start_url = 'http://jnjybx.jnjy.net.cn/admin/login.aspx?doType=loginout'
    
            return [
                Request(start_url, callback=self.login)
            ]
    
        # 模拟用户登录
        def login(self, response):
                return scrapy.FormRequest.from_response(
                    response,
                    formdata={'username': '***', 'password': '***'},
                    meta={'school_id': ***},
                    callback=self.check_login
                )
    
        # 检查登录是否成功
        def check_login(self, response):
            self.logger.info(response.body)
            body_json = json.loads(response.body)
            # 获取参数
            school_id = response.meta['school_id']
            self.logger.info(school_id)
            if "ret" in body_json and body_json["ret"] != 0:
                self.logger.error("Login failed")
                return
            else:
                self.logger.info("Login Success")
                # 这里重新请求了一次
                yield scrapy.Request(self.target_url, meta={'school_id': school_id}, callback=self.find_student_manager)
    

    因为主页并不是我需要的页面,所以find_student_manager()方法作用是找到我需要的那个链接,进行请求后再进行分页爬取。

        # 检验登录成功后 跳转 学生管理连接
        def find_student_manager(self, response):
            self.logger.info(response.url)
            school_id = response.meta['school_id']
            self.logger.info(school_id)
            next_page = response.css('a[href="studentManage.aspx"]::attr(href)').extract_first()
            logging.info(next_page)
            if next_page is not None:
                self.logger.info("next_url:" + next_page)
                next_page = response.urljoin(next_page)
                self.logger.info("next_url:" + next_page)
                yield scrapy.Request(next_page, meta={'school_id': school_id})
            else:
                self.logger.error("not find href you needed")

    解析html是需要选择器的,和编写css时给页面加样式的时候操作类似。

    scrapy提供两种选择器xpath(),css();

    XPath是用来在XML中选择节点的语言,同时可以用在HTML上面。CSS是HTML文档上面的样式语言。

    css选择器语法请参考:https://www.cnblogs.com/ruoniao/p/6875227.html

    我这里使用css选择器来获取a标签的herf,分析一下这句话:

    next_page=response.css('a[href="studentManage.aspx"]::attr(href)').extract_first()

    简单来讲,.css()返回的是一个SelectorList对象,它是内建List的子类,我们并不能直接使用它得到数据。.extract()方法就是使SelectorList ——> List,变为单一化的unicode字符串列表,我们就可以直接使用了。.extract_first()顾名思义,就是取第一个值,也可写为 .extract()[0],需要注意的是list为空的时候会报异常。

    再看看这句话:

    next_page = response.urljoin(next_page)

    通过选择器获取到是一个href的字符串值,是相对url,需要使用.urljoin()方法来构建完整的绝对URL,便于再次请求。

    进入需要爬取的页面,开始分页爬取:

    # 爬取 需要 的数据
        def parse(self, response):
            school_id = response.meta['school_id']
    
            counter = 0
            # id_cards = response.css('tr[target="ID_CARD"]::attr(rel)')
            # i = 0
            view_state = response.css('input#__VIEWSTATE::attr(value)').extract_first()
            view_state_generator = response.css('input#__VIEWSTATEGENERATOR::attr(value)').extract_first()
            page_num = response.css('input[name="pageNum"]::attr(value)').extract_first()
            num_per_page = response.css('input[name="numPerPage"]::attr(value)').extract_first()
            order_field = response.css('input[name="orderField"]::attr(value)').extract_first()
            order_direction = response.css('input[name="orderDirection"]::attr(value)').extract_first()
            self.logger.info(page_num)
    
            for sel in response.css('tr[target="ID_CARD"]'):
    
                counter = counter + 1
                item = ScrapySchoolInsuranceItem()
    
                item['classroom'] = sel.css('td::text').extract()[0]
                item['id_card'] = sel.css('td::text').extract()[1]
                item['student_name'] = sel.css('td::text').extract()[2]
                item['parent_name'] = sel.css('td::text').extract()[3]
                item['phone'] = sel.css('td::text').extract()[4]
                item['is_pay'] = sel.css('span::text').extract_first()
                item['school_id'] = school_id
                yield item
    
            self.logger.info(str(counter)+" "+num_per_page)
    
            if counter == int(num_per_page):
                yield scrapy.FormRequest.from_response(
                    response,
                    formdata={'__VIEWSTATE': view_state, '__VIEWSTATEGENERATOR': view_state_generator,
                              'pageNum': str(int(page_num) + 1), 'numPerPage': num_per_page,
                              'orderField': order_field, 'orderDirection': order_direction},
                    meta={'school_id': school_id},
                    callback=self.parse
                )
    

    分析页面:

    我所需要的数据是

    的结构,且每页的结构都相同, 其中一小段html:
    <tr target="ID_CARD" rel='1301*******0226'>
             <td >初中二年级7班(南京市***中学)</td>
             <td >130**********226</td>
             <td >李**</td>
             <td >蒋**</td>
             <td >139******61</td>
             <td ><span style='color:green'>已支付</span></td>
    </tr>

    所以只需要使用选择器进行循环爬取付值给item,然后回调自己就可以把所有数据爬取下来了。

    看Chrome的请求状态,发现是post请求且有两个陌生的参数。分析页面发现有两个隐藏参数__VIEWSTATE,__VIEWSTATEGENERATOR,且每次请求都会改变。

    <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="***" />
    
    <input type="hidden" name="__VIEWSTATEGENERATOR" id="__VIEWSTATEGENERATOR" value="CCD96271" />

    ViewState是ASP.NET中用来保存WEB控件回传时状态值一种机制。__EVENTVALIDATION只是用来验证事件是否从合法的页面发送,只是一个数字签名。
    对于我们爬虫而需要做的就是,获取本页面的这两个值,在请求下一页面的时候作为参数进行请求。分页爬取需要不断回调自己进行递归,此时请求并不是get请求,而是url不变的post请求,我这是使用一个计数器counter防止其无限递归下去。

    这里你会仔细发现,一开始自定义的school_id也被加入了item中。

    前面提到,爬虫引擎会检索返回值,返回items时候会被pipelines调用,pipelines就是处理数据的类。

    四、持久化操作

    pipelines.py

    # -*- coding: utf-8 -*-
    import MySQLdb
    
    
    class ScrapySchoolInsurancePipeline(object):
    
        def process_item(self, item, spider):
    
            db_name = ""
            if item["school_id"] == '1002':
                db_name = "scrapy_school_insurance"
            elif item["school_id"] == '1003':
                db_name = "db_mcp_1003"
            if db_name != "":
                conn = MySQLdb.connect("localhost", "root", "a123", db_name, charset='utf8')
                cursor = conn.cursor()
                # 使用cursor()方法获取操作游标
                # 使用execute方法执行SQL语句
                sql = "insert into `insurance_info` " \
                      "(classroom,id_card,student,parent,phone,is_pay,school_id) " \
                      "values (%s, %s, %s, %s, %s, %s, %s)" \
                      "ON DUPLICATE KEY UPDATE is_pay = %s;"
                params = (item["classroom"], item["id_card"],
                          item["student_name"], item["parent_name"],
                          item["phone"], item["is_pay"], item["school_id"], item["is_pay"])
                cursor.execute(sql, params)
           、conn.commit()
           cursor.close()
           conn.close()
    

    process_item()方法,是pipeline默认调用的。因为需要根据school_id进行分库插入并没有进行setting设置,而是使用MySQLdb库动态链接数据库。执行sql操作和java类似。sql使用“ON DUPLICATE KEY UPDATE”去重更新。

    此时我们已经完成了三步,定义items,编写spider逻辑,pipeline持久化。
    下一步就是如何让程序正确的跑起来。

    五、运行

    谈运行,首先要说一下本案例setting.py的书写,它设计运行的方方面面。

    # -*- coding: utf-8 -*-
    
    BOT_NAME = 'scrapy_school_insurance'
    
    SPIDER_MODULES = ['scrapy_school_insurance.spiders']
    NEWSPIDER_MODULE = 'scrapy_school_insurance.spiders'
    
    # 编码格式
    FEED_EXPORT_ENCODING = 'utf-8'
    
    # Obey robots.txt rules 不遵循网络规范
    ROBOTSTXT_OBEY = False
    
    EXTENSIONS = {
        'scrapy.telnet.TelnetConsole': None
    }
    
    # 设置log级别
    # LOG_LEVEL = 'INFO'
    
    # 本项目带登陆需要开启cookies,一般爬取不需要cookie
    COOKIES_ENABLED = True
    
     'scrapy_school_insurance.middlewares.ScrapySchoolInsuranceSpiderMiddleware': 543,
     
    # 开启 后pipelines才生效 后面的数字表示的是pipeline的执行顺序
    ITEM_PIPELINES = {
       'scrapy_school_insurance.pipelines.ScrapySchoolInsurancePipeline': 300,
    }
    

    完成如上操作后,在终端中到达此项目根目录下运行:

    scrapy crawl school_insurance
    

    想生成json文件:

    scrapy crawl school_insurance -o test.json -t json

    现在我有多个账号存在数据库中,想分别登入读取信息该如何操作?

    构思了两个方案:

    1.读取所有账号,存入一个spider中,每次用一个账号爬取完后退出登录,清除cookie,再拿第二个账号登入,进行爬取工作。
    2.动态配置spider,每个账号对应一个spider,进行顺序执行。

    仅从描述上看,第二个方案就比第一个方案靠谱,可行。

    采用第二个方案,需要动态配置完之后告诉spider要运行了,也就是使用编程的方式运行spider:Scrapy是构建于Twisted异步网络框架基础之上,因此可以启动Twisted reactor并在reactor中启动spider。CrawlerRunner就会为你启动一个Twisted reactor。 需先新建一个run.py:

    #!/bin/env python
    #  -*- coding: utf-8 -*-
    import logging
    
    import MySQLdb.cursors
    from twisted.internet import reactor
    
    
    from scrapy.utils.project import get_project_settings
    from scrapy.utils.log import configure_logging
    from scrapy.crawler import CrawlerRunner
    
    import sys
    sys.path.append("../")
    from scrapy_school_insurance.spiders.school_insurance_spider import SchoolInsuranceSpider
    
    if __name__ == '__main__':
        settings = get_project_settings()
        configure_logging(settings)
        db_names = ['scrapy_school_insurance', 'db_mcp_1003']
        results = list()
        for db_name in db_names:
            logging.info(db_name)
            db = MySQLdb.connect("localhost", "root", "a123", db_name, charset='utf8',
                                 cursorclass=MySQLdb.cursors.DictCursor)
            # 使用cursor()方法获取操作游标
            cursor = db.cursor()
            # 使用execute方法执行SQL语句
            cursor.execute("select * from school_account")
            # 使用 fetchone() 方法获取一条数据
            result = cursor.fetchone()
            logging.info(result)
            results.append(result)
            db.close()
        logging.info(results)
        runner = CrawlerRunner(settings)
    
        for result in results:
            runner.crawl(SchoolInsuranceSpider, account=result)
    
        d = runner.join()
        d.addBoth(lambda _: reactor.stop())
    
        reactor.run()
    
        logging.info("all findAll")
    

    需要注意的是数据库

    获取账号信息,启动reactor,启动spider

    runner = CrawlerRunner(settings)
    
    for result in results:
        runner.crawl(SchoolInsuranceSpider, account=result)

    这句话在spider时,将账号信息作为参数传递过去了,所以我们的spider需要修改一下接收参数
    加入构造器,供内部调用:

     def __init__(self, account, **kwargs):
            super(SchoolInsuranceSpider, self).__init__(**kwargs)
            self.account = account

    此时login()可修改为:

        def login(self, response):
            return scrapy.FormRequest.from_response(
                response,
                formdata={'username': self.account['username'], 'password': self.account['password']},
                meta={'school_id': self.account['school_id']},
                callback=self.check_login
            )

    完成后在终端运行run.py即可:

    @localhost:~/project-workspace/scrapy_school_insurancescrapy_school_insurance/$ python run.py

    此时会报 not import SchoolInsuranceSpider,但是已经明明import了,因为路径的问题,run.py启动时并找不到它,需在import前加 sys.path.append("../")python才可以通过路径找到它

    最后需要做的就是定时启动python脚本:
    使用crontab
    详细语法参考:https://blog.csdn.net/netdxy/article/details/50562864

    主要是两步

    crontab -e

    添加定时任务,每天3点执行python脚本,wq,ok

    * */3 * * * python ~/project-workspace/scrapy_school_insurance/scrapy_school_insurance/run.py

    六、梳理

    Scrapy架构组件、运行流程,结合实例理解一下

    1472307-20181026161717515-1526990965.png

    posted @ 2018-10-26 16:13 王诗文 阅读(...) 评论(...) 编辑 收藏

    转载于:https://www.cnblogs.com/wangshiwen/p/9857002.html

    展开全文
  • SSM框架整合步骤思路及案例分析

    千次阅读 多人点赞 2019-06-12 19:20:06
    SSM框架整合 SSM框架整合就是分别实现Spring与SpringMVC、Spring与...搭建步骤: 1、 新建项目并导入jar文件 整体结构: java、resources文件夹创建更新(若没有),java中新建文件包后,再并列新建包: 实体类entit...
  • 因子分析模型 - 案例步骤详解 - (SPSS建模)

    万次阅读 多人点赞 2018-10-29 09:52:04
    一、SPSS中的因子分析。 具体操作步骤: (1)定义变量:x1-财政用于农业的支出的比重,x2-第二、三产业从业人数占全社会从业人数的比重,x3-非农村人口比重,x4-乡村从业人员占农村人口的比重,x5-农业总产值占农林牧...
  • 步骤分析: 第一步:先定义一个大的 div(整个页面),然后嵌套 8 个小的 div(共八行); 第二步:(第一行)在第一个 div 里面嵌套 3 个小的 div; 第三步:(第二行)在小 div 里面写一个列表标签(需要使用 ...
  • 显示译码器是数字电子技术组合逻辑电路中一个很重要的器件,在数字电子技术应用中不可缺少,特别是在信息技术数字化的今天,...总是对如何准确设计出符合功能要求的显示译码器胸中无数,本文对此问题进行了分析与研究。
  • 显示译码器是数字电子技术组合逻辑电路中一个很重要的器件,在数字电子技术应用中不可缺少,特别是在信息技术数字化的今天,...总是对如何准确设计出符合功能要求的显示译码器胸中无数,本文对此问题进行了分析与研究。
  • 步骤三深入访谈 1确定深入访谈的对象主要是该职务的实际担任者对调查人员了解职务信息最为直接详尽其次应选择职工中的典型 2根据初步的调查了解和所应收集的职务分析信息要求制定较为详细的结构化访谈提纲 3第一次...
  • 文章目录 案例介绍 数据预处理 ...按照正常的案例分析步骤进行操作,此次为了凸显程序效果会加上许多绘图效果。 数据预处理 导入Python库与所需数据集: import pandas as pd import matplotlib...
  • 第一节 主成分分析方法 主成分分析的基本原理 主成分分析的计算步骤 主成分分析方法应用实例 地理系统是多要素的复杂系统在地理学研究中多变量问题是经常会遇到的变量太多无疑会增加分析问题的难度与复杂性而且在...
  • 其应用越来越广泛,但在组织开展科技创新和电子设计制作竞赛活动中,学生在设计制作抢答器、记分器、记时器等电子产品时,总是对如何准确设计出符合功能要求的显示译码器胸中无数,本文对此问题进行了分析与研究。...
  • 数据分析步骤

    2021-01-19 11:13:56
    案例了解数据分析步骤 https://zhuanlan.zhihu.com/p/136819457
  • JavaWeb_文件上传案例_总体步骤分析文件上传案例_总体步骤分析 文件上传案例_总体步骤分析 1.FileUploadServlet.java package com.xs.fileupload.app.servlet; import java.io.File; import java.io.IOException;...
  • 在练习林子雨老师的“淘宝双11数据分析与预测课程案例步骤四:利用Spark预测回头客行为”章节时出现了代码报错。具体在执行"val model = SVMWithSGD.train(train, numIterations)"代码后出现了如下报错:...
  • SPSS因子分析案例

    万次阅读 多人点赞 2018-01-14 20:43:40
    一、SPSS中的因子分析。 具体操作步骤: (1)定义变量:x1-财政用于农业的支出的比重,x2-第二、三产业从业人数占全社会从业人数的比重,x3-非农村人口比重,x4-乡村从业人员占农村人口的比重,x5-农业总产值占农林牧...
  • 当使用计算机来解决一个具体问题时,一般需要经过如下几个步骤:首先要从该具体问题抽象出一个适当的数学模型,然后设计或选择一个求解此数学模型的算法,最后编出程序进行调试、测试,得到最终的答案。例如,用...
  • 论文研究- 案例分析——决策分析讲座(四).pdf, §4.1 分析步骤及其框图 以前的几讲已对决策分析作了一般介绍,本讲将列举一案例并系统地作一分析。案例及其数据都是虚拟的。 在案例分析中,我们把分析的步骤区分为三...
  • 现在用 Python 写线性回归的博客都快烂大街了,为什么还要用 SPSS 做线性回归呢?这就来说说 SPSS 存在的原因吧。...SPSS 做因子分析,输出结果中有一项 Kaiser-Meyer-Olkin Measure of Sampling Ade...
  • 分析 根据需求,首先定义以下3大要素 采集源,即source——监控文件内容更新 : exec ‘tail -F file’ 下沉目标,即sink——HDFS文件系统 : hdfs sink Source和sink之间的传递通道——channel,可...
  • BootStrap网页案例开发步骤

    千次阅读 2016-11-29 23:18:23
    基于BootStrap网页开发案例简介强大的前端响应式布局开发框架 主要文件:css、js、fonts1.收集网页所需要的素材-文字,图片 *下载bootstrap框架 ^从官方文档copy基本网页结构:basic template2.按照demo分析页面...
  • 模型及案例分析.pdf

    2019-12-28 10:36:50
    SWOT 模型及案例解说 SWOT 分析模型 SWOT Analysis SWOT 分析法 也称TOWS 分析法 道斯矩阵 即态势分析法 20 世纪 80 年代初...2 SWOT 模型含义介绍 3 SWOT 分析模型的方法 [1] 4 SWOT 分析步骤 5 成功应用 SWOT 分析法
  • 读入数据总结Adventure Works Cycles案例分析前言一、项目背景介绍二、使用步骤1.引入库2.读入数据总结 前言 提示:这里可以添加本文要记录的大概内容: 例如:随着人工智能的不断发展,机器学习这门技术也越来越...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,162
精华内容 1,664
关键字:

案例分析步骤