Python教程笔记

第一章 计算机基础知识

课程介绍

计算机是什么

在现实生活中,越来越无法离开计算机了
    电脑、笔记本、手机、游戏机、汽车导航、智能电视 。。。
计算机就是一个用来计算的机器!
目前来讲,计算机只能根据人类的指令来完成各种操作,人让它干嘛他就得干嘛
所以我们学习计算机,就是学习如何控制计算机!

计算机的组成

计算机由两部分组成:硬件 和 软件
硬件包含:键盘、鼠标、显示器、CPU、主板、内存、硬盘 。。。
    硬件是看的见摸得着的
软件包含:系统软件(windows、macOS、Linux)和应用软件(office 、QQ、绝地求生)
    软件是看的见摸不着的,软件负责控制计算机中的硬件    

计算机的使用方式

我们必须要通过软件来对计算机完成各种操作,
    但是注意,软件中并不是所有的功能都会对用户开放,
        用户需要调用软件提供的接口(Interface 交互界面)来操作计算机

用户界面分成两种:TUI(文本交互界面)和 GUI(图形化交互界面)

windows的命令行

命令行就是文本交互界面,通过命令行可以使用一个一个的指令来操作计算机
任何的计算机的操作系统中都包含有命令行(windows、linux、macOS)
命令行有多个不同的名字:
    命令行、命令行窗口、DOS窗口、命令提示符、CMD窗口、Shell、终端、Terminal
    练习1:
        通过搜索引擎来搜索一下,各个操作系统当中的命令行窗口的样式

1.如何进入到命令行
    win键 + R 出现运行窗口,输入cmd,然后回车
2.命令行的结构
    - 版本及版权声明(一般没有什么用)
        Microsoft Windows [版本 10.0.16299.431]
        (c) 2017 Microsoft Corporation。保留所有权利。

    - 命令提示符
        C:\Users\lilichao>  
            C:  
                - 当前所在的磁盘根目录
                - 可以通过 x: 来切换盘符(x表示你的盘符)

            \Users\lilichao
                - 所在磁盘的路径,当前所在的文件夹
                - cd 来切换目录
            >
                - 命令提示符,在大于号后边可以直接输入指令

    练习2:尝试使用多种方式进入到你的系统的命令行,并且观察你的和我的有什么区别? 

3.常用的dos命令
    dir 查看当前目录下的所有文件(夹)
    cd 进入到指定的目录
        . 表示当前目录
        .. 表示上一级目录
    md 创建一个目录
    rd 删除一个目录    
    del 删除一个文件
    cls 清除屏幕

    命令的语法
        命令 [参数] [选项]

    练习3:通过搜索引擎搜索一下其他的一些常用DOS命令,并尝试使用一些命令的选项    

4.小技巧
    - 方向键上下,查看命令的历史记录
    - tab键自动补全命令        

环境变量(environment variable)

环境变量指的就是操作系统当中的一些变量。
可以通过修改环境变量,来对计算机进行配置(主要是来配置一些路径的)
1.查看环境变量
    > 右键 计算机(此电脑),选择属性
    > 系统界面左侧选择 高级系统设置
    > 选择环境变量
    环境变量界面分成了两个部分,上边是用户环境变量,下边是系统环境变量
        建议只修改用户的环境变量,不要修改系统的环境变量

2.添加环境变量
    > 通过新建按钮添加环境变量
    > 一个环境变量可以由多个值,值与值之间使用;(英文)隔开

3.修改环境变量
    > 通过编辑按钮来修改环境变量

4.删除环境变量
    > 通过删除按钮来删除环境变量

练习4:进入到环境变量的界面,创建一个USERNAME环境变量,
    修改USERNAME环境变量,并尝试添加多个值,然后删除USERNAME环境变量    

path环境变量

path环境变量中保存的是一个一个的路径。
当我们在命令行中输入一个命令(或访问一个文件时),
    系统会首先在当前目录下寻找,如果找到了则直接执行或打开
    如果没有找到,则会依次去path环境变量的路径中去寻找,直到找到为止
    如果path环境变量中的路径都没有找到,则报错
        'xxx' 不是内部或外部命令,也不是可运行的程序或批处理文件。
我们可以将一些经常需要访问到的文件会程序的路径,添加到path环境变量中,
    这样我们就可以在任意的位置访问到这些文件了

注意事项:
    1.如果环境变量中没有path,可以手动添加
    2.path环境变量不区分大小写 PATH Path path   
    3.修改完环境变量必须重新启动命令行窗口
    4.多个路径之间使用;隔开

练习5:在桌面创建一个hello文件夹,文件中创建一个abc.txt输入随意的内容
        然后将hello的路径添加到path环境变量中,尝试在任意位置访问abc.txt
        最后将hello路径从path环境变量中删除。             

进制

- 十进制(最常用的进制)
    - 十进制就是满十进一的进制
    - 十进制当中一共有10个数字
        0 1 2 3 4 5 6 7 8 9
    - 十进制如何计数
        0 1 2 3 4 5 6 7 8 9 10 11 12 。。。 19 20 。。。29 30

- 二进制(计算机底层使用的进制)
    - 满二进一
    - 二进制中一共有2个数字
        0 1
    - 二进制如何计数
        0 1 10 11 100 101 110 111 1000
    - 所有的数据在计算机底层都是以二进制的形式保存的,计算机只认二进制
    - 可以将内存想象为一个一个的小格子,小格子中可以存储一个0或一个1
    - 内存中的每一个小格子,我们称为1bit(位)    
        bit是计算机中的最小的单位
        byte是我们最小的可操作的单位
        8bit = 1byte(字节)    
        1024byte = 1kb(千字节) 
        1024kb = 1mb(兆字节)
        1024mb = 1gb(吉字节)
        1024gb = 1tb(太字节)
        。。。


- 八进制(一般不用)
    - 满八进一
    - 八进制中一共有8个数字
        0 1 2 3 4 5 6 7
    - 八进制如何计数
        0 1 2 3 4 5 6 7 10 11 。。。 17 20 。。。27 30

- 十六进制
    - 满十六进一
    - 十六进制中一共有16个数字
        由于十六进制是满16才进位,
            所以十六进制中引入了a b c d e f来表示 10 11 12 13 14 15   
        0 1 2 3 4 5 6 7 8 9 a b c d e f 
    - 十六进制如何计数    
        0 1 2 3 4 5 6 7 8 9 a b c d e f 10 11 12 。。。 1a 1b 1c 1d 1e 1f
        20 21 22 。。。 2a 2b 2c 2d 2e 2f 30    
    - 我们在查看二进制数据时,一般会以十六进制的形式显示

文本文件和字符集

- 文本分成两种,一种叫做纯文本,还有一种叫做富文本
- 纯文本中只能保存单一的文本内容,无法保存内容无关的东西(字体、颜色、图片。。。)
- 富文本中可以保存文本以外的内容(word文档)
- 在开发时,编写程序使用的全都是纯文本!
- 纯文本在计算机底层也会转换为二进制保存,
    将字符转换为二进制码的过程,我们称为编码
    将二进制码转换为字符的过程,我们称为解码
    编码和解码时所采用的规则,我们称为字符集
- 常见的字符集:
    ASCII
        - 美国人编码,使用7位来对美国常用的字符进行编码
        - 包含128个字符
    ISO-8859-1
        - 欧洲的编码,使用8位
        - 包含256个字符
    GB2312
    GBK
        国标码,中国的编码
    Unicode   
        万国码,包含世界上所有的语言和符号,编写程序时一般都会使用Unicode编码
        Unicode编码有多种实现,UTF-8 UTF-16 UTF-32
        最常用的就是UTF-8
- 乱码
    编写程序时,如果发现程序代码出现乱码的情况,就要马上去检查字符集是否正确        

Sublime Text 3

- 纯文本编辑器
- Package Control(Sublime的包管理器)
    - Sublime Text3中的插件,通过该插件可以向Sublime中安装新的包
- 练习:
    1.安装Sublime Text3
    2.在Sublime中安装Package Control
    3.通过Package Control安装Sublime的中文语言包   
    4.尝试为你的Sublime安装新的主题(通过搜索引擎搜索) 

第二章 Python入门

什么是计算机语言

计算机就是一台用来计算机的机器,人让计算机干什么计算机就得干什么!
需要通过计算机的语言来控制计算机(编程语言)!
计算机语言其实和人类的语言没有本质的区别,不同点就是交流的主体不同!
计算机语言发展经历了三个阶段:
    机器语言
        - 机器语言通过二进制编码来编写程序
        - 执行效率好,编写起来太麻烦

    符号语言(汇编)
        - 使用符号来代替机器码
        - 编写程序时,不需要使用二进制,而是直接编写符号
        - 编写完成后,需要将符号转换为机器码,然后再由计算机执行
            符号转换为机器码的过程称为汇编
        - 将机器码转换为符号的过程,称为反汇编  
        - 汇编语言一般只适用于某些硬件,兼容性比较差  

    高级语言
        - 高级语言的语法基本和现在英语语法类似,并且和硬件的关系没有那么紧密了
        - 也就是说我们通过高级语言开发程序可以在不同的硬件系统中执行
        - 并且高级语言学习起来也更加的容易,现在我们知道的语言基本都是高级语言
        - C、C++、C#、Java、JavaScript、Python 。。。

编译型语言和解释型语言

计算机只能识别二进制编码(机器码),所以任何的语言在交由计算机执行时必须要先转换为机器码,
    也就是像 print('hello') 必需要转换为类似 1010101 这样的机器码   

根据转换时机的不同,语言分成了两大类:
    编译型语言
        - C语言
        - 编译型语言,会在代码执行前将代码编译为机器码,然后将机器码交由计算机执行
        - a(源码) --编译--> b(编译后的机器码)
        - 特点:
            执行速度特别快
            跨平台性比较差

    解释型语言 
        - Python JS Java
        - 解释型语言,不会在执行前对代码进行编译,而是在执行的同时一边执行一边编译
        - a(源码)--解释器--> 解释执行  
        - 特点:
            执行速度比较慢
            跨平台性比较好   

Python的介绍

Python是解释型语言

Python(英国发音:/ˈpaɪθən/ 美国发音:/ˈpaɪθɑːn/),是一种广泛使用的高级编程语言,属于通用型编程语言,由吉多·范罗苏姆创造,第一版发布于1991年。可以视之为一种改良(加入一些其他编程语言的优点,如面向对象)的LISP。作为一种解释型语言,Python的设计哲学强调代码的可读性和简洁的语法(尤其是使用空格缩进划分代码块,而非使用大括号或者关键词)。相比于C++或Java,Python让开发者能够用更少的代码表达想法。不管是小型还是大型程序,该语言都试图让程序的结构清晰明了。 

Life is short you need Python (人生苦短,我用Python)    

Python的用途:
    WEB应用
        Facebook 豆瓣 。。。
    爬虫程序
    科学计算
    自动化运维
    大数据(数据清洗)
    云计算
    桌面软件/游戏
    人工智能
    。。。     

Python开发环境搭建

开发环境搭建就是安装Python的解释器
Python的解释器分类:
    CPython(官方)
        用c语言编写的Python解释器
    PyPy
        用Python语言编写的Python解释器
    IronPython
        用.net编写的Python解释器
    Jython
        用Java编写的Python解释器

步骤:
    1.下载安装包 python-3.6.5.exe
        - 3.x
        - 2.x    
    2.安装(傻瓜式安装) 
    3.打开命令行窗口,输入python 出现如下内容
        Python 3.6.5 (v3.6.5:f59c0932b4, Mar 28 2018, 16:07:46) [MSC v.1900 32 bit (Intel)] on win32
        Type "help", "copyright", "credits" or "license" for more information.
        >>>    

Python的交互界面

当我们通过命令行来输入Python,所进入到的界面就是Python的交互界面
结构:
    版本和版权声明:
    Python 3.6.5 (v3.6.5:f59c0932b4, Mar 28 2018, 16:07:46) [MSC v.1900 32 bit (Intel)] on win32
    Type "help", "copyright", "credits" or "license" for more information.

    命令提示符:
    >>>

    在命令提示符后可以直接输入Python的指令!输入完的指令将会被Python的解释器立即执行!

    安装Python的同时,会自动安装一个Python的开发工具IDLE,通过IDLE也可以进入到交互模式
    但是不同的是,在IDLE中可以通过TAB键来查看语句的提示。
    IDLE实际上就是一个交互界面,但是他可以有一些简单的提示,并且可以将代码保存

交互模式只能你输入一行代码,它就是执行一行,所以他并不适用于我们日常的开发! 
    仅可以用来做一些日常的简单的测试!   

我们一般会将Python代码编写到一个py文件中,然后通过python指令来执行文件中的代码

练习:
    自己尝试创建一个py文件,并向文件中写入python打印语句(print...) 
        然后执行该文件。
    如果你的系统的扩展名无法修改,请尝试自行baidu!

Python和Sublime的整合

1.在Sublime中执行Python代码,ctrl + b 自动在Sublime内置的控制台中执行  
    这种执行方式,在某些版本的Sublime中对中文支持不好,并且不能使用input()函数

2.使用SublimeREPL来运行python代码    
    安装完成,设置快捷键,希望按f5则自动执行当前的Python代码
    { "keys": ["f5"], "caption": "SublimeREPL:Python","command": "run_existing_window_command", "args":{"id": "repl_python_run","file": "config/Python/Main.sublime-menu"}},

几个概念

1.表达式
    表达式就是一个类似于数学公式的东西
    比如:10 + 5   8 - 4
    表达式一般仅仅用了计算一些结果,不会对程序产生实质性的影响
    如果在交互模式中输入一个表达式,解释器会自动将表达式的结果输出

2.语句
    在程序中语句一般需要完成某种功能,比如打印信息、获取信息、为变量赋值。。。
    比如:
        print()
        input()
        a = 10
    语句的执行一般会对程序产生一定的影响
    在交互模式中不一定会输出语句的执行结果  

3.程序(program)
    程序就是由一条一条的语句和一条一条的表达式构成的。

4.函数(function)
    函数就是一种语句,函数专门用来完成特定的功能
    函数长的形如:xxx()          
    函数的分类:
        内置函数
            - 由Python解释器提供的函数,可以在Python中直接使用
        自定义函数   
            - 由程序员自主的创建的函数
    当我们需要完成某个功能时,就可以去调用内置函数,或者自定义函数 
    函数的两个要素:
        参数
            - ()中的内容就是函数的参数
            - 函数中可以没有参数,也可以有多个参数,多个参数之间使用,隔开
        返回值        
            - 返回值是函数的返回结果,不是所有的函数都有返回值

基本语法

1.在Python中严格区分大小写
2.Python中的每一行就是一条语句,每条语句以换行结束
3.Python中每一行语句不要过长(规范中建议每行不要超过80个字符)
    "rulers":[80],
4.一条语句可以分多行编写,多行编写时语句后边以\结尾  
5.Python是缩进严格的语言,所以在Python中不要随便写缩进  
6.在Python中使用#来表示注释,#后的内容都属于注释,注释的内容将会被解释器所忽略
    我们可以通过注释来对程序进行解释说明,一定要养成良好的编写注释的习惯
    注释要求简单明了,一般习惯上#后边会跟着一个空格

字面量和变量

字面量就是一个一个的值,比如:1,2,3,4,5,6,‘HELLO’
    字面量所表示的意思就是它的字面的值,在程序中可以直接使用字面量

变量(variable)变量可以用来保存字面量,并且变量中保存的字面量是不定的
    变量本身没有任何意思,它会根据不同的字面量表示不同的意思

一般我们在开发时,很少直接使用字面量,都是将字面量保存到变量中,通过变量来引用字面量

变量和标识符

数据类型

数据类型指的就是变量的值得类型,也就是可以为变量赋哪些值 
数值
    整型
        布尔值
    浮点型
    复数
字符串
空值

类型检查

对象(object)

- Python是一门面向对象的语言
- 一切皆对象!
- 程序运行当中,所有的数据都是存储到内存当中然后再运行的!
- 对象就是内存中专门用来存储指定数据的一块区域
- 对象实际上就是一个容器,专门用来存储数据
- 像我们之前学习的数值、字符串、布尔值、None都是对象
- 参考 图1

对象的结构

- 每个对象中都要保存三种数据
    - id(标识)
        > id用来标识对象的唯一性,每一个对象都有唯一的id
        > 对象的id就相当于人的身份证号一样
        > 可以通过id()函数来查看对象的id
        > id是由解析器生成的,在CPython中,id就是对象的内存地址
        > 对象一旦创建,则它的id永远不能再改变

    - type(类型)
        > 类型用来标识当前对象所属的类型
        > 比如:int str float bool 。。。
        > 类型决定了对象有哪些功能
        > 通过type()函数来查看对象的类型
        > Python是一门强类型的语言,对象一旦创建类型便不能修改


    - value(值)
        > 值就是对象中存储的具体的数据
        > 对于有些对象值是可以改变的
        > 对象分成两大类,可变对象 不可变对象
            可变对象的值可以改变
            不可变对象的值不能改变,之前学习的对象都是不可变对象
    - 参考 图2

练习:尝试自己画一下对象的内存结构。  

变量和对象

- 对象并没有直接存储到变量中,在Python中变量更像是给对象起了一个别名
- 变量中存储的不是对象的值,而是对象的id(内存地址),
    当我们使用变量时,实际上就是在通过对象id在查找对象
- 变量中保存的对象,只有在为变量重新赋值时才会改变
- 变量和变量之间是相互独立的,修改一个变量不会影响另一个变量

- 参考 图3

类型转换

- 所谓的类型转换,将一个类型的对象转换为其他对象
- 类型转换不是改变对象本身的类型,而是根据当前对象的值创建一个新对象

运算符(操作符)

- 运算符可以对一个值或多个值进行运算或各种操作
- 比如 + 、-、= 都属于运算符
- 运算符的分类:
    1.算术运算符
    2.赋值运算符
    3.比较运算符(关系运算符)
    4.逻辑运算符
    5.条件运算符(三元运算符)    

第三章 流程控制语句

简介

Python代码在执行时是按照自上向下顺序执行的。
通过流程控制语句,可以改变程序的执行顺序,也可以让指定的程序反复执行多次
流程控制语句分成两大类:条件判断语句,循环语句

条件判断语句(if语句)

练习1:
    编写一个程序,获取一个用户输入的整数。然后通过程序显示这个数是奇数还是偶数。

练习2:
    编写一个程序,检查任意一个年份是否是闰年。
    如果一个年份可以被4整除不能被100整除,或者可以被400整除,这个年份就是闰年

练习3:
    我家的狗5岁了,5岁的狗相当于多大年龄的人呢?
    其实非常简单,狗的前两年每一年相当于人类的10.5岁,然后每增加一年就增加四岁。
    那么5岁的狗相等于人类的年龄就应该是10.5+10.5+4+4+4 = 33岁 

    编写一个程序,获取用户输入的狗的年龄,然后通过程序显示其相当于人类的年龄。
    如果用户输入负数,请显示一个提示信息

练习4:
    从键盘输入小明的期末成绩:
        当成绩为100时,'奖励一辆BMW'
        当成绩为[80-99]时,'奖励一台iphone'
        当成绩为[60-79]时,'奖励一本参考书'
        其他时,什么奖励也没有

练习5:
    大家都知道,男大当婚,女大当嫁。那么女方家长要嫁女儿,当然要提出一定的条件:
        高:180cm以上; 富:1000万以上; 帅:500以上;
        如果这三个条件同时满足,则:'我一定要嫁给他'
        如果三个条件有为真的情况,则:'嫁吧,比上不足,比下有余。'
        如果三个条件都不满足,则:'不嫁!'

循环语句

练习1:
    求100以内所有的奇数之和

练习2:
    求100以内所有7的倍数之和,以及个数

练习3: 
    水仙花数是指一个 n 位数(n≥3 ),它的每个位上的数字的 n 次幂之和等于它本身(例如:1**3 + 5**3 + 3**3 = 153)。
    求1000以内所有的水仙花数

练习4:    
    获取用户输入的任意数,判断其是否是质数。质数是只能被1和它自身整除的数,1不是质数也不是合数。

循环嵌套

练习1:
    打印99乘法表
    1*1=1
    1*2=2 2*2=4
    1*3=3 2*3=6 3*3=9
    ...                 9*9=81

练习2:
    求100以内所有的质数

小游戏 《唐僧大战白骨精》

1、身份选择
    ① 显示提示信息
        欢迎光临 xxx 游戏!
        请选择你的身份:
            1.xxx
            2.xxx
        请选择:x
    ② 根据用户选择来分配身份(显示不同的提示消息)  
        1.---
        2.---
        3.---  

2、游戏进行
    ① 显示玩家的基本信息(攻击力 生命值)
    ② 显示玩家可以进行的操作:
        1、练级
            - 提升玩家的攻击力和生命值
        2、打BOSS
            - 玩家对BOSS进行攻击,玩家要攻击BOSS,BOSS对玩家进行反击
            - 计算BOSS是否被玩家消灭,玩家是否被BOSS消灭
            - 游戏结束
        3、逃跑
            - 退出游戏,显示提示信息,游戏结束!

第四章 序列

列表(list)

- 列表是Python中的一个对象
- 对象(object)就是内存中专门用来存储数据的一块区域
- 之前我们学习的对象,像数值,它只能保存一个单一的数据
- 列表中可以保存多个有序的数据
- 列表是用来存储对象的对象
- 列表的使用:
    1.列表的创建
    2.操作列表中的数据

- 练习:
    - 创建一个列表,在列表中保存你最好的5个朋友的名字
        然后分别通过索引来获取每一个朋友的名字

序列(sequence)

- 序列是Python中最基本的一种数据结构
- 数据结构指计算机中数据存储的方式
- 序列用于保存一组有序的数据,所有的数据在序列当中都有一个唯一的位置(索引)
    并且序列中的数据会按照添加的顺序来分配索引
- 序列的分类:
    可变序列(序列中的元素可以改变):
        > 列表(list)
    不可变序列(序列中的元素不能改变):
        > 字符串(str)    
        > 元组(tuple)
    - 刚刚我们所讲所有操作都是序列的通用操作01 02 03 三个文件中的操作

EMS(Employee Manager System 员工管理系统) 练习

- 做命令行版本的员工管理系统
- 功能:
    四个:
        1.查询
            - 显示当前系统当中的所有员工
        2.添加
            - 将员工添加到当前系统中
        3.删除
            - 将员工从系统当中删除
        4.退出
            - 退出系统
- 员工信息要保存到哪里? 列表,在系统中应该有一个列表,专门用来保存所有员工信息的 

可变对象

- 每个对象中都保存了三个数据:
    id(标识)
    type(类型)
    value(值)    

- 列表就是一个可变对象
    a = [1,2,3]

- a[0] = 10 (改对象)
    - 这个操作是在通过变量去修改对象的值
    - 这种操作不会改变变量所指向的对象    
    - 当我们去修改对象时,如果有其他变量也指向了该对象,则修改也会在其他的变量中体现

- a = [4,5,6] (改变量)
    - 这个操作是在给变量重新赋值
    - 这种操作会改变变量所指向的对象
    - 为一个变量重新赋值时,不会影响其他的变量

- 一般只有在为变量赋值时才是修改变量,其余的都是修改对象

字典(dict)

- 字典属于一种新的数据结构,称为映射(mapping)
- 字典的作用和列表类似,都是用来存储对象的容器
- 列表存储数据的性能很好,但是查询数据的性能的很差
- 在字典中每一个元素都有一个唯一的名字,通过这个唯一的名字可以快速的查找到指定的元素
- 在查询元素时,字典的效率是非常快的
- 在字典中可以保存多个对象,每个对象都会有一个唯一的名字
    这个唯一的名字,我们称其为键(key),通过key可以快速的查询value
    这个对象,我们称其为值(value)
    所以字典,我们也称为叫做键值对(key-value)结构
    每个字典中都可以有多个键值对,而每一个键值对我们称其为一项(item)

集合(set)

- 集合和列表非常相似
- 不同点:
    1.集合中只能存储不可变对象
    2.集合中存储的对象是无序(不是按照元素的插入顺序保存)
    3.集合中不能出现重复的元素

第五章 函数

函数简介(function)

- 函数也是一个对象
- 对象是内存中专门用来存储数据的一块区域
- 函数可以用来保存一些可执行的代码,并且可以在需要时,对这些语句进行多次的调用
- 创建函数:
    def 函数名([形参1,形参2,...形参n]) :
        代码块
    - 函数名必须要符号标识符的规范
        (可以包含字母、数字、下划线、但是不能以数字开头)    
- 函数中保存的代码不会立即执行,需要调用函数代码才会执行
- 调用函数:
    函数对象()
- 定义函数一般都是要实现某种功能的    

函数的参数

- 在定义函数时,可以在函数名后的()中定义数量不等的形参,
    多个形参之间使用,隔开
- 形参(形式参数),定义形参就相当于在函数内部声明了变量,但是并不赋值
- 实参(实际参数)
    - 如果函数定义时,指定了形参,那么在调用函数时也必须传递实参,
        实参将会赋值给对应的形参,简单来说,有几个形参就得传几个实参

- 练习1:
    定义一个函数,可以用来求任意三个数的乘积

- 练习2:
    定义一个函数,可以根据不同的用户名显示不同的欢迎信息    

函数式编程

- 在Python中,函数是一等对象
- 一等对象一般都会具有如下特点:
    ① 对象是在运行时创建的
    ② 能赋值给变量或作为数据结构中的元素
    ③ 能作为参数传递
    ④ 能作为返回值返回
    
- 高阶函数
    - 高阶函数至少要符合以下两个特点中的一个
      ① 接收一个或多个函数作为参数
      ② 将函数作为返回值返回 

- 装饰器         

第六章 对象(Object)

什么是对象?

- 对象是内存中专门用来存储数据的一块区域。
- 对象中可以存放各种数据(比如:数字、布尔值、代码)
- 对象由三部分组成:
    1.对象的标识(id)
    2.对象的类型(type)
    3.对象的值(value)

面向对象(oop)

- Python是一门面向对象的编程语言
- 所谓的面向对象的语言,简单理解就是语言中的所有操作都是通过对象来进行的
- 面向过程的编程的语言
    - 面向过程指将我们的程序的逻辑分解为一个一个的步骤,
        通过对每个步骤的抽象,来完成程序
    - 例子:
        - 孩子上学
            1.妈妈起床
            2.妈妈上厕所
            3.妈妈洗漱
            4.妈妈做早饭
            5.妈妈叫孩子起床
            6.孩子上厕所
            7.孩子要洗漱
            8.孩子吃饭
            9.孩子背着书包上学校

    - 面向过程的编程思想将一个功能分解为一个一个小的步骤,
        我们通过完成一个一个的小的步骤来完成一个程序
    - 这种编程方式,符合我们人类的思维,编写起来相对比较简单
    - 但是这种方式编写代码的往往只适用于一个功能,
        如果要在实现别的功能,即使功能相差极小,也往往要重新编写代码,
        所以它可复用性比较低,并且难于维护 

- 面向对象的编程语言
    - 面向对象的编程语言,关注的是对象,而不关注过程 
    - 对于面向对象的语言来说,一切都是对象       
    - 例子:
        1.孩他妈起床叫孩子上学

    - 面向对象的编程思想,将所有的功能统一保存到对应的对象中
        比如,妈妈功能保存到妈妈的对象中,孩子的功能保存到孩子对象中
        要使用某个功能,直接找到对应的对象即可
    - 这种方式编写的代码,比较容易阅读,并且比较易于维护,容易复用。
    - 但是这种方式编写,不太符合常规的思维,编写起来稍微麻烦一点 

- 简单归纳一下,面向对象的思想
    1.找对象
    2.搞对象

类(class)

- 我们目前所学习的对象都是Python内置的对象
- 但是内置对象并不能满足所有的需求,所以我们在开发中经常需要自定义一些对象
- 类,简单理解它就相当于一个图纸。在程序中我们需要根据类来创建对象
- 类就是对象的图纸!
- 我们也称对象是类的实例(instance)
- 如果多个对象是通过一个类创建的,我们称这些对象是一类对象
- 像 int() float() bool() str() list() dict() .... 这些都是类
- a = int(10) # 创建一个int类的实例 等价于 a = 10
- 我们自定义的类都需要使用大写字母开头,使用大驼峰命名法(帕斯卡命名法)来对类命名

- 类也是一个对象!
- 类就是一个用来创建对象的对象!
- 类是type类型的对象,定义类实际上就是定义了一个type类型的对象

使用类创建对象的流程

1.创建一个变量
2.在内存中创建一个新对象
3.将对象的id赋值给变量

类的定义

- 类和对象都是对现实生活中的事物或程序中的内容的抽象
- 实际上所有的事物都由两部分构成:
    1.数据(属性)
    2.行为(方法)

- 在类的代码块中,我们可以定义变量和函数,
    变量会成为该类实例的公共属性,所有的该类实例都可以通过 对象.属性名 的形式访问 
    函数会成为该类实例的公共方法,所有该类实例都可以通过 对象.方法名() 的形式调用方法

- 注意:
    方法调用时,第一个参数由解析器自动传递,所以定义方法时,至少要定义一个形参! 

- 实例为什么能访问到类中的属性和方法
    类中定义的属性和方法都是公共的,任何该类实例都可以访问

    - 属性和方法查找的流程
        当我们调用一个对象的属性时,解析器会先在当前对象中寻找是否含有该属性,
            如果有,则直接返回当前的对象的属性值,
            如果没有,则去当前对象的类对象中去寻找,如果有则返回类对象的属性值,
            如果类对象中依然没有,则报错!

    - 类对象和实例对象中都可以保存属性(方法)
        - 如果这个属性(方法)是所有的实例共享的,则应该将其保存到类对象中
        - 如果这个属性(方法)是某个实例独有,则应该保存到实例对象中     
        
    - 一般情况下,属性保存到实例对象中
        而方法需要保存到类对象中    

创建对象的流程

p1 = Person()的运行流程
    1.创建一个变量
    2.在内存中创建一个新对象
    3.__init__(self)方法执行
    4.将对象的id赋值给变量

类的基本结构

class 类名([父类]) :

    公共的属性... 

    # 对象的初始化方法
    def __init__(self,...):
        ...

    # 其他的方法    
    def method_1(self,...):
        ...

    def method_2(self,...):
        ...

    ...    

- 练习:
    尝试自定义一个表示狗的类(Dog)      
        属性:
            name
            age
            gender
            height
            ...
        方法:  
            jiao()
            yao()
            run()
            ...

第七章 异常和文件

异常

程序在运行过程当中,不可避免的会出现一些错误,比如:
    使用了没有赋值过的变量
    使用了不存在的索引
    除0
    ...
这些错误在程序中,我们称其为异常。
程序运行过程中,一旦出现异常将会导致程序立即终止,异常以后的代码全部都不会执行!    

处理异常

程序运行时出现异常,目的并不是让我们的程序直接终止!
Python是希望在出现异常时,我们可以编写代码来对异常进行处理!    

try语句
    try:
        代码块(可能出现错误的语句)
    except 异常类型 as 异常名:
        代码块(出现错误以后的处理方式)
    except 异常类型 as 异常名:
        代码块(出现错误以后的处理方式)
    except 异常类型 as 异常名:
        代码块(出现错误以后的处理方式)
    else:
        代码块(没出错时要执行的语句)    
    finally:
        代码块(该代码块总会执行)    

    try是必须的 else语句有没有都行
    except和finally至少有一个    

可以将可能出错的代码放入到try语句,这样如果代码没有错误,则会正常执行,
    如果出现错误,则会执行expect子句中的代码,这样我们就可以通过代码来处理异常
    避免因为一个异常导致整个程序的终止            

异常的传播(抛出异常)

当在函数中出现异常时,如果在函数中对异常进行了处理,则异常不会再继续传播,
    如果函数中没有对异常进行处理,则异常会继续向函数调用处传播,
    如果函数调用处处理了异常,则不再传播,如果没有处理则继续向调用处传播
    直到传递到全局作用域(主模块)如果依然没有处理,则程序终止,并且显示异常信息

当程序运行过程中出现异常以后,所有的异常信息会被保存一个专门的异常对象中,
    而异常传播时,实际上就是异常对象抛给了调用处
    比如 : ZeroDivisionError类的对象专门用来表示除0的异常
            NameError类的对象专门用来处理变量错误的异常
            ....

在Python为我们提供了多个异常对象            

抛出异常

- 可以使用 raise 语句来抛出异常,
    raise语句后需要跟一个异常类 或 异常的实例

文件(File)

- 通过Python程序来对计算机中的各种文件进行增删改查的操作
- I/O(Input / Output)
- 操作文件的步骤:
    ① 打开文件
    ② 对文件进行各种操作(读、写),然后保存
    ③ 关闭文件

Python基础:

**

二、****pip****的使用**

pip是一个现代的,通用的Python包管理工具。提供了对Python包的查找、下载、安装、卸载的功能,便

于我们对Python的资源包进行管理。


**1.**安装

在安装Python时,会自动下载并且安装pip.

**2.**配置

在windows命令行里,输入pip -V可以查看pip的版本。
**四、****Python**

**

1.1****注释**

**1.1****注释介绍**

在我们工作编码的过程中,如果一段代码的逻辑比较复杂,不是特别容易理解,可以适当的添加注释,以辅助自己

或者其他编码人员解读代码。

**没注释的代码**


注意:注释是给程序员看的,为了让程序员方便阅读代码,解释器会忽略注释。使用自己熟悉的语言,适当的对代

码进行注释说明是一种良好的编码习惯。

**1.2****注释的分类**

在Python中支持单行注释和多行注释。

**单行注释**

以#开头,#右边的所有东西当做说明,而不是真正要执行的程序,起辅助说明作用。
# #开头右边的都是注释,解析器会忽略注释
print('hello world')  #我的作用是在控制台输出hello world
多行注释
2.变量以及数据类型
	2.1变量的定义
	 print("今天天气真好")
print("今天天气真好")
print("今天天气真好")
print("今天天气真好")
print("今天天气真好")
print("今天天气真好")
print("今天天气真好")
print("今天天气真好")
print("今天天气真好")
对于重复使用,并且经常需要修改的数据,可以定义为变量,来提高编程效率。
定义变量的语法为:变量名 = 变量值 。(这里的=作用是赋值。)

 # 定义一个变量表示这个字符串。如果需要修改内容,只需要修改变量对应的值即可weather = "今天天气真好"
print(weather)  # 注意,变量名不需要使用引号包裹
print(weather)
print(weather)
说明:
变量即是可以变化的量,可以随时进行修改。
程序就是用来处理数据的,而变量就是用来存储数据的。
2.2变量的类型
程序中:在Python里为了应对不同的业务需求,也把数据分为不同的类型。如下图所示:

2.2****变量的类型

程序中:在**Python****里为了应对不同的业务需求,也把数据分为不同的类型。**如下图所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RNhxYCiV-1665155932668)(C:\Users~风轻云淡~\AppData\Roaming\Typora\typora-user-images\image-20220914201431064.png)]

2.3****查看数据类型

在python中,只要定义了一个变量,而且它有数据,那么它的类型就已经确定了,不需要咱们开发者主动的

去说明它的类型,系统会自动辨别。也就是说在使用的时候**“变量没有类型,数据才有类型”**。

比如下面的示例里,a的类型可以根据数据来确认,但是我们没法预测变量b的类型。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FOGJ2CNw-1665155932669)(C:\Users~风轻云淡~\AppData\Roaming\Typora\typora-user-images\image-20220914201506841.png)]

在python中,只要定义了一个变量,而且它有数据,那么它的类型就已经确定了,不需要咱们开发者主动的

去说明它的类型,系统会自动辨别。也就是说在使用的时候**“变量没有类型,数据才有类型”**。

比如下面的示例里,a的类型可以根据数据来确认,但是我们没法预测变量b的类型。

如果临时想要查看一个变量存储的数据类型,可以使用type(变量的名字),来查看变量存储的数据类型。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tTc4YuG7-1665155932670)(C:\Users~风轻云淡~\AppData\Roaming\Typora\typora-user-images\image-20220914201540241.png)]

**3.**标识符和关键字

计算机编程语言中,标识符是用户编程时使用的名字,用于给变量、常量、函数、语句块等命名,以建立起名称与

使用之间的关系。

1.标识符由字母、下划线和数字组成,且数字不能开头。

2.严格区分大小写。

3.不能使用关键字。

遵守一定的命名规范。驼峰命名法,又分为大驼峰命名法和小驼峰命名法。

FirstName、LastName.

还有一种命名法是用下划线“_”来连接所有的单词,比如send_buf.

Python的命令规则遵循PEP8标准

3.2关键字

关键字的概念

一些具有特殊功能的标识符,这就是所谓的关键字。

关键字,已经被python官方使用了,所以不允许开发者自己定义和关键字相同名字的标识符。

关键字

 False   None  True  and   as    assert  break   class 

continue def   del  elif   else   except  finally  for

from   global if   import  in    is    lambda  nonlocal 

not    or   pass  raise  return  try   while   with 

yield

**4.**类型转换

函数 明 int(x) 将x转换为一个整数 
float(x) 将x转换为一个浮点数
str(x) 将对象 x 转换为字符串
将对象x转换成为布尔 bool(x) 值

转换成为整数

print(int("123"))  # 123 将字符串转换成为整数
 
print(int(123.78))  # 123 将浮点数转换成为整数
 
print(int(True))  # 1 布尔值True转换成为整数是 1 print(int(False)) # 0 布尔值False转换成为整数是 0  
# 以下两种情况将会转换失败
'''
123.456 和 12ab 字符串,都包含非法字符,不能被转换成为整数,会报错print(int("123.456"))
print(int("12ab"))

转换成为浮点数
 f1 = float("12.34")
 print(f1)   # 12.34
print(type(f1)) # float 将字符串的 "12.34" 转换成为浮点数 12.34  
f2 = float(23)
print(f2)  # 23.0
print(type(f2)) # float 将整数转换成为了浮点数
转换成为字符串
 str1 = str(45)
 str2 = str(34.56)str3 = str(True)
 print(type(str1),type(str2),type(str3))
 转换成为布尔值
  print(bool(''))
  print(bool(""))print(bool(0))
print(bool({}))print(bool([]))
5.运算符
5.1算数运算符
下面以a=10,b=20为例进行计算
算符优先级。并且,不同类型的数字在进行混合运算时,整数将会转换成浮点数进行运算。

 >>> 10 + 5.5 * 2
21.0
>>> (10 + 5.5) * 2 31.0
算数运算符在字符串里的使用
如果是两个字符串做加法运算,会直接把这两个字符串拼接成一个字符串。
 In [1]: str1 ='hello' 
In [2]: str2 = 'world' 
In [3]: str1+str2
Out[3]: 'helloworld'
 
In [4]:
如果是数字和字符串做加法运算,会直接报错。
 In [1]: str1 = 'hello'
 
In [2]: a = 2
 
In [3]: a+str1
‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐TypeError                                 Traceback (most recent call last)<ipython‐input‐3‐993727a2aa69> in <module>
‐‐‐‐> 1 a+str1
 
TypeError: unsupported operand type(s) for +: 'int' and 'str'
如果是数字和字符串做乘法运算,会将这个字符串重复多次。
 In [4]: str1 = 'hello' 
In [5]: str1*10
Out[5]: 'hellohellohellohellohellohellohellohellohellohello'
5.2赋值运算符
把=号右边的结果赋给左边的变量,如num=1+2*3,结果num的值为7
>>> num = 10
>>> num
10
 
# 同时为多个变量赋值(使用等号连接)
>>> a = b = 4
>>> a
4
>>> b
4
>>>
 
# 多个变量赋值(使用逗号分隔)
>>> num1, f1, str1 = 100, 3.14, "hello">>> num1
100
>>> f1
3.14
>>> str1
"hello"
5.3复合赋值运算符
>>> a = 100
>>> a += 1  # 相当于执行 a = a + 1
>>> a
101
 
# 示例:*=
>>> a = 100
>>> a *= 2  # 相当于执行 a = a * 2
>>> a
200
 
# 示例:*=,运算时,符号右侧的表达式先计算出结果,再与左边变量的值运算>>> a = 100
>>> a *= 1 + 2  # 相当于执行 a = a * (1+2)
>>> a
300
5.4比较运算符
以下假设变量a为10,变量b为20:
and or  not


6.输入输出
6.1输出
普通输出
python中变量的输出
 print('吴亦凡火了')
 格式化输出
比如有以下代码:
 pirnt("我今年10岁")
pirnt("我今年11岁")
pirnt("我今年12岁")
看如下代码:
 age = 10
 print("我今年%d岁" % age) 
age += 1
print("我今年%d岁" % age) 
age += 1
在程序中,看到了%这样的操作符,这就是Python中格式化输出。



6.2输入
在Python中,获取键盘输入的数据的方法是采用input函数(至于什么是函数,咱们以后的章节中讲解),那么这个input怎么用呢?
看如下示例:
 password = input("请输入密码:")
 print('您刚刚输入的密码是:%s' % password)
 注意:
 input()的小括号中放入的是提示信息,用来在获取数据之前给用户的一个简单提示input()在从键盘获取了数据以后,会存放到等号右边的变量中
input()会把用户输入的任何值都作为字符串来对待

7.流程控制语句7.1if判断语句
if语句是用来进行判断的,其使用格式如下:
     if 要判断的条件:
     		        条件成立时,要做的事情
     		        
        age = 30
    if age >= 18:
        print("我已经成年了")
        
         age = 16
    if age >= 18:
        print("我已经成年了")
   以上2个demo仅仅是age变量的值不一样,导致结果却不同;能够看得出if判断语句的作用:就是当满足一定条件时才会执行代码块语句,否则就不执行代码块语句。
注意:代码的缩进为一个tab键,或者4个空格
7.2ifelse

想一想:在使用if的时候,它只能做到满足条件时要做的事情。那万一需要在不满足条件的时候,做某些事,该怎么办呢?
答:使用if-else

if-else的使用格式
     if 条件:
        满足条件时的操作    else:
       			        不满足条件时的操作
       age = 18 
    if age >= 18:
        print("我可以去红浪漫了")    else:
        print("未成年,不允许去")
elif的功能
elif的使用格式如下:
				     if xxx1:
        事情1
    elif xxx2:        事情2
    elif xxx3:        事情3
   
  当xxx1满足时,执行事情1,然后整个if结束
当xxx1不满足时,那么判断xxx2,如果xxx2满足,则执行事情2,然后整个if结束当xxx1不满足时,xxx2也不满足,如果xxx3满足,则执行事情3,然后整个if结束

     score = 77
 
    if score>=90:
        print('本次考试,等级为A')    elif score>=80:
        print('本次考试,等级为B')    elif score>=70:
        print('本次考试,等级为C')    elif score>=60:
        print('本次考试,等级为D')    elif score<60:
        
                print('本次考试,等级为E')
  7.4for
在Python中for循环可以遍历任何序列的项目,如一个列表或者一个字符串等。for循环的格式

 for 临时变量 in 列表或者字符串等可迭代对象:    循环满足条件时执行的代码
 
 for循环的使用
 	遍历字符串:
 	 for s in "hello":    print(s)
 	 
 for i in range(5):    print(i)
 
 练习
使用for循环,计算1~100的和
7.5range
range可以生成数字供for循环遍历,它可以传递三个参数,分别表示起始、结束和步长。
[2, 5, 8]
>>> for x in range(2, 10, 3):...     print(x)
...
2
5
8

8.数据类型高级8.1字符串高级								
获取长度:len 查找内容:find						
判断:startswith,endswith 计算出现次数:count
替换内容:replace
切割字符串:split
修改大小写:upper,lower 空格处理:strip
字符串拼接:join

判断字符串是不是以谁谁谁开头/结尾
返回str在start和end之间在mystr里面出现的次数
替换字符串中指定的内容,如果指定次数count,则替换不会超过count次。通过参数的内容切割字符串
将字符串中的大小写互换
去空格
字符串拼接

8.2列表高级
		列表的增删改查
		添加元素
		添加元素有一下几个方法:
		append在末尾添加元素
insert在指定位置插入元素
extend合并两个列表
append
append会把新元素添加到列表末尾


     #定义变量A,默认有3个元素
    A = ['xiaoWang','xiaoZhang','xiaoHua']
 
    print("‐‐‐‐‐添加之前,列表A的数据‐‐‐‐‐A=%s" % A) 
    #提示、并添加元素
    temp = input('请输入要添加的学生姓名:')
    A.append(temp)
 
 
     print("‐‐‐‐‐添加之后,列表A的数据‐‐‐‐‐A=%s" % A)
     
   insert语句:
   insert(index,object)在指定位置index前插入元素object
    strs = ['a','b','m','s']
    strs.insert(3,'h')
print(strs)  # ['a', 'b', 'm', 'h', 's']

extend
通过extend可以将另一个列表中的元素逐一添加到列表中

 a = ['a','b','c']
 b = ['d','e','f']
a.extend(b)
print(a)  # ['a', 'b', 'c', 'd', 'e', 'f'] 将 b 添加到 a 里print(b) # ['d','e','f'] b的内容不变

修改元素
我们是通过指定下标来访问列表元素,因此修改元素的时候,为指定的列表下标赋值即可。

    #定义变量A,默认有3个元素
    A = ['xiaoWang','xiaoZhang','xiaoHua']
 
    print("‐‐‐‐‐修改之前,列表A的数据‐‐‐‐‐A=%s" % A) 
    #修改元素
    A[1] = 'xiaoLu'
 
    print("‐‐‐‐‐修改之后,列表A的数据‐‐‐‐‐A=%s" % A)
    
    
    查找元素
所谓的查找,就是看看指定的元素是否存在,主要包含一下几个方法:

in和notin

in,notin
python中查找的常用方法为:

in(存在),如果存在那么结果为true,否则为false
notin(不存在),如果不存在那么结果为true,否则false

     #待查找的列表
    nameList = ['xiaoWang','xiaoZhang','xiaoHua'] 
    #获取用户要查找的名字
    findName = input('请输入要查找的姓名:')
 
    #查找是否存在
    if findName in nameList:
        print('在列表中找到了相同的名字')
    else:
        print('没有找到')
        
说明:
		in的方法只要会用了,那么notin也是同样的用法,只不过notin判断的是不存在
		
删除元素
类比现实生活中,如果某位同学调班了,那么就应该把这个条走后的学生的姓名删除掉;在开发中经常会用到删除这种功能。
列表元素的常用删除方法有:

del:根据下标进行删除
pop:删除最后一个元素
remove:根据元素的值进行删除

del
 movieName = ['加勒比海盗','骇客帝国','第一滴血','指环王','霍比特人','速度与激情']
 print('‐‐‐‐‐‐删除之前‐‐‐‐‐‐movieName=%s' % movieName)del movieName[2]
print('‐‐‐‐‐‐删除之后‐‐‐‐‐‐movieName=%s' % movieName)


pop
 movieName = ['加勒比海盗','骇客帝国','第一滴血','指环王','霍比特人','速度与激情']
 print('‐‐‐‐‐‐删除之前‐‐‐‐‐‐movieName=%s' % movieName)movieName.pop()
print('‐‐‐‐‐‐删除之后‐‐‐‐‐‐movieName=%s' % movieName)


remove

 movieName = ['加勒比海盗','骇客帝国','第一滴血','指环王','霍比特人','速度与激情']
 print('‐‐‐‐‐‐删除之前‐‐‐‐‐‐movieName=%s' % movieName)movieName.remove('指环王')
print('‐‐‐‐‐‐删除之后‐‐‐‐‐‐movieName=%s' % movieName)

8.3元组高级
Python的元组与列表类似,不同之处在于元组的元素不能修改。元组使用小括号,列表使用方括号。

 >>> aTuple = ('et',77,99.9)
 >>> aTuple
('et',77,99.9)


访问元组


python中不允许修改元组的数据,包括不能删除其中的元素。定义只有一个数据的元组
定义只有一个元素的元组,需要在唯一的元素后写一个逗号


 >>> a = (11)
 >>> a
11
>>> type(a)
int
>>> a = (11,)  # 只有一个元素的元组,必须要在元素后写一个逗号>>> a
(11,)
>>> type(a)
tuple

8.4切片
切片是指对操作的对象截取其中一部分的操作。字符串、列表、元组都支持切片操作。
切片的语法:[起始:结束:步长],也可以简化使用[起始:结束]
注意:选取的区间从"起始"位开始,到"结束"位的前一位结束(不包含结束位本身),步长表示选取间隔。


 # 索引是通过下标取某一个元素
# 切片是通过下标去某一段元素
 
s = 'Hello World!'
print(s)
 
print(s[4])  # o 字符串里的第4个元素
 
print(s[3:7])  # lo W 包含下标 3,不含下标 7
 
print(s[1:]) # ello World! 从下标为1开始,取出 后面所有的元素(没有结束位)
 
print(s[:4])  # Hell 从起始位置开始,取到 下标为4的前一个元素(不包括结束位本身)
 
print(s[1:5:2]) # el 从下标为1开始,取到下标为5的前一个元素,步长为2(不包括结束位本身)


8.5字典高级

查看元素
除了使用key查找数据,还可以使用get来获取数据
 info = {'name':'班长','age':18}
 
print(info['age']) # 获取年龄
# print(info['sex']) # 获取不存在的key,会发生异常
 
print(info.get('sex')) # 获取不存在的key,获取到空的内容,不会出现异常print(info.get('sex', '男'))  # 获取不存在的key, 可以提供一个默认值。
修改元素
字典的每个元素中的数据是可以修改的,只要通过key找到,即可修改

 info = {'name':'班长', 'id':100}
 
print('修改之前的字典为 %s:' % info)
 
info['id'] = 200  # 为已存在的键赋值就是修改 
print('修改之后的字典为 %s:' % info)

结果:
修改之前的字典为 {'name': '班长', 'id': 100} 修改之后的字典为 {'name': '班长', 'id': 200} 


添加元素
如果在使用变量名['键']=数据时,这个“键”在字典中,不存在,那么就会新增这个元素demo:添加新的元素

 info = {'name':'班长'}
 
print('添加之前的字典为:%s' % info)
 
info['id'] = 100  # 为不存在的键赋值就是添加元素 
print('添加之后的字典为:%s' % info)

添加之前的字典为:{'name': '班长'} 
添加之后的字典为:{'name': '班长', 'id': 100} 

删除元素
对字典进行删除操作,有一下几种:
del
clear()

demo:del删除指定的元素

 info = {'name':'班长', 'id':100}
 
print('删除前,%s' % info)
 
del info['name']  # del 可以通过键删除字典里的指定元素 
print('删除后,%s' % info)


删除前,{'name': '班长', 'id': 100} 删除后,{'id': 100} 


 
del删除整个字典
 info = {'name':'monitor', 'id':100} 
print('删除前,%s'%info)
 
del info  # del 也可以直接删除变量
 
print('删除后,%s'%info)


删除前,{'name': 'monitor', 'id': 100} Traceback (most recent call last): 
  File "<stdin>", line 1, in <module> NameError: name 'info' is not defined 
  
  
   
clear清空整个字典
 info = {'name':'monitor', 'id':100} 
print('清空前,%s'%info)
 
info.clear()
 
print('清空后,%s'%info)

 清空前,{'name': 'monitor', 'id': 100}清空后,{}
 
  
字典的遍历
遍历字典的key(键)



**9.**函数

 print('欢迎马大哥光临红浪漫')
 print('男宾2位')
 
print('欢迎马大哥光临红浪漫')print('男宾2位')
 
print('欢迎马大哥光临红浪漫')print('男宾2位')
 
print('欢迎马大哥光临红浪漫')print('男宾2位')

9.1定义函数
定义函数的格式如下:

 # 定义一个函数,能够完成打印信息的功能def f1():
    print('欢迎马大哥光临红浪漫')
    print('男宾2位')   
    
    9.2调用函数
定义了函数之后,就相当于有了一个具有某些功能的代码,想要让这些代码能够执行,需要调用它调用函数很简单的,通过函数名()即可完成调用
 # 定义完函数后,函数是不会自动执行的,需要调用它才可以f1()
 
 函数定义好以后,函数体里的代码并不会执行,如果想要执行函数体里的内容,需要手动的调用函数。每次调用函数时,函数都会从头开始执行,当这个函数中的代码执行完毕后,意味着调用结束了。
 
 9.3函数参数
思考一个问题,如下:

现在需要定义一个函数,这个函数能够完成2个数的加法运算,并且把结果打印出来,该怎样设计?下面的代码可以吗?有什么缺陷吗?

 def add2num():  a = 11
  b = 22
  c = a+b
  print(c)
  
  为了让一个函数更通用,即想让它计算哪两个数的和,就让它计算哪两个数的和,在定义函数的时候可以让函数接收数据,就解决了这个问题,这就是函数的参数
定义、调用带有参数的函数
定义一个add2num(a,b)函数,来计算任意两个数字之和:

 def add2num(a, b):
    c = a+b
    print c
 
add2num(11, 22) # 调用带有参数的函数时,需要在小括号中,传递数据

注意:在定义函数的时候,小括号里写等待赋值的变量名
在调用函数的时候,小括号里写真正要进行运算的数据

调用函数时参数的顺序

 >>> def test(a,b):
 ...     print(a,b)
... 
>>> test(1,2)  # 位置参数
1 2
>>> test(b=1,a=2)  # 关键字参数2 1

定义时小括号中的参数,用来接收参数用的,称为“形参”
调用时小括号中的参数,用来传递给函数用的,称为“实参”

9.4函数返回值“返回值”介绍
现实生活中的场景:

所谓“返回值”,就是程序中函数完成一件事情后,最后给调用者的结果

带有返回值的函数
想要在函数中把结果返回给调用者,需要在函数中使用return 如下示例:

 def add2num(a, b):
    c = a+b
    return c  # return 后可以写变量名
 
  def add2num(a, b):
  		    return a+b  # return 后可以写计算表达式
  		    
 保存函数的返回值
在本小节刚开始的时候,说过的“买冰淇淋”的例子中,最后女儿给你冰淇淋时,你一定是从女儿手中接过来对么,程序也是如此,如果一个函数返回了一个数据,那么想要用这个数据,那么就需要保存
保存函数的返回值示例如下:

 #定义函数
def add2num(a, b):
    return a+b
 
#调用函数,顺便保存函数的返回值
result = add2num(100,98)
 
#因为result已经保存了add2num的返回值,所以接下来就可以使用了print(result)


9.5局部变量什么是局部变量如下图所示:
局部变量,就是在函数内部定义的变量
其作用范围是这个函数内部,即只能在这个函数中使用,在函数的外部是不能使用的

		 # 定义全局变量
		 a = 100
 
def test1():
    print(a)  # 虽然没有定义变量a但是依然可以获取其数据 
def test2():
    print(a)  # 虽然没有定义变量a但是依然可以获取其数据 
# 调用函数
test1()
test2()

在函数外边定义的变量叫做全局变量
全局变量能够在所有的函数中进行访问




10.文件

打开文件/创建文件
在python,使用open函数,可以打开一个已经存在的文件,或者创建一个新文件open(文件路径,访问模式)
示例如下:

 f = open('test.txt', 'w')
 
 说明:
 
 	文件路径
 	绝对路径:指的是绝对位置,完整地描述了目标的所在地,所有目录层级关系是一目了然的。
 	E:\python,从电脑的盘符开始,表示的就是一个绝对路径。
 	相对路径:是从当前文件所在的文件夹开始的路径。
 	
 	test.txt ,是在当前文件夹查找test.txt文件
 	./test.txt ,也是在当前文件夹里查找test.txt文件,
 	
 	
 	访问模式:
 	r:以只读方式打开文件。文件的指针将会放在文件的开头。如果文件不存在,则报错。这是默认模式。
 	w:打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
 	a:打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
 	r+:打开一个文件用于读写。文件指针将会放在文件的开头。
 	w+:打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
 	a+:打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。
 	rb:以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。
 	wb:以二进制格式打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
 	ab:以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
 	rb+:以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。
 	wb+:以二进制格式打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
 	ab+:以二进制格式打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。
 	
 	关闭文件
示例如下:
	 # 新建一个文件,文件名为:test.txt f = open('test.txt', 'w')
 
# 关闭这个文件
f.close()


10.2文件的读写
写数据(write)
使用write()可以完成向文件写入数据
	demo:新建一个文件 file_write_test.py ,向其中写入如下代码:
	 f = open('test.txt', 'w')
f.write('hello world, i am here!\n' * 5)f.close()

运行之后会在:file_write_test.py文件所在的路径中创建一个文件 ,并写入内容,运行效果显示如下:

如果文件不存在,那么创建;如果存在那么就先清空,然后写入数据

读数据(read)
使用read(num)可以从文件中读取数据,num表示要从文件中读取的数据的长度(单位是字节),如果没有传入num,那么就表示读取文件中所有的数据

demo:新建一个文件,file_read_test.py ,向其中写入如下代码:

 f = open('test.txt', 'r')
 
 
 content = f.read(5)  # 最多读取5个数据
print(content)
 
print("‐"*30)  # 分割线,用来测试
 
content = f.read()  # 从上次读取的位置继续读取剩下的所有的数据print(content)
 
f.close()  # 关闭文件,这个可是个好习惯哦


注意:如果用open打开文件时,如果使用的"r",那么可以省略

读数据(
readline只用来读取一行数据。
 f = open('test.txt', 'r') 
content = f.readline()
print("1:%s" % content)
 
content = f.readline()
print("2:%s" % content)
 
 
f.close()


读数据(readlines)

readlines可以按照行的方式把整个文件中的内容进行一次性读取,并且返回的是一个列表,其中每一行为列表的一个元素。


 f = open('test.txt', 'r')
 content = f.readlines()print(type(content))
 
for temp in content:
    print(temp)
 
f.close()

10.3序列化和反序列化

通过文件操作,我们可以将字符串写入到一个本地文件。但是,如果是一个对象(例如列表、字典、元组等),就无法直接写入到一个文件里,需要对这个对象进行序列化,然后才能写入到文件里。
设计一套协议,按照某种规则,把内存中的数据转换为字节序列,保存到文件,这就是序列化,反之,从文件的字节序列恢复到内存中,就是反序列化。
对象---》字节序列===序列化
字节序列--》对象===反序列化
Python中提供了JSON这个模块用来实现数据的序列化和反序列化。
JSON模块
JSON(JavaScriptObjectNotation,JS对象简谱)是一种轻量级的数据交换标准。JSON的本质是字符串。
使用JSON实现序列化
JSON提供了dump和dumps方法,将一个对象进行序列化。
dumps方法的作用是把对象转换成为字符串,它本身不具备将数据写入到文件的功能。

 import json
file = open('names.txt', 'w')
names = ['zhangsan', 'lisi', 'wangwu', 'jerry', 'henry', 'merry', 'chris']# file.write(names)  出错,不能直接将列表写入到文件里
 
# 可以调用 json的dumps方法,传入一个对象参数
result = json.dumps(names)
 
# dumps 方法得到的结果是一个字符串
print(type(result))  # <class 'str'>
 
# 可以将字符串写入到文件里
file.write(result)
 
file.close()

dump方法可以在将对象转换成为字符串的同时,指定一个文件对象,把转换后的字符串写入到这个文件里。
 import json
 
file = open('names.txt', 'w')
names = ['zhangsan', 'lisi', 'wangwu', 'jerry', 'henry', 'merry', 'chris'] 
# dump方法可以接收一个文件参数,在将对象转换成为字符串的同时写入到文件里
json.dump(names, file)
file.close()


使用JSON实现反序列化
使用loads和load方法,可以将一个JSON字符串反序列化成为一个Python对象。loads方法需要一个字符串参数,用来将一个字符串加载成为Python对象。

 import json
 
# 调用loads方法,传入一个字符串,可以将这个字符串加载成为Python对象
result = json.loads('["zhangsan", "lisi", "wangwu", "jerry", "henry", "merry", "chris"]')print(type(result))  # <class 'list'>

load方法可以传入一个文件对象,用来将一个文件对象里的数据加载成为Python对象。

 import json
 
# 以可读方式打开一个文件
file = open('names.txt', 'r')
 
# 调用load方法,将文件里的内容加载成为一个Python对象result = json.load(file)
 
print(result)
file.close()


11.异常

程序在运行过程中,由于我们的编码不规范,或者其他原因一些客观原因,导致我们的程序无法继续运行,此时,

程序就会出现异常。如果我们不对异常进行处理,程序可能会由于异常直接中断掉。为了保证程序的健壮性,我们

在程序设计里提出了异常处理这个概念。

11.1****读取文件异常

在读取一个文件时,如果这个文件不存在,则会报出FileNotFoundError

11.2try...except语句

try...except语句可以对代码运行过程中可能出现的异常进行处理。语法结构:

try:
		    可能会出现异常的代码块
except 异常的类型:
    出现异常以后的处理语句
   
   
  例如: try:
    f = open('test.txt', 'r')
    print(f.read())
except FileNotFoundError:
    print('文件没有找到,请检查文件名称是否正确')
    

Python高级:爬虫教程

Urllib 介绍

**1.**什么是互联网爬虫?

如果我们把互联网比作一张大的蜘蛛网,那一台计算机上的数据便是蜘蛛网上的一个猎物,而爬虫程序就是一只小

蜘蛛,沿着蜘蛛网抓取自己想要的数据

解释1:通过一个程序,根据Url(http://www.taobao.com)进行爬取网页,获取有用信息

解释2:使用程序模拟浏览器,去向服务器发送请求,获取响应信

2.爬虫核心?

1.爬取网页:爬取整个网页 包含了网页中所有得内容

2.解析数据:将网页中你得到的数据 进行解析

3.难点:爬虫和反爬虫之间的博弈

**3.**爬虫的用途?

数据分析/人工数据集

社交软件冷启动

**4.**爬虫分类?

通用爬虫:

实例

百度、360、google、sougou等搜索引擎‐‐‐伯乐在线

功能

访问网页‐>抓取数据‐>数据存储‐>数据处理‐>提供检索服务

robots协议

一个约定俗成的协议,添加robots.txt文件,来说明本网站哪些内容不可以被抓取,起不到限制作用

自己写的爬虫无需遵守

网站排名(SEO)

\1. 根据pagerank算法值进行排名(参考个网站流量、点击率等指标)

\2. 百度竞价排名

缺点

\1. 抓取的数据大多是无用的

2.不能根据用户的需求来精准获取数据

聚焦爬虫

功能

根据需求,实现爬虫程序,抓取需要的数据

设计思路

1.确定要爬取的url

如何获取Url

2.模拟浏览器通过http协议访问url,获取服务器返回的html代码

如何访问

3.解析html字符串(根据一定规则提取需要的数据)

如何解析

**5.**反爬手段?

1.User‐Agent:

User Agent中文

User Agent中文名为用户代理,简称 UA,它是一个特殊字符串头,使得服务器能够识别客户使用的操作系统及版

本、CPU 类型、浏览器及版本、浏览器渲染引擎、浏览器语言、浏览器插件等。

2.代理IP

西次代理

快代理

什么是高匿名、匿名和透明代理?它们有什么区别?

1.使用透明代理,对方服务器可以知道你使用了代理,并且也知道你的真实IP。

2.使用匿名代理,对方服务器可以知道你使用了代理,但不知道你的真实IP。

3.使用高匿名代理,对方服务器不知道你使用了代理,更不知道你的真实IP。

3.验证码访问

打码平台

云打码平台

超级🦅

4.动态加载网页 网站返回的是js数据 并不是网页的真实数据

selenium驱动真实的浏览器发送请求

5.数据加密

分析js代码

6.urllib****库使用

     urllib.request.urlopen() 模拟浏览器向服务器发送请求
    response    服务器返回的数据
        response的数据类型是HttpResponse
        字节‐‐>字符串
                解码decode
        字符串‐‐>字节
                编码encode
        read()       字节形式读取二进制   扩展:rede(5)返回前几个字节        readline()   读取一行
        readlines()  一行一行读取 直至结束
        getcode()    获取状态码
        geturl()     获取url
        getheaders() 获取headers
    urllib.request.urlretrieve()
        请求网页
        请求图片
        请求视频



**7.**请求对象的定制

​ UA介绍:User Agent中文名为用户代理,简称 UA,它是一个特殊字符串头,使得服务器能够识别客户使用的操作系统

及版本、CPU 类型、浏览器及版本。浏览器内核、浏览器渲染引擎、浏览器语言、浏览器插件

语法:request = urllib.request.Request()

**8.**编解码

**

1.get请求方式:****urllib.parse.quote****()** 

import urllib.request

import urllib.parse

url = 'https://www.baidu.com/s?wd='

 

headers = {

  'User‐Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like 

Gecko) Chrome/74.0.3729.169 Safari/537.36'

}

 

url = url + urllib.parse.quote('小野')

 

request = urllib.request.Request(url=url,headers=headers)

 

response = urllib.request.urlopen(request)

 

print(response.read().decode('utf‐8'))

2.get****请求方式:urllib.parse.urlencode()

import urllib.request

import urllib.parse

url = 'http://www.baidu.com/s?'

data = {

  'name':'小刚',

  'sex':'男',

}

data = urllib.parse.urlencode(data)

url = url + data

print(url)

headers = {

  'User‐Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like 

Gecko) Chrome/74.0.3729.169 Safari/537.36'

}
response = urllib.request.urlopen(request)

print(response.read().decode('utf‐8'))

3.post****请求方式

import urllib.request

import urllib.parse

url = 'https://fanyi.baidu.com/sug'

headers = {

  'user‐agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like 

Gecko) Chrome/74.0.3729.169 Safari/537.36'

}

keyword = input('请输入您要查询的单词')

data = {

  'kw':keyword

}

data = urllib.parse.urlencode(data).encode('utf‐8')

request = urllib.request.Request(url=url,headers=headers,data=data)

response = urllib.request.urlopen(request)

print(response.read().decode('utf‐8'))

总结:post和get区别?

1:get请求方式的参数必须编码,参数是拼接到url后面,编码之后不需要调用encode方法

2:post请求方式的参数必须编码,参数是放在请求对象定制的方法中,编码之后需要调用encode方法

案例练习:百度详细翻译

 import urllib.request
 import urllib.parse
 
url = 'https://fanyi.baidu.com/v2transapi'
headers = {
    # ':authority': 'fanyi.baidu.com',
    # ':method': 'POST',
    # ':path': '/v2transapi',
    # ':scheme': 'https',
    # 'accept': '*/*',
    # 'accept‐encoding': 'gzip, deflate, br',    # 'accept‐language': 'zh‐CN,zh;q=0.9',
    # 'content‐length': '119',
        # 'content‐type': 'application/x‐www‐form‐urlencoded; charset=UTF‐8',
            'cookie': 'REALTIME_TRANS_SWITCH=1; FANYI_WORD_SWITCH=1; HISTORY_SWITCH=1; 
            
    SOUND_SPD_SWITCH=1; SOUND_PREFER_SWITCH=1; PSTM=1537097513; 
BIDUPSID=D96F9A49A8630C54630DD60CE082A55C; BAIDUID=0814C35D13AE23F5EAFA8E0B24D9B436:FG=1; 
to_lang_often=%5B%7B%22value%22%3A%22en%22%2C%22text%22%3A%22%u82F1%u8BED%22%7D%2C%7B%22value%22 %3A%22zh%22%2C%22text%22%3A%22%u4E2D%u6587%22%7D%5D; 
from_lang_often=%5B%7B%22value%22%3A%22zh%22%2C%22text%22%3A%22%u4E2D%u6587%22%7D%2C%7B%22value%22%3A%22en%22%2C%22text%22%3A%22%u82F1%u8BED%22%7D%5D; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; 
delPer=0; H_PS_PSSID=1424_21115_29522_29519_29099_29568_28835_29220_26350; PSINO=2; locale=zh; 
Hm_lvt_64ecd82404c51e03dc91cb9e8c025574=1563000604,1563334706,1565592510; 
Hm_lpvt_64ecd82404c51e03dc91cb9e8c025574=1565592510; 
yjs_js_security_passport=2379b52646498f3b5d216e6b21c6f1c7bf00f062_1565592544_js',
    # 'origin': 'https://fanyi.baidu.com',
    # 'referer': 'https://fanyi.baidu.com/translate?
aldtype=16047&query=&keyfrom=baidu&smartresult=dict&lang=auto2zh',
    # 'sec‐fetch‐mode': 'cors',
    # 'sec‐fetch‐site': 'same‐origin',
    # 'user‐agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like 
Gecko) Chrome/76.0.3809.100 Safari/537.36',
    # 'x‐requested‐with': 'XMLHttpRequest',
}
data = {
    'from': 'en',
    'to': 'zh',
    'query': 'you',
    'transtype': 'realtime',
    'simple_means_flag': '3',
    'sign': '269482.65435',
    'token': '2e0f1cb44414248f3a2b49fbad28bbd5',
}
#参数的编码
data = urllib.parse.urlencode(data).encode('utf‐8')
# 请求对象的定制
request = urllib.request.Request(url=url,headers=headers,data=data)
response = urllib.request.urlopen(request)
# 请求之后返回的所有的数据
content = response.read().decode('utf‐8')
import json
# loads将字符串转换为python对象
obj = json.loads(content)
# python对象转换为json字符串  ensure_ascii=False  忽略字符集编码
s = json.dumps(obj,ensure_ascii=False)
print(s)        

9.ajaxget****请求

案例:豆瓣电影

 # 爬取豆瓣电影前10页数据
# https://movie.douban.com/j/chart/top_list?
type=20&interval_id=100%3A90&action=&start=0&limit=20
# https://movie.douban.com/j/chart/top_list?
type=20&interval_id=100%3A90&action=&start=20&limit=20
# https://movie.douban.com/j/chart/top_list?
type=20&interval_id=100%3A90&action=&start=40&limit=20
 
import urllib.request
import urllib.parse
 
# 下载前10页数据
# 下载的步骤:1.请求对象的定制  2.获取响应的数据 3.下载
 
# 每执行一次返回一个request对象
def create_request(page):
    base_url = 'https://movie.douban.com/j/chart/top_list?type=20&interval_id=100%3A90&action=&'    headers = {
            'User‐Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36'
    }
    data={
        #  1 2  3  4
        #  0 20 40 60
        'start':(page‐1)*20,
        'limit':20
    }
    # data编码
    data = urllib.parse.urlencode(data)
    url = base_url + data
    request = urllib.request.Request(url=url,headers=headers)
    return request
# 获取网页源码
def get_content(request):
    response = urllib.request.urlopen(request)
    content = response.read().decode('utf‐8')
    return content
 
def down_load(page,content):
#    with open(文件的名字,模式,编码)as fp:
#        fp.write(内容)
    with open('douban_'+str(page)+'.json','w',encoding='utf‐8')as fp:
        fp.write(content)
 
if __name__ == '__main__':
    start_page = int(input('请输入起始页码'))
    end_page = int(input('请输入结束页码'))
    for page in range(start_page,end_page+1):
        request = create_request(page)
        content = get_content(request)
        down_load(page,content)

10.ajaxpost****请求

案例:KFC官网

11.URLError\HTTPError

简介:1.HTTPError类是URLError类的子类

2.导入的包urllib.error.HTTPError urllib.error.URLError

3.http错误:http错误是针对浏览器无法连接到服务器而增加出来的错误提示。引导并告诉浏览者该页是哪里出

了问题。

4.通过urllib发送请求的时候,有可能会发送失败,这个时候如果想让你的代码更加的健壮,可以通过try‐

except进行捕获异常,异常有两类,URLError\HTTPError

 eg:
 
import urllib.request
import urllib.error
url = 'https://blog.csdn.net/ityard/article/details/102646738' 
# url = 'http://www.goudan11111.com'
 
headers = {
        # 'Accept': 
        'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,applicati
      on/signed‐exchange;v=b3',
        # 'Accept‐Encoding': 'gzip, deflate, br',
        # 'Accept‐Language': 'zh‐CN,zh;q=0.9',
        # 'Cache‐Control': 'max‐age=0',
        # 'Connection': 'keep‐alive',
        'Cookie': 'uuid_tt_dd=10_19284691370‐1530006813444‐566189; 
smidV2=2018091619443662be2b30145de89bbb07f3f93a3167b80002b53e7acc61420; 
_ga=GA1.2.1823123463.1543288103; dc_session_id=10_1550457613466.265727; 
acw_tc=2760821d15710446036596250e10a1a7c89c3593e79928b22b3e3e2bc98b89; 
Hm_lvt_e5ef47b9f471504959267fd614d579cd=1571329184; 
Hm_ct_e5ef47b9f471504959267fd614d579cd=6525*1*10_19284691370‐1530006813444‐566189; 
__yadk_uid=r0LSXrcNYgymXooFiLaCGt1ahSCSxMCb; 
Hm_lvt_6bcd52f51e9b3dce32bec4a3997715ac=1571329199,1571329223,1571713144,1571799968; 
acw_sc__v2=5dafc3b3bc5fad549cbdea513e330fbbbee00e25; firstDie=1; SESSION=396bc85c‐556b‐42bd‐
890c‐c20adaaa1e47; UserName=weixin_42565646; UserInfo=d34ab5352bfa4f21b1eb68cdacd74768; 
UserToken=d34ab5352bfa4f21b1eb68cdacd74768; UserNick=weixin_42565646; AU=7A5; 
UN=weixin_42565646; BT=1571800370777; p_uid=U000000; dc_tos=pzt4xf; 
Hm_lpvt_6bcd52f51e9b3dce32bec4a3997715ac=1571800372; 
Hm_ct_6bcd52f51e9b3dce32bec4a3997715ac=1788*1*PC_VC!6525*1*10_19284691370‐1530006813444‐
566189!5744*1*weixin_42565646; 
announcement=%257B%2522isLogin%2522%253Atrue%252C%2522announcementUrl%2522%253A%2522https%253A%2 52F%252Fblogdev.blog.csdn.net%252Farticle%252Fdetails%252F102605809%2522%252C%2522announcementCo unt%2522%253A0%252C%2522announcementExpire%2522%253A3600000%257D',
        # 'Host': 'blog.csdn.net',
        # 'Referer': 'https://passport.csdn.net/login?code=public',
        # 'Sec‐Fetch‐Mode': 'navigate',
        # 'Sec‐Fetch‐Site': 'same‐site',
        # 'Sec‐Fetch‐User': '?1',
        # 'Upgrade‐Insecure‐Requests': '1',
        'User‐Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36',
    }
try:    request = urllib.request.Request(url=url,headers=headers)
 
    response = urllib.request.urlopen(request) 
    content = response.read().decode('utf‐8')    print(content)
except urllib.error.HTTPError:
    print(1111)
 
except urllib.error.URLError:
    print(2222)
    

12.cookie****登录

使用案例:

​ 1.weibo登陆

​ 作业:qq空间的爬取

**

13.Handler****处理器**

 为什么要学习handler?

   urllib.request.urlopen(url)

​     不能定制请求头

   urllib.request.Request(url,headers,data)

​     可以定制请求头

   Handler

​     定制更高级的请求头(随着业务逻辑的复杂 请求对象的定制已经满足不了我们的需求(动态cookie和代理

不能使用请求对象的定制)


eg:

import urllib.request
url = 'http://www.baidu.com'
headers = {
        'User ‐ Agent': 'Mozilla / 5.0(Windows NT 10.0;Win64;x64) AppleWebKit / 537.36(KHTML, likeGecko) Chrome / 74.0.3729.169Safari / 537.36'
    }
request = urllib.request.Request(url=url,headers=headers)
 
handler = urllib.request.HTTPHandler()
 
opener = urllib.request.build_opener(handler)
 
response = opener.open(request)
 
print(response.read().decode('utf‐8'))
 

**14.**代理服务器

1.代理的常用功能?

    1.突破自身IP访问限制,访问国外站点。
    2.访问一些单位或团体内部资源
            扩展:某大学FTP(前提是该代理地址在该资源的允许访问范围之内),使用教育网内地址段免费代理服务器,就可以用于对教育网开放的各类FTP下载上传,以及各类资料查询共享等服务。
    3.提高访问速度
            扩展:通常代理服务器都设置一个较大的硬盘缓冲区,当有外界的信息通过时,同时也将其保存到缓冲区中,当其他用户再访问相同的信息时, 则直接由缓冲区中取出信息,传给用户,以提高访问速度。
    4.隐藏真实IP
            扩展:上网者也可以通过这种方法隐藏自己的IP,免受攻击。
2.代码配置代理
    创建Reuqest对象
    创建ProxyHandler对象
    用handler对象创建opener对象
    使用opener.open函数发送请求

eg:

import urllib.request
url = 'http://www.baidu.com/s?wd=ip'
headers = {
        'User ‐ Agent': 'Mozilla / 5.0(Windows NT 10.0;Win64;x64) AppleWebKit / 537.36(KHTML, likeGecko) Chrome / 74.0.3729.169Safari / 537.36'
    }
request = urllib.request.Request(url=url,headers=headers)
proxies = {'http':'117.141.155.244:53281'}
handler = urllib.request.ProxyHandler(proxies=proxies)
opener = urllib.request.build_opener(handler)
response = opener.open(request)
content = response.read().decode('utf‐8')
with open('daili.html','w',encoding='utf‐8')as fp:
    fp.write(content)

第一章:xpath的使用

xpath使用: 注意:提前安装xpath插件 (1)打开chrome浏览器 
(2)点击右上角小圆点 
(3)更多工具 
(4)扩展程序 
(5)拖拽xpath插件到扩展程序中 
(6)如果crx文件失效,需要将后缀修改zip 
(7)再次拖拽 
(8)关闭浏览器重新打开 
(9)ctrl + shift + x 
(10)出现小黑框 1.安装lxml库pip install lxml ‐i https://pypi.douban.com/simple 2.导入lxml.etree from lxml import etree 3.etree.parse() 
解析本地文件 html_tree = etree.parse('XX.html') 4.etree.HTML() 服务器响应文件 html_tree = etree.HTML(response.read().decode('utf‐8') 4.html_tree.xpath(xpath路径)
xpath基本语法: 1.路径查询 //:查找所有子孙节点,不考虑层级关系 / :找直接子节点 2.谓词查询 //div[@id] //div[@id="maincontent"] 
3.属性查询 //@class 
4.模糊查询 //div[contains(@id, "he")] //div[starts‐with(@id, "he")] 
5.内容查询 //div/h1/text() 
6.逻辑运算 //div[@id="head" and @class="s_down"] //title | //price
 jsonpath的安装及使用方式:

​      pip安装: 

​          pip install jsonpath

​      jsonpath的使用:

​          obj = json.load(open('json文件', 'r', encoding='utf‐8'))

​          ret = jsonpath.jsonpath(obj, 'jsonpath语法')

3.BeautifulSoup

1.BeautifulSoup简称:

   bs4

2.什么是BeatifulSoup?

  BeautifulSoup,和lxml一样,是一个html的解析器,主要功能也是解析和提取数据

3.优缺点?

  缺点:效率没有lxml的效率高 

  优点:接口设计人性化,使用方便

2.安装以及创建

 1.安装
    pip install bs4
2.导入
    from bs4 import BeautifulSoup
3.创建对象
    服务器响应的文件生成对象
        soup = BeautifulSoup(response.read().decode(), 'lxml')    本地文件生成对象
        soup = BeautifulSoup(open('1.html'), 'lxml')
        注意:默认打开文件的编码格式gbk所以需要指定打开编码格式

3.节点定位

1.根据标签名查找节点

​    soup.a 【注】只能找到第一个a

​      soup.a.name

​      soup.a.attrs

2.函数

​    (1).find(返回一个对象)

​         find('a'):只找到第一个a标签
                  find('a', title='名字')
                  find('a', class_='名字')
        (2).find_all(返回一个列表)
                  find_all('a')  查找到所有的a
                  find_all(['a', 'span'])  返回所有的a和span
                  find_all('a', limit=2)  只找前两个a
        (3).select(根据选择器得到节点对象)【推荐】
                  1.element
                      eg:p
                  2..class
                      eg:.firstname
                  3.#id
                      eg:#firstname
                  4.属性选择器
                      [attribute]
                          eg:li = soup.select('li[class]')
                      [attribute=value]
                          eg:li = soup.select('li[class="hengheng1"]')                  5.层级选择器
                      element element
                          div p
                      element>element
                          div>p
                      element,element
                          div,p 
                                eg:soup = soup.select('a,span')

4.节点信息

     (1).获取节点内容:适用于标签中嵌套标签的结构            obj.string
            obj.get_text()【推荐】
    (2).节点的属性
            tag.name 获取标签名
                eg:tag = find('li)
                   print(tag.name)
           tag.attrs将属性值作为一个字典返回
    (3).获取节点属性
            obj.attrs.get('title')【常用】
            obj.get('title')
            obj['title']

Selenium

1.Selenium

    1)Selenium是一个用于Web应用程序测试的工具。
2)Selenium 测试直接运行在浏览器中,就像真正的用户在操作一样。


3.如何安装selenium?

​ http://chromedriver.storage.googleapis.com/index.html

4.selenium的使用步骤?

1)导入:from selenium import webdriver 

2)创建谷歌浏览器操作对象:

                path = 谷歌浏览器驱动文件路径
                browser = webdriver.Chrome(path)
  3)访问网址
                  url = 要访问的网址              
                  browser.get(url)
 4‐1:selenium的元素定位?
        元素定位:自动化要做的就是模拟鼠标和键盘来操作来操作这些元素,点击、输入等等。操作这些元素前首先要找到它们,WebDriver提供很多定位元素的方法
        方法:
              1.find_element_by_id
                        eg:button = browser.find_element_by_id('su')
              2.find_elements_by_name
                        eg:name = browser.find_element_by_name('wd')
              3.find_elements_by_xpath
                        eg:xpath1 = browser.find_elements_by_xpath('//input[@id="su"]')
              4.find_elements_by_tag_name
                        eg:names = browser.find_elements_by_tag_name('input')
              5.find_elements_by_css_selector
                        eg:my_input = browser.find_elements_by_css_selector('#kw')[0]
              6.find_elements_by_link_text
             eg:browser.find_element_by_link_text("新闻")
    4‐2:访问元素信息
    获取元素属性
        .get_attribute('class')    获取元素文本
        .text
    获取标签名
        .tag_name
 4‐3:交互
    点击:click()
    输入:send_keys()
    后退操作:browser.back()
    前进操作:browser.forword()
    模拟JS滚动:
        js='document.documentElement.scrollTop=100000'        browser.execute_script(js) 执行js代码
    获取网页代码:page_source 
    退出:browser.quit()

2.Phantomjs

1.什么是Phantomjs?

1)是一个无界面的浏览器
2)支持页面元素查找,js的执行等
3)由于不进行css和gui渲染,运行效率要比真实的浏览器要快很多

2.如何使用Phantomjs?

1)获取PhantomJS.exe文件路径path
2)browser = webdriver.PhantomJS(path)3)browser.get(url)
     扩展:保存屏幕快照:browser.save_screenshot('baidu.png')

3.Chromehandless

Chrome-headless模式,Google针对Chrome浏览器59版新增加的一种模式,可以让你不打开UI界面的情况下使用Chrome浏览器,所以运行效果与Chrome保持完美一致。
 1.系统要求:
          Chrome 
                Unix\Linux 系统需要 chrome >= 59                 Windows 系统需要 chrome >= 60
          Python3.6
          Selenium==3.4.*
          ChromeDriver==2.31

2.配置:

    from selenium import webdriver
        from selenium.webdriver.chrome.options import Options
 
    chrome_options = Options()
    chrome_options.add_argument('‐‐headless')
    chrome_options.add_argument('‐‐disable‐gpu')
 
    path = r'C:\Program Files (x86)\Google\Chrome\Application\chrome.exe'    chrome_options.binary_location = path
 
    browser = webdriver.Chrome(chrome_options=chrome_options)
 
    browser.get('http://www.baidu.com/')
     3.配置封装:
          from selenium import webdriver
          #这个是浏览器自带的  不需要我们再做额外的操作
          from selenium.webdriver.chrome.options import Options
 
          def share_browser():
              #初始化
              chrome_options = Options()
              chrome_options.add_argument('‐‐headless')
              chrome_options.add_argument('‐‐disable‐gpu')
              #浏览器的安装路径    打开文件位置
              #这个路径是你谷歌浏览器的路径
              path = r'C:\Program Files (x86)\Google\Chrome\Application\chrome.exe'              chrome_options.binary_location = path
 
              browser = webdriver.Chrome(chrome_options=chrome_options)
 
              return  browser
  封装调用:
          from handless import share_browser
 
          browser = share_browser()
 
          browser.get('http://www.baidu.com/')
 
          browser.save_screenshot('handless1.png')

第四节:request

requests

**1.**基本使用

    官方文档
        http://cn.python‐requests.org/zh_CN/latest/
    快速上手
        http://cn.python‐requests.org/zh_CN/latest/user/quickstart.html

2.安装

    pip install requests
 3.response的属性以及类型
    类型             :models.Response
    r.text          : 获取网站源码
    r.encoding      :访问或定制编码方式    r.url           :获取请求的url
    r.content       :响应的字节类型
    r.status_code    :响应的状态码
    r.headers        :响应的头信息

2.get****请求

     requests.get()
        eg:
             import requests
              url = 'http://www.baidu.com/s?'
              headers = {
                  'User‐Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML,                   like Gecko) Chrome/65.0.3325.181 Safari/537.36'
              }
              data = {
                  'wd':'北京'
              }
              response = requests.get(url,params=data,headers=headers)
    定制参数
        参数使用params传递
        参数无需urlencode编码
        不需要请求对象的定制
        请求资源路径中?可加可不加

3.post****请求

  requests.post()
    百度翻译:
        eg:
            import requests
            post_url = 'http://fanyi.baidu.com/sug'
             headers={
                  'User‐Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36                   (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36'
              }
            data = {
                'kw': 'eye'
            }
            r = requests.post(url = post_url,headers=headers,data=data)
            
             6:get和post区别?
    1: get请求的参数名字是params  post请求的参数的名字是data      2: 请求资源路径后面可以不加?  
    3: 不需要手动编解码  
    4: 不需要做请求对象的定制

**4.**代理

 7:proxy定制
    在请求中设置proxies参数
    参数类型是一个字典类型
    eg:
        import requests
        url = 'http://www.baidu.com/s?'
         headers = {
              'user‐agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML,              like Gecko) Chrome/65.0.3325.181 Safari/537.36'
          }
        data = {
            'wd':'ip'
        }
        proxy = {
              'http':'219.149.59.250:9797'
          }
       r = requests.get(url=url,params=data,headers=headers,proxies=proxy)
        with open('proxy.html','w',encoding='utf‐8') as fp:
            fp.write(r.text)

5.cookie****定制

 8:cookie定制

  应用案例:

scrapy

(1)scrapy是什么?

2)安装scrapy:
            pip install scrapy
  安装过程中出错:
            如果安装有错误!!!!
             pip install Scrapy
             building 'twisted.test.raiser' extension
             error: Microsoft Visual C++ 14.0 is required. Get it with "Microsoft Visual C++             Build Tools": http://landinghub.visualstudio.com/visual‐cpp‐build‐tools
  解决方案:
        http://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted 
        下载twisted对应版本的whl文件(如我的Twisted‐17.5.0‐cp36‐cp36m‐win_amd64.whl),cp后面是            python版本,amd64代表64位,运行命令:
        pip install C:\Users\...\Twisted‐17.5.0‐cp36‐cp36m‐win_amd64.whl
        pip install Scrapy
  如果再报错
            python ‐m pip install ‐‐upgrade pip
  如果再报错   win32
  解决方法:
        pip install pypiwin32
  再报错:使用anaconda
        使用步骤:
            打开anaconda
            点击environments
            点击not installed
            输入scrapy
            apply
            在pycharm中选择anaconda的环境
            

1.scrapy****项目的创建以及运行

1.创建scrapy项目:

​ 终端输入 scrapy startproject 项目名称

 2.项目组成:

​     spiders 

​       __init__.py

​       自定义的爬虫文件.py    ‐‐‐》由我们自己创建,是实现爬虫核心功能的文件

​     __init__.py         

​     items.py           ‐‐‐》定义数据结构的地方,是一个继承自scrapy.Item的类

​     middlewares.py        ‐‐‐》中间件  代理
          pipelines.py                ‐‐‐》管道文件,里面只有一个类,用于处理下载数据的后续处理
                                                  默认是300优先级,值越小优先级越高
                settings.py                 ‐‐‐》配置文件  比如:是否遵守robots协议,User‐Agent定义等                                             
 3.创建爬虫文件:            
 1)跳转到spiders文件夹   cd 目录名字/目录名字/spiders 2)scrapy genspider 爬虫名字 网页的域名
   爬虫文件的基本组成:
             继承scrapy.Spider类
                      name = 'baidu'       ‐‐‐》  运行爬虫文件时使用的名字
                     allowed_domains       ‐‐‐》 爬虫允许的域名,在爬取的时候,如果不是此域名之下的url,会被过滤掉
                      start_urls           ‐‐‐》 声明了爬虫的起始地址,可以写多个url,一般是一个
                      parse(self, response) ‐‐‐》解析数据的回调函数
                                  response.text         ‐‐‐》响应的是字符串
                                  response.body         ‐‐‐》响应的是二进制文件
                                  response.xpath()‐》xpath方法的返回值类型是selector列表
                                  extract()             ‐‐‐》提取的是selector对象的是data
                                  extract_first()       ‐‐‐》提取的是selector列表中的第一个数据
                                  
                                  
  4.运行爬虫文件:
            scrapy crawl 爬虫名称
            注意:应在spiders文件夹内执行                                 
3.scrapy架构组成
1)引擎                   ‐‐‐》自动运行,无需关注,会自动组织所有的请求对象,分发给下载器
2)下载器                 ‐‐‐》从引擎处获取到请求对象后,请求数据
3)spiders               ‐‐‐》Spider类定义了如何爬取某个(或某些)网站。包括了爬取的动作(例
如:是否跟进链接)以及如何从网页的内容中提取结构化数据(爬取item)。 换句话说,Spider就是您定义爬取的动作及分析某个网页(或者是有些网页)的地方。
Item pipeline)   ‐‐‐》最终处理数据的管道,会预留接口供我们处理数据
当Item在Spider中被收集之后,它将会被传递到Item Pipeline,一些组件会按照一定的顺序执行对Item的处理。
每个item pipeline组件(有时称之为“Item Pipeline”)是实现了简单方法的Python类。他们接收到Item并通过它执行一些行为,同时也决定此Item是否继续通过pipeline,或是被丢弃而不再进行处理。
          以下是item pipeline的一些典型应用:
          1. 清理HTML数据
          2. 验证爬取的数据(检查item包含某些字段)
          3. 查重(并丢弃)
          4. 将爬取结果保存到数据库中

4.scrapy****工作原理

2.scrapyshell

 1.什么是scrapy shell?
    Scrapy终端,是一个交互终端,供您在未启动spider的情况下尝试及调试您的爬取代码。 其本意是用来测试提取数据的代码,不过您可以将其作为正常的Python终端,在上面测试任何的Python代码。
该终端是用来测试XPath或CSS表达式,查看他们的工作方式及从爬取的网页中提取的数据。 在编写您的spider时,该终端提供了交互性测试您的表达式代码的功能,免去了每次修改后运行spider的麻烦。
一旦熟悉了Scrapy终端后,您会发现其在开发和调试spider时发挥的巨大作用。
 2.安装ipython
    安装:pip install ipython
    简介:如果您安装了 IPython ,Scrapy终端将使用 IPython (替代标准Python终端)。 IPython 终端与其他相比更为强大,提供智能的自动补全,高亮输出,及其他特性。
1)scrapy shell www.baidu.com
2)scrapy shell http://www.baidu.com
        (3) scrapy shell "http://www.baidu.com"        (4) scrapy shell "www.baidu.com"
 
语法:1)response对象:
                  response.body
                  response.text
                  response.url
                  response.status
    2)response的解析:
    
                     response.xpath() (常用)
                             使用xpath路径查询特定元素,返回一个selector列表对象
                  response.css()
                             使用css_selector查询元素,返回一个selector列表对象
                              获取内容 :response.css('#su::text').extract_first()
                              获取属性 :response.css('#su::attr(“value”)').extract_first()
       3)selector对象(通过xpath方法调用返回的是seletor列表)
                         extract()
                             提取selector对象的值
                             如果提取不到值 那么会报错
                             使用xpath请求到的对象是一个selector对象,需要进一步使用extract()方法拆包,转换为unicode字符串
                  extract_first()
                              提取seletor列表中的第一个值
                              如果提取不到值 会返回一个空值
                             返回第一个解析到的值,如果列表为空,此种方法也不会报错,会返回一个空值
                  xpath()
                  css()
                             注意:每一个selector对象可以再次的去使用xpath或者css方法

3.yield

1.带有yield的函数不再是一个普通函数,而是一个生成器generator,可用于迭代
2.yield是一个类似return的关键字,迭代一次遇到yield时就返回yield后面(右边)的值。重点是:下一次迭代
时,从上一次迭代遇到的yield后面的代码(下一行)开始执行

3.简要理解:yield就是return返回一个值,并且记住这个返回的位置,下次迭代就从这个位置后(下一行)开始

4.Mysql

https://dev.mysql.com/downloads/windows/installer/5.7.html)
https://jingyan.baidu.com/album/d7130635f1c77d13fdf475df.html)

5.pymysql****的使用步骤

1.pip install pymysql
2.pymysql.connect(host,port,user,password,db,charset)
3.conn.cursor()
4.cursor.execute()

6.CrawlSpider

 1.继承自scrapy.Spider
2.独门秘笈
    CrawlSpider可以定义规则,再解析html内容的时候,可以根据链接规则提取出指定的链接,然后再向这些链接发送请求
    所以,如果有需要跟进链接的需求,意思就是爬取了网页之后,需要提取链接再次爬取,使用CrawlSpider是非常合适的
    
     3.提取链接
    链接提取器,在这里就可以写规则提取指定链接
scrapy.linkextractors.LinkExtractor(
     allow = (),           # 正则表达式  提取符合正则的链接
     deny = (),            # (不用)正则表达式  不提取符合正则的链接
     allow_domains = (),   # (不用)允许的域名
     deny_domains = (),    # (不用)不允许的域名
     restrict_xpaths = (), # xpath,提取符合xpath规则的链接
     restrict_css = ()     # 提取符合选择器规则的链接)
4.模拟使用
        正则用法:links1 = LinkExtractor(allow=r'list_23_\d+\.html')
        xpath用法:links2 = LinkExtractor(restrict_xpaths=r'//div[@class="x"]')        css用法:links3 = LinkExtractor(restrict_css='.x')
5.提取连接
        link.extract_links(response)
  6.注意事项
    【注1】callback只能写函数名字符串, callback='parse_item'
    【注2】在基本的spider中,如果重新发送请求,那里的callback写的是   callback=self.parse_item 【注‐
    

7.CrawlSpider****案例

1.创建项目:scrapy startproject dushuproject
2.跳转到spiders路径  cd\dushuproject\dushuproject\spiders 3.创建爬虫类:scrapy genspider ‐t crawl read www.dushu.com 4.items
5.spiders
6.settings
7.pipelines
        数据保存到本地
        数据保存到mysql数据库

**8.**数据入库

1)settings配置参数:
             DB_HOST = '192.168.231.128'              DB_PORT = 3306
              DB_USER = 'root'
              DB_PASSWORD = '1234'
              DB_NAME = 'test'
              DB_CHARSET = 'utf8'
   (2)管道配置
              from scrapy.utils.project import get_project_settings               import pymysql
              class MysqlPipeline(object):
                 
                   #__init__方法和open_spider的作用是一样的   
                  #init是获取settings中的连接参数
                  def __init__(self):
                      settings = get_project_settings()
                      self.host = settings['DB_HOST']
                      self.port = settings['DB_PORT']
                      self.user = settings['DB_USER']
                      self.pwd = settings['DB_PWD']
                      self.name = settings['DB_NAME']
                      self.charset = settings['DB_CHARSET']
 
                      self.connect()
             # 连接数据库并且获取cursor对象
                 def connect(self):
                      self.conn = pymysql.connect(host=self.host,
                                                 port=self.port,
                                                 user=self.user,
                                                 password=self.pwd,
                                                 db=self.name,
                                                 charset=self.charset)
                      self.cursor = self.conn.cursor()
 
                
                def process_item(self, item, spider):
                    sql = 'insert into book(image_url, book_name, author, info) values("%s", "%s", "%s", "%s")' % (item['image_url'], item['book_name'], item['author'], item['info'])
                    
                    sql = 'insert into book(image_url,book_name,author,info) values
 ("{}","{}","{}","{}")'.format(item['image_url'], item['book_name'], item['author'], 
item['info'])
                    # 执行sql语句
                    self.cursor.execute(sql)
                    self.conn.commit()
                    return item
            
                 def close_spider(self, spider):
                    self.conn.close()
                    self.cursor.close()
                

**9.**日志信息和日志等级

1)日志级别:

            CRITICAL:严重错误
            ERROR:   一般错误
            WARNING: 警告
            INFO:     一般信息
            DEBUG:   调试信息
            
            默认的日志等级是DEBUG
            只要出现了DEBUG或者DEBUG以上等级的日志            那么这些日志将会打印
            (2)settings.py文件设置:
           默认的级别为DEBUG,会显示上面所有的信息
                       在配置文件中  settings.py
            LOG_FILE  : 将屏幕显示的信息全部记录到文件中,屏幕不再显示,注意文件后缀一定是.log             LOG_LEVEL : 设置日志显示的等级,就是显示哪些,不显示哪些

10.scrapypost****请求

1)重写start_requests方法:

        def start_requests(self)
 (2) start_requests的返回值:
     scrapy.FormRequest(url=url, headers=headers, callback=self.parse_item, formdata=data)            url: 要发送的post地址
            headers:可以定制头信息
            callback: 回调函数   
            formdata: post所携带的数据,这是一个字典

**11.**代理

1)到settings.py中,打开一个选项

​    DOWNLOADER_MIDDLEWARES = {

​      'postproject.middlewares.Proxy': 543,

​    }

2)到middlewares.py中写代码

        def process_request(self, request, spider):
            request.meta['proxy'] = 'https://113.68.202.10:9999'           
            return None

对应代码示例

# 单行注释
# 打印了一句话
# 一般情况下 注释是在代码的上面书写的
# 我是一个单行注释
print('中国是一个美丽的国家')#有的时候也会将单行注释写在代码的后面
# print('你不好使') 因为你把代码写在了注释的后面



# 多行注释
'''
桃花坞里桃花庵
桃花庵下种桃树
print('哈哈')
print('嘿嘿')
'''


# ctrl + ?
# 重复的值 书写/修改起来都很麻烦

# 在不使用变量的情况下
print('今天的天气很好,晴天了')
print('今天的天气很好,晴天了')
print('今天的天气很好,晴天了')
print('今天的天气很好,晴天了')


# 在使用变量的情况下
# 变量的格式: 变量的名字 = 变量的值

weather = '今天的天气很好,晴天了1111'

print(weather)
print(weather)
print(weather)
print(weather)

# 应用场景
img = 'https://item.jd.com/10027680626445.html'
print(img)

# 数据类型
# Number     数值
#      int
#      float
# boolean    布尔
# string     字符串
# list       列表
# tuple      元组
# dict       字典

# 变量类型的基本使用
# Number     数值
#      int
money = 5000
#      float
money1 = 1.2

# boolean    布尔
# 流程控制语句
# 性别的变量
# 性别在实际的企业级开发中 使用的单词是sex  gender
# 男  True
sex = True
gender = False

# string     字符串
# 字符串 使用的是单引号 或者双引号
s = '苍茫的大海上有一只海燕 你可长点心吧'
s1 = "嘀嗒嘀嗒嘀"
# 不允许一单一双 屌丝写法
# s2 = '哈哈哈"
# s3 = "呵呵呵'

# 单引号和双引号的嵌套
s4 = '"嘿嘿嘿"'
print(s4)
s5 = "'嘿嘿'"
print(s5)

# 单引号套单引号  双引号套双引号
# s6 = ''行还是不行呢''
# s7 = ""行还是不行呢""



# list  列表
# tuple 元组
# dict  字典


# list  列表
# 应用场景:当获取到了很多个数据的时候 那么我们可以将他们存储到列表中 然后直接使用列表访问
name_list = ['周杰伦','科比']
print(name_list)

# tuple 元组
age_tuple = (18,19,20,21)
print(age_tuple)

# dict  字典
# 应用场景:scrapy框架使用
# 格式:变量的名字 = {key:value,key1:value1}
person = {'name':'红浪漫','age':18}
print(person)

# 要求必须掌握 列表 元组  字典的格式
# int
# float
# boolean
# string
# list
# tuple
# dict
# type方法判断变量的数据类型
# 格式:type(变量)




# int
a = 1
print(a)
# <class 'int'>
print(type(a))

# float
b = 1.2
print(b)
# <class 'float'>
print(type(b))

# boolean
c = True
print(c)
# <class 'bool'>
print(type(c))


# string
d = '中国'
print(d)
# <class 'str'>
print(type(d))

# list
e = [1,2,3,4]
print(e)
# <class 'list'>
print(type(e))


# tuple
f = (1,2,3,4,5)
print(f)
# <class 'tuple'>
print(type(f))

# dict
g = {'name':'zs'}
print(g)
# <class 'dict'>
print(type(g))
# 1. 标识符由字母、下划线和数字组成,且数字不能开头。
# 2. 严格区分大小写。
# 3. 不能使用关键字。


# 大驼峰 小驼峰 命名法   下划线

# 常见的关键字 了解即可

# 标识符由字母、下划线和数字组成
a_1 = 1
print(a_1)

# 数字不能开头
# 1_a = 2
# print(1_a)

# 不能有除了字母 _ 数字之外的数据
# a_1_$ = 1
# print(a_1_$)

# 2. 严格区分大小写。
# Animal = 1
# print(animal)

# 3. 不能使用关键字。
# for = 1
# print(for)



# 转换为整型
# str --> int
# a = '123'
# print(type(a))
# # 将字符串转换为整数
# b = int(a)
# print(type(b))

# float --> int
# a = 1.63
# print(type(a))
# 如果我们将float转为整数 那么会返回的是小数点前面的数据
# b = int(a)
# print(b)
# print(type(b))

# boolean --> int
# 强制类型转换为谁 就写什么方法
# True ---> 1   False ---> 0
# a = False
# print(type(a))
# b = int(a)
# print(b)
# print(type(b))


# 123.456 和 12ab 字符串,都包含非法字符,不能被转换成为整数,会报错
# 以下 如果字符串当中包含了非法的字符 则报错
# a = '1.23'
# print(type(a))
# b = int(a)
# print(b)

# a = '12ab'
# print(type(a))
# b = int(a)
# print(b)

# 当我们在爬虫的时候大部分获取的都是字符串数据类型

# a = '12.34'
# print(type(a))
# 将字符串类型的数据转换为浮点数
# b = float(a)
# print(b)
# print(type(b))


a = 666
print(a)
print(type(a))

b = float(a)
print(b)
print(type(b))

# 整型转换为字符串   大部分的应用场景

# 整数转换为字符串
# a = 80
# print(type(a))
# # 强制类型转换为字符串的方法是str()
# b = str(a)
# print(b)
# print(type(b))

# 浮点数转换为字符串
# a = 1.2
# print(type(a))
# b = str(a)
# print(b)
# print(type(b))

# 布尔类型转换为字符串
a = True
print(type(a))
b = str(a)
print(b)
print(type(b))



# 如果对非0的整数(int 包含正数和负数)进行bool类型的转换 那么就全都是True
# a = 1
# print(type(a))
# 将整数变成布尔类型的数据
# b = bool(a)
# print(b)
# print(type(b))

# a = 2
# print(type(a))
# b = bool(a)
# print(b)
# print(type(b))

# a = -1
# print(type(a))
#
# b = bool(a)
# print(b)
# print(type(b))

# a = 0
# print(type(a))
# 在整数的范围内 0强制类型转换为bool类型的结果是false
# b = bool(a)
# print(b)
# print(type(b))

# 浮点数
# 将浮点数转换为bool类型的数据的时候  正的浮点数和负的浮点数的结果是true
# 如果是0.0 那么结果是false
# a = 1.0
# print(type(a))
# b = bool(a)
# print(b)
# print(type(b))

# a = -1.0
# # print(type(a))
# # b = bool(a)
# # print(b)
# # print(type(b))

# a = 0.0
# print(type(a))
# b = bool(a)
# print(b)
# print(type(b))

# 字符串
# 只要字符串中有内容 那么在强制类型转换为bool的时候 那么就返回True
# a = '网红截聊天的图'
# print(type(a))
# b = bool(a)
# print(b)
# print(type(b))

# a = '     '
# print(type(a))
# b = bool(a)
# print(b)
# print(type(b))

# a = ''
# print(type(a))
# b = bool(a)
# print(b)
# print(type(b))

# a = ""
# print(type(a))
# b = bool(a)
# print(b)
# print(type(b))

# 列表
# 只要列表中有数据 那么强制类型转换为bool的时候 就返回True
# a = ['吴亦凡','鹿晗','张艺兴','黄子韬']
# print(type(a))
# b = bool(a)
# print(b)
# print(type(b))

# 如果列表中什么数据都没有的情况下 那么返回的是False
# a = []
# print(type(a))
# b = bool(a)
# print(b)
# print(type(b))

# 元组
# 只要元组中有数据 那么强制类型转换为bool的时候 就会返回True
# a = ('李逵','林冲','卢俊义','武松','潘金莲')
# print(type(a))
# b = bool(a)
# print(b)
# print(type(b))

# 如果元组中没有数据的话 那么就返回False
# a = ()
# print(type(a))
# b = bool(a)
# print(b)
# print(type(b))

# 字典
# 只要字典中有内容 那么在强制类型转换为bool的时候 就会返回True
# a = {'name':'武大郎'}
# print(type(a))
# b = bool(a)
# print(b)
# print(type(b))

# 如果在字典中没有数据的话 那么返回的就是False
# a = {}
# print(type(a))
# b = bool(a)
# print(b)
# print(type(b))

# 什么情况下是False
print(bool(0))
print(bool(0.0))
print(bool(''))
print(bool(""))
print(bool([]))
print(bool(()))
print(bool({}))
a = 3
b = 2

# print(a + b)
#
# print(a - b)
#
# print(a * b)
#
# print(a / b)
# # 取整
# print(a // b)
# # 取余
# print(a % b)
# # 指数  幂
# print(a ** b)
#
# print((5 + 1) * 2)

# 扩展
# 字符串的加法 是进行拼接的
# a = '123'
# b = '456'
# print(a + b)

# 在python中 +两端都是字符串才可以进行加法运算
# a = '123'
# b = 456
# # print(a + b)
# print(a + str(b))

# 字符串的乘法 是将字符串重复多少次
a = '我爱你 你爱我 蜜雪冰城甜蜜蜜'
print(a * 3)

a = 10
print(a)


b = c = 20
print(b)
print(c)

# 多个变量赋值(使用逗号分隔)
d,e,f = 1,2,3
print(d)
print(e)
print(f)


a = 1
# a加上一个2 打印结果
# a = a + 2
# print(a)

a += 2   # a = a + 2
print(a)

b = 1
# b 乘以一个3 打印结果
# b = b * 3
# print(b)

b *= 3  # b = b * 3
print(b)

c = 2
# c 减去一个1 打印结果
# c = c - 1
# print(c)

c -= 1  # c = c - 1
print(c)


d = 3

# d 除以一个2 打印结果
# d = d / 2
# print(d)

d /= 2 # d = d / 2
print(d)

e = 3

# e 整除一个2 打印结果
# e = e // 2
# print(e)

e //= 2  # e = e // 2
print(e)

# %  取余  取模  模余
f = 3
# f 对5来取余数 打印结果
# f = f % 5
# print(f)

f %= 5 # f = f % 5
print(f)


g = 5

# 求一下5的3次幂
# g = g ** 3
# print(g)

g **= 3   # g = g ** 3
print(g)

# +=  -+  *=  /=  //=  %=  **=
# 比较运算符返回的都是boolean类型的数据

# == 恒等   判断==两边的变量是否是一致
# a = 10
# b = 10
# print(a == b)

# != 不等  判断!=两边的变量是否不一致
# a = 10
# b = 10
# print(a != b)
# 扩展:<>  python2版本使用 python3 遗弃
# print(10 <> 20)

# > 大于
print(10 > 20)
print(10 > 5)

# >= 大于等于
print(10 >= 10)
print(10 >= 5)
print(10 >= 20)

# < 小于
print(10 < 20)
print(10 < 5)

# <= 小于等于
print(10 <= 10)
print(10 <= 20)


# 比较运算符  ==  !=  > >= < <=
# 逻辑运算符  and 与  or 或  not 非

# and 与
# and两边的数据 必须全部都是true的时候 才会返回true 只要有一端返回的是false 那么就返回false
# and两端都是false的时候 返回的是false
print(10 > 20 and 10 > 11)
# and一端是true 一端是false 返回的是false
print(10 > 5 and 10 >11)
# and一端返回的是false 一端返回的是true  返回的是false
print(10 > 11 and 10 > 5)
# and 两端返回的都是true则返回的是的true
print(10 > 5 and 10 > 6)

# or 或者
# or的两端只要有一端是true 那么结果就是true
# or的两端都是false 则返回的是false
print(10 > 20 or 10 > 21)
# or的两端前面的是true  后面的是false 那么返回的是true
print(10 > 5 or 10 > 20)
# or的两端 前面的是false 后面的是true  那么返回的是true
print(10 > 20 or 10 > 5)
# or的两端都是true  那么返回的是true
print(10 > 5 or 10 > 6)

# not  非  取反
print(not True)
print(not False)
print(not (10 > 20))



# and的性能优化
# a = 36
# a > 10 and print('hello world')
# and的性能优化 当and前面的结果是false的情况下 那么后面的代码就不再执行了
# a < 10 and print('hello world')


# or的性能优化
# or 只要有一方为true 那么结果就是true
a = 38

# a > 39 or print('你好世界')
a > 37 or print('你好 世界')


# and 短路与
# or  短路或





# 普通输出
print('故事里的小黄花,从出生那年就飘着')

# 格式化输出
# scrapy框架的时候   excel文件  mysql  redis
age = 18
name = '红浪漫晶哥'

# %s 代表的是字符串    %d 代表的是数值
print('我的名字是%s,我的年龄是%d' % (name,age))


# password = input('请输入您的银行卡密码')
# print('我的密码是:%s' % password)

name = input('请输入您的名字')
print('我的名字是:%s' % name)


# if关键字的语句结构
# if 判断条件:
#         代码(如果判断条件为true的时候执行if下面的内容)

age = 17

# 吉多  abc语言
# 如果您的年龄大于18了 那么你就可以开车了
if age > 18:
    print('你可以开车了')

# True代表的是男  False代表的是女
gender = True

if gender == True:
    # if下面的代码 必须是一个tab键 或者四个空格
    print('你是一个男性')



# 在控制台上输入一个年龄  如果您的年龄大于18了 那么打印可以去网吧了

# input返回的是字符串类型
age = input('请输入您的年龄')

# 字符串和整数int是不可以比较的
if int(age) > 18:
    print('您成年了,可以去网吧了')

# 案例中考察了三个知识点
# (1) 控制台输入
# (2) 强制类型转换
# (3) int和str是不能比较的
# ifelse的语法
# if 判断条件:
#       判断条件为true的时候执行的代码
# else:
#       判断条件为false的时候执行的代码


age = 17

if age > 18:
    print('你可以去网吧了')
else:
    print('回家写作业去吧')

# 在控制台上输入一个年龄   如果您的年龄大于18了  那么输出 欢迎光临红浪漫 男宾一位
# 否则那么输出  回家洗洗睡

age = int(input('请输入您的年龄'))

if age > 18:
    print('欢迎光临红浪漫,男宾一位')
else:
    print('洗洗睡吧')
# 在控制台上输入您的成绩分数
# 如果你考了90以上  成绩为优秀
# 如果你考了80以上  成绩为良好
# 如果你考了70以上  成绩为中等
# 如果你考了60以上  成绩为合格
# 否则            成绩为不合格


# score = int(input('请输入您的分数'))

# if score >= 90:
#     print('优秀')
# if score >= 80:
#     print('良好')
# if score >= 70:
#     print('中等')
# if score >= 60:
#     print('及格')
# if score < 60:
#     print('不及格')

# elif
score = int(input('请输入您的成绩'))

if score >= 90:
    print('优秀')
elif score >= 80:
    print('良好')
elif score >= 70:
    print('中等')
elif score >= 60:
    print('及格')
else:
    print('不及格')

# 循环字符串
# range(5)
# range(1,6)
# range(1,10,3)
# 循环一个列表


# 一个一个的输出 叫做循环 也叫做遍历
# for
# 格式:  for 变量  in 要遍历的数据:
#             方法体


# 循环字符串
# s = 'china'
# i是字符串中一个又一个的字符的变量
# s是代表的是要遍历的数据
# for i in s:
#     print(i)


# range(5)
# range方法的结果 一个可以遍历的对象
# range(5)  0~4  左闭右开区间(0,5)
# for i in range(5):
#     print(i)


# range(1,6)
# range(起始值,结束值)
# 左闭右开区间
# for i in range(1,6):
#     print(i)


# range(1,10,3)
# range(起始值,结束值,步长)
# 1  4  7  10
# 左闭右开区间
# for i in range(1,11,3):
#     print(i)


# 应用场景  会爬取一个列表返回给我们
# 循环一个列表
a_list = ['周杰伦','林俊杰','陶喆','庞龙']

# 遍历列表中的元素
# for i in a_list:
#     print(i)

# 遍历列表中的下标

# 判断列表中的元素的个数
# print(len(a_list))
# 0 1 2
for i in  range(len(a_list)):
    print(i)

# - 获取长度:len                     len函数可以获取字符串的长度。
# - 查找内容:find                    查找指定内容在字符串中是否存在,如果存在就返回该内容在字符串中第一次出现的开始位置索引值,如果不存在,则返回-1.
# - 判断:startswith,endswith        判断字符串是不是以谁谁谁开头/结尾
# - 计算出现次数:count                返回 str在start和end之间 在 mystr里面出现的次数
# - 替换内容:replace                 替换字符串中指定的内容,如果指定次数count,则替换不会超过count次。
# - 切割字符串:split                  通过参数的内容切割字符串
# - 修改大小写:upper,lower           将字符串中的大小写互换
# -  空格处理:strip                   去空格
# - 字符串拼接:join                   字符串拼接

# len  length的缩写  长度
s = 'china'
print(len(s))

s1 = 'china'
print(s1.find('a'))

s2 = 'china'
print(s2.startswith('h'))
print(s2.endswith('n'))

s3 = 'aaabb'
print(s3.count('b'))

s4 = 'cccdd'
print(s4.replace('c','d'))

s5 = '1#2#3#4'
print(s5.split('#'))

s6 = 'china'
print(s6.upper())

s7 = 'CHINA'
print(s7.lower())

s8 = '   a   '
print(len(s8))

print(len(s8.strip()))

s9 = 'a'
print(s9.join('hello'))




# append  追加   在列表的最后来添加一个对象/数据
food_list = ['铁锅炖大鹅','酸菜五花肉']
print(food_list)

food_list.append('小鸡炖蘑菇')
print(food_list)


# insert  插入
char_list = ['a','c','d']
print(char_list)
# index的值就是你想插入数据的那个下标
char_list.insert(1,'b')
print(char_list)


# extend
num_list = [1,2,3]
num1_list = [4,5,6]

num_list.extend(num1_list)
print(num_list)



city_list = ['北京','上海','深圳','武汉','西安']

print(city_list)

# 将列表中的元素的值修改
# 可以通过下标来修改,注意列表中的下标是从0开始的
city_list[4] = '大连'
print(city_list)


# in 是判断某一个元素是否在某一个列表中
# food_list = ['锅包肉','汆白肉','东北乱炖']

# 判断一下在控制台输入的那个数据 是否在列表中
# food = input('请输入您想吃的食物')
#
# if food in food_list:
#     print('在')
# else:
#     print('不在,一边拉去')


# not in

ball_list = ['篮球','台球']

# 在控制台上输入你喜欢的球类 然后判断是否不在这个列表中
ball = input('请输入您喜欢的球类')

if ball not in ball_list:
    print('不在')
else:
    print('在')


# a_list = [1,2,3,4,5]
#
# print(a_list)

# 根据下标来删除列表中的元素
# 爬取的数据中 有个别的数据 是我们不想要的 那么我们就可以通过下标的方式来删除
# del a_list[2]
# print(a_list)


# b_list = [1,2,3,4,5]
# print(b_list)
# pop是删除列表中的最后一个元素
# b_list.pop()
#
# print(b_list)


c_list = [1,2,3,4,5]
print(c_list)

# 根据元素来删除列表中的数据
c_list.remove(3)
print(c_list)

#
# a_tuple = (1,2,3,4)
#
# print(a_tuple[0])
# print(a_tuple[1])

# 元组是不可以修改里面的内容的
# a_tuple[3] = 5
# print(a_tuple)

# a_list = [1,2,3,4]
#
# print(a_list[0])
#
# a_list[3] = 5
# print(a_list)
# 列表中的元素是可以修改的 而元组中的元素是不可以被修改



a_tuple = (5)

print(type(a_tuple))

# 当元组中只要一个元素的时候  那么他是整型数据
# 定义只有一个元素的元组,需要在唯一的元素后写一个逗号
b_tuple = (5,)
print(type(b_tuple))





s ='hello world'

# 在切片中直接写一个下标
print(s[0])

# 左闭右开区间   包含坐标的数据 不包含右边的数据
print(s[0:4])

# 是从起始的值开始  一直到末尾
print(s[1:])

# 是下标为0的索引的元素开始 一直到第二参数为止   遵循左闭右开区间
print(s[:4])

# hello  world
# 从下标为0的位置开始 到下标为6的位置结束  每次增长2个长度
print(s[0:6:2])


# 定义一个字典
person = {'name':'吴签','age':28}

# 访问person的name
# print(person['name'])
# print(person['age'])

# 使用[]的方式,获取字典中不存在的key的时候  会发生异常   keyerror
# print(person['sex'])

# 不能使用.的方式来访问字典的数据
# print(person.name)


# print(person.get('name'))
# print(person.get('age'))

# 使用.的方式,获取字典中不存在的key的时候  会返回None值
print(person.get('sex'))




person = {'name':'张三','age':18}


# 修改之前的字典
print(person)

# 修改name的值为法外狂徒
person['name'] = '法外狂徒'

# 修改之后的字典
print(person)


person = {'name':'老马'}

print(person)

# 给字典添加一个新的key value
# 如果使用变量名字['键'] = 数据时  这个键如果在字典中不存在  那么就会变成新增元素
person['age'] = 18

# 如果这个键在字典中存在 那么就会变成这个元素
person['name'] = '阿马'

print(person)


# del
#    (1) 删除字典中指定的某一个元素
person = {'name':'老马','age':18}

# 删除之前
# print(person)
#
# del person['age']
#
# # 删除之后
# print(person)

#   (2) 删除整个字典
# 删除之前
# print(person)
#
# del person
#
# # 删除之后
# print(person)


# clear
#   (3) 清空字典 但是保留字典对象
print(person)

# 清空指的是将字典中所有的数据 都删除掉  而保留字典的结构
person.clear()

print(person)


# 遍历--》就是数据一个一个的输出

person = {'name':'阿马','age':18,'sex':'男'}

# (1) 遍历字典的key
# 字典.keys() 方法 获取的字典中所有的key值  key是一个变量的名字 我们可以随便起
# for key in person.keys():
#     print(key)

# (2) 遍历字典的value
# 字典.values()方法  获取字典中所有的value值   value也是一个变量 我们可以随便命名
# for value in person.values():
#     print(value)

# (3) 遍历字典的key和value
# for key,value in person.items():
#     print(key,value)


# (4) 遍历字典的项/元素
for item in person.items():
    print(item)





# print('欢迎马大哥光临红浪漫')
# print('男宾2位')
# print('欢迎下次光临')
#
# print('欢迎马大哥光临红浪漫')
# print('男宾2位')
# print('欢迎下次光临')
#
# print('欢迎马大哥光临红浪漫')
# print('男宾2位')
# print('欢迎下次光临')
#
# print('欢迎马大哥光临红浪漫')
# print('男宾2位')
# print('欢迎下次光临')


# 很多重复的业务逻辑 重复出现的时候 我们可以使用函数

# 定义函数
def f1():
    print('欢迎马大哥光临红浪漫')
    print('男宾2位')
    print('欢迎下次光临')

# 调用函数
f1()

f1()




# 使用函数来计算1和2的和
# def sum():
#     a = 1
#     b = 2
#     c = a + b
#     print(c)
#
# sum()


def sum(a,b):
    c = a + b
    print(c)


# 位置参数   按照位置一一对应的关系来传递参数
sum(1,2)

sum(100,200)


# 关键字传参
sum(b = 200,a = 100)


# 定义函数的时候  sum(a,b)  我们称a 和 b 为形式参数  简称形参
# 调用函数的时候  sum(1,2) 我们称1 和 2 为实际参数  简称实参



# 返回值的关键字是return,存在函数中

# def buyIceCream():
#
#     return '冰激凌'
#
# # 使用一个变量来接受函数的返回值
# food = buyIceCream()
#
# print(food)

# 案例练习
# 定义一个函数 然后让函数计算两个数值的和  并且返回这个计算之后的结果

def sum(a,b):
    c = a + b
    return c

a = sum(123,456)

print(a)



# 局部变量:在函数的内部定义的变量  我们称之为局部变量
# 特点:其作用域范围是函数内部,而函数的外部是不可以使用

#
# def f1():
#     # 在函数内部定义的变量 我们叫做局部变量
#     a = 1
#     print(a)


# f1()
# print(a)


# 全局变量: 定义在函数外部的变量 我们称之为全局变量
# 特点:可以在函数的外部使用,也可以在函数的内部使用

a = 1

print(a)

def f1():
    print(a)

f1()

# 在满足条件的情况 要使用作用域最小的那个变量范围


# 创建一个test.txt文件
# open(文件的路径,模式)
# 模式:  w 可写
#       r 可读
# open('test.txt','w')


# 打开文件
# fp = open('test.txt','w')
# fp.write('hello world')

# 文件夹是不可以创建的  暂时需要手动创建
# fp = open('demo/text.txt','w')
# fp.write('hello shangguigu')

# 文件的关闭
fp = open('a.txt','w')
fp.write('hello')
fp.close()


# 写数据
# write方法

# fp = open('test.txt','a')
#
# fp.write('hello world,i am here\n' * 5)
#
# fp.close()

# 如果我再次来运行这段代码  会打印10次还是打印5呢?
# 如果文件存在 会先情况原来的数据 然后再写
# 我想在每一次执行之后都要追加数据
# 如果模式变为了a 那么就会执行追加的操作


# 读数据
fp = open('test.txt','r')
# 默认情况下 read是一字节一字节的读 效率比较低
# content = fp.read()
# print(content)

# readline是一行一行的读取  但是只能读取一行
# content = fp.readline()
# print(content)


# readlines可以按照行来读取  但是会将所有的数据都读取到 并且以一个列表的形式返回
# 而列表的元素 是一行一行的数据
content = fp.readlines()
print(content)


# fp = open('test.txt','w')
# # 默认情况我们只能将字符串写入到文件中
# fp.write('hello world')
#
# fp.close()


# fp = open('test.txt','w')
# # 默认情况下 对象是无法写入到文件中  如果想写入到文件 那么必须使用序列化操作
# name_list = ['zhangsan','lisi']
#
# fp.write(name_list)


# 序列化的2种方式
# dumps()
# (1)创建一个文件
# fp = open('test.txt','w')
#
# # (2)定义一个列表
# name_list = ['zs','ls']
#
# # 导入json模块到该文件中
# import json
# # 序列化
# # 将python对象 变成 json字符串
# # 我们在使用scrapy框架的时候  该框架会返回一个对象 我们要将对象写入到文件中 就要使用json.dumps
# names = json.dumps(name_list)
#
# # 将names写入到文件中
# fp.write(names)
# fp.close()





# dump
# 在将对象转换为字符串的同时,指定一个文件的对象 然后把转换后的字符串写入到这个文件里


# fp = open('text.txt','w')
# #
# # name_list = ['zs','ls']
# #
# # import json
# # # 相当于names = json.dumps(name_list) 和 fp.write(names)
# # json.dump(name_list,fp)
# #
# # fp.close()



# 反序列化
# 将json的字符串变成一个python对象

# fp = open('text.txt','r')
#
# content = fp.read()
#
# # 读取之后 是字符串类型的
# print(content)
# print(type(content))
#
# # loads
# import json
# # 将json字符串变成python对象
# result = json.loads(content)
# # 转换之后
# print(result)
# print(type(result))



# load

fp = open('text.txt','r')

import json

result = json.load(fp)

print(result)
print(type(result))

fp.close()


# fp = open('text.txt','r')
#
# fp.read()
#
# fp.close()
# 异常的格式
# try:
#     可能出现异常的代码
# except 异常的类型
#     友好的提示

try:
    fp = open('text.txt','r')
    fp.read()
except FileNotFoundError:
    print('系统正在升级,请稍后再试。。。')
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <!--  table  表格
          tr     行
          td     列
    -->
        <table width="200px" height="200px" border="1px">
            <tr>
                <td>
                    姓名
                </td>
                <td>
                    年龄
                </td>
                <td>
                    性别
                </td>
            </tr>

            <tr>
                <td>
                    张三
                </td>

                <td>
                    18
                </td>

                <td>
                    男
                </td>
            </tr>
        </table>

<!--        ul  li 无序列表  爬虫的使用场景非常之多-->

        <ul>
            <li>铁锅炖大鹅</li>
            <li>小鸡炖蘑菇</li>
            <li>锅包肉</li>
        </ul>

<!--        ol li-->

        <ol>
            <li>穿上衣服</li>
            <li>下床</li>
            <li>洗漱</li>
        </ol>

    <a href="http://www.atguigu.com/">尚硅谷</a>

    </body>
</html>

# 使用urllib来获取百度首页的源码
import urllib.request


# (1)定义一个url  就是你要访问的地址
url = 'http://www.baidu.com'

# (2)模拟浏览器向服务器发送请求 response响应
response = urllib.request.urlopen(url)

# (3)获取响应中的页面的源码  content 内容的意思
# read方法  返回的是字节形式的二进制数据
# 我们要将二进制的数据转换为字符串
# 二进制--》字符串  解码  decode('编码的格式')
content = response.read().decode('utf-8')

# (4)打印数据
print(content)


import urllib.request

url = 'http://www.baidu.com'

# 模拟浏览器向服务器发送请求
response = urllib.request.urlopen(url)

# 一个类型和六个方法
# response是HTTPResponse的类型
# print(type(response))

# 按照一个字节一个字节的去读
# content = response.read()
# print(content)

# 返回多少个字节
# content = response.read(5)
# print(content)

# 读取一行
# content = response.readline()
# print(content)

# content = response.readlines()
# print(content)

# 返回状态码  如果是200了 那么就证明我们的逻辑没有错
# print(response.getcode())

# 返回的是url地址
# print(response.geturl())

# 获取是一个状态信息
print(response.getheaders())

# 一个类型 HTTPResponse
# 六个方法 read  readline  readlines  getcode geturl getheaders


import urllib.request

# 下载网页
# url_page = 'http://www.baidu.com'

# url代表的是下载的路径  filename文件的名字
# 在python中 可以变量的名字  也可以直接写值
# urllib.request.urlretrieve(url_page,'baidu.html')

# 下载图片
# url_img = 'https://img1.baidu.com/it/u=3004965690,4089234593&fm=26&fmt=auto&gp=0.jpg'
#
# urllib.request.urlretrieve(url= url_img,filename='lisa.jpg')

# 下载视频
url_video = 'https://vd3.bdstatic.com/mda-mhkku4ndaka5etk3/1080p/cae_h264/1629557146541497769/mda-mhkku4ndaka5etk3.mp4?v_from_s=hkapp-haokan-tucheng&auth_key=1629687514-0-0-7ed57ed7d1168bb1f06d18a4ea214300&bcevod_channel=searchbox_feed&pd=1&pt=3&abtest='

urllib.request.urlretrieve(url_video,'hxekyyds.mp4')


import urllib.request

url = 'https://www.baidu.com'

# url的组成
# https://www.baidu.com/s?wd=周杰伦

# http/https    www.baidu.com   80/443     s      wd = 周杰伦     #
#    协议             主机        端口号     路径     参数           锚点
# http   80
# https  443
# mysql  3306
# oracle 1521
# redis  6379
# mongodb 27017

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'
}

# 因为urlopen方法中不能存储字典 所以headers不能传递进去
# 请求对象的定制
request = urllib.request.Request(url=url,headers=headers)

response = urllib.request.urlopen(request)

content = response.read().decode('utf8')

print(content)



# https://www.baidu.com/s?wd=%E5%91%A8%E6%9D%B0%E4%BC%A6


# 需求 获取 https://www.baidu.com/s?wd=周杰伦的网页源码

import urllib.request
import urllib.parse


url = 'https://www.baidu.com/s?wd='

# 请求对象的定制为了解决反爬的第一种手段
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'
}

# 将周杰伦三个字变成unicode编码的格式
# 我们需要依赖于urllib.parse
name = urllib.parse.quote('周杰伦')

url = url + name

# 请求对象的定制
request = urllib.request.Request(url=url,headers=headers)

# 模拟浏览器向服务器发送请求
response = urllib.request.urlopen(request)

# 获取响应的内容
content = response.read().decode('utf-8')

# 打印数据
print(content)




# urlencode应用场景:多个参数的时候


# https://www.baidu.com/s?wd=周杰伦&sex=男

# import urllib.parse
#
# data = {
#     'wd':'周杰伦',
#     'sex':'男',
#     'location':'中国台湾省'
# }
#
# a = urllib.parse.urlencode(data)
# print(a)


#获取https://www.baidu.com/s?wd=%E5%91%A8%E6%9D%B0%E4%BC%A6&sex=%E7%94%B7的网页源码

import urllib.request
import urllib.parse

base_url = 'https://www.baidu.com/s?'

data = {
    'wd':'周杰伦',
    'sex':'男',
    'location':'中国台湾省'
}

new_data = urllib.parse.urlencode(data)

# 请求资源路径
url = base_url + new_data

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'
}

# 请求对象的定制
request = urllib.request.Request(url=url,headers=headers)

# 模拟浏览器向服务器发送请求
response = urllib.request.urlopen(request)

# 获取网页源码的数据
content = response.read().decode('utf-8')

# 打印数据
print(content)



# post请求

import urllib.request
import urllib.parse


url = 'https://fanyi.baidu.com/sug'

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'
}

data = {
    'kw':'spider'
}

# post请求的参数 必须要进行编码
data = urllib.parse.urlencode(data).encode('utf-8')

# post的请求的参数 是不会拼接在url的后面的  而是需要放在请求对象定制的参数中
# post请求的参数 必须要进行编码
request = urllib.request.Request(url=url,data=data,headers=headers)

# 模拟浏览器向服务器发送请求
response = urllib.request.urlopen(request)

# 获取响应的数据
content = response.read().decode('utf-8')

# 字符串--》json对象

import json

obj = json.loads(content)
print(obj)



# post请求方式的参数 必须编码   data = urllib.parse.urlencode(data)
# 编码之后 必须调用encode方法 data = urllib.parse.urlencode(data).encode('utf-8')
# 参数是放在请求对象定制的方法中  request = urllib.request.Request(url=url,data=data,headers=headers)




import urllib.request
import urllib.parse

url = 'https://fanyi.baidu.com/v2transapi?from=en&to=zh'

headers = {
    # 'Accept': '*/*',
    # 'Accept-Encoding': 'gzip, deflate, br',
    # 'Accept-Language': 'zh-CN,zh;q=0.9',
    # 'Connection': 'keep-alive',
    # 'Content-Length': '135',
    # 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
    'Cookie': 'BIDUPSID=DAA8F9F0BD801A2929D96D69CF7EBF50; PSTM=1597202227; BAIDUID=DAA8F9F0BD801A29B2813502000BF8E9:SL=0:NR=10:FG=1; __yjs_duid=1_c19765bd685fa6fa12c2853fc392f8db1618999058029; REALTIME_TRANS_SWITCH=1; FANYI_WORD_SWITCH=1; HISTORY_SWITCH=1; SOUND_SPD_SWITCH=1; SOUND_PREFER_SWITCH=1; BDUSS=R2bEZvTjFCNHQxdUV-cTZ-MzZrSGxhbUYwSkRkUWk2SkxxS3E2M2lqaFRLUlJoRVFBQUFBJCQAAAAAAAAAAAEAAAA3e~BTveK-9sHLZGF5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFOc7GBTnOxgaW; BDUSS_BFESS=R2bEZvTjFCNHQxdUV-cTZ-MzZrSGxhbUYwSkRkUWk2SkxxS3E2M2lqaFRLUlJoRVFBQUFBJCQAAAAAAAAAAAEAAAA3e~BTveK-9sHLZGF5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFOc7GBTnOxgaW; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; BAIDUID_BFESS=DAA8F9F0BD801A29B2813502000BF8E9:SL=0:NR=10:FG=1; BDRCVFR[feWj1Vr5u3D]=I67x6TjHwwYf0; PSINO=2; H_PS_PSSID=34435_31660_34405_34004_34073_34092_26350_34426_34323_22158_34390; delPer=1; BA_HECTOR=8185a12020018421b61gi6ka20q; BCLID=10943521300863382545; BDSFRCVID=boDOJexroG0YyvRHKn7hh7zlD_weG7bTDYLEOwXPsp3LGJLVJeC6EG0Pts1-dEu-EHtdogKK0mOTHv8F_2uxOjjg8UtVJeC6EG0Ptf8g0M5; H_BDCLCKID_SF=tR3aQ5rtKRTffjrnhPF3-44vXP6-hnjy3bRkX4Q4Wpv_Mnndjn6SQh4Wbttf5q3RymJ42-39LPO2hpRjyxv4y4Ldj4oxJpOJ-bCL0p5aHl51fbbvbURvD-ug3-7qqU5dtjTO2bc_5KnlfMQ_bf--QfbQ0hOhqP-jBRIE3-oJqC8hMIt43f; BCLID_BFESS=10943521300863382545; BDSFRCVID_BFESS=boDOJexroG0YyvRHKn7hh7zlD_weG7bTDYLEOwXPsp3LGJLVJeC6EG0Pts1-dEu-EHtdogKK0mOTHv8F_2uxOjjg8UtVJeC6EG0Ptf8g0M5; H_BDCLCKID_SF_BFESS=tR3aQ5rtKRTffjrnhPF3-44vXP6-hnjy3bRkX4Q4Wpv_Mnndjn6SQh4Wbttf5q3RymJ42-39LPO2hpRjyxv4y4Ldj4oxJpOJ-bCL0p5aHl51fbbvbURvD-ug3-7qqU5dtjTO2bc_5KnlfMQ_bf--QfbQ0hOhqP-jBRIE3-oJqC8hMIt43f; Hm_lvt_64ecd82404c51e03dc91cb9e8c025574=1629701482,1629702031,1629702343,1629704515; Hm_lpvt_64ecd82404c51e03dc91cb9e8c025574=1629704515; __yjs_st=2_MDBkZDdkNzg4YzYyZGU2NTM5NzBjZmQ0OTZiMWRmZGUxM2QwYzkwZTc2NTZmMmIxNDJkYzk4NzU1ZDUzN2U3Yjc4ZTJmYjE1YTUzMTljYWFkMWUwYmVmZGEzNmZjN2FlY2M3NDAzOThhZTY5NzI0MjVkMmQ0NWU3MWE1YTJmNGE5NDBhYjVlOWY3MTFiMWNjYTVhYWI0YThlMDVjODBkNWU2NjMwMzY2MjFhZDNkMzVhNGMzMGZkMWY2NjU5YzkxMDk3NTEzODJiZWUyMjEyYTk5YzY4ODUyYzNjZTJjMGM5MzhhMWE5YjU3NTM3NWZiOWQxNmU3MDVkODExYzFjN183XzliY2RhYjgz; ab_sr=1.0.1_ZTc2ZDFkMTU5ZTM0ZTM4MWVlNDU2MGEzYTM4MzZiY2I2MDIxNzY1Nzc1OWZjZGNiZWRhYjU5ZjYwZmNjMTE2ZjIzNmQxMTdiMzIzYTgzZjVjMTY0ZjM1YjMwZTdjMjhiNDRmN2QzMjMwNWRhZmUxYTJjZjZhNTViMGM2ODFlYjE5YTlmMWRjZDAwZGFmMDY4ZTFlNGJiZjU5YzE1MGIxN2FiYTU3NDgzZmI4MDdhMDM5NTQ0MjQxNDBiNzdhMDdl',
    # 'Host': 'fanyi.baidu.com',
    # 'Origin': 'https://fanyi.baidu.com',
    # 'Referer': 'https://fanyi.baidu.com/?aldtype=16047',
    # 'sec-ch-ua': '"Chromium";v="92", " Not A;Brand";v="99", "Google Chrome";v="92"',
    # 'sec-ch-ua-mobile': '?0',
    # 'Sec-Fetch-Dest': 'empty',
    # 'Sec-Fetch-Mode': 'cors',
    # 'Sec-Fetch-Site': 'same-origin',
    # 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36',
    # 'X-Requested-With': 'XMLHttpRequest',
}

data = {
    'from': 'en',
    'to': 'zh',
    'query': 'love',
    'transtype': 'realtime',
    'simple_means_flag': '3',
    'sign': '198772.518981',
    'token': '5483bfa652979b41f9c90d91f3de875d',
    'domain': 'common',
}
# post请求的参数  必须进行编码 并且要调用encode方法
data = urllib.parse.urlencode(data).encode('utf-8')

# 请求对象的定制
request = urllib.request.Request(url = url,data = data,headers = headers)

# 模拟浏览器向服务器发送请求
response = urllib.request.urlopen(request)

# 获取响应的数据
content = response.read().decode('utf-8')

import json

obj = json.loads(content)
print(obj)

# get请求
# 获取豆瓣电影的第一页的数据 并且保存起来

import urllib.request

url = 'https://movie.douban.com/j/chart/top_list?type=5&interval_id=100%3A90&action=&start=0&limit=20'

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'
}

# (1) 请求对象的定制
request = urllib.request.Request(url=url,headers=headers)

# (2)获取响应的数据
response = urllib.request.urlopen(request)
content = response.read().decode('utf-8')

# (3) 数据下载到本地
# open方法默认情况下使用的是gbk的编码  如果我们要想保存汉字 那么需要在open方法中指定编码格式为utf-8
# encoding = 'utf-8'
# fp = open('douban.json','w',encoding='utf-8')
# fp.write(content)

with open('douban1.json','w',encoding='utf-8') as fp:
    fp.write(content)


# https://movie.douban.com/j/chart/top_list?type=5&interval_id=100%3A90&action=&
# start=0&limit=20

# https://movie.douban.com/j/chart/top_list?type=5&interval_id=100%3A90&action=&
# start=20&limit=20

# https://movie.douban.com/j/chart/top_list?type=5&interval_id=100%3A90&action=&
# start=40&limit=20

# https://movie.douban.com/j/chart/top_list?type=5&interval_id=100%3A90&action=&
# start=60&limit=20

# page    1  2   3   4
# start   0  20  40  60

# start (page - 1)*20


# 下载豆瓣电影前10页的数据
# (1) 请求对象的定制
# (2) 获取响应的数据
# (3) 下载数据

import urllib.parse
import urllib.request

def create_request(page):
    base_url = 'https://movie.douban.com/j/chart/top_list?type=5&interval_id=100%3A90&action=&'

    data = {
        'start':(page - 1) * 20,
        'limit':20
    }

    data = urllib.parse.urlencode(data)

    url = base_url + data

    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'
    }

    request = urllib.request.Request(url=url,headers=headers)
    return request


def get_content(request):
    response = urllib.request.urlopen(request)
    content = response.read().decode('utf-8')
    return content


def down_load(page,content):
    with open('douban_' + str(page) + '.json','w',encoding='utf-8')as fp:
        fp.write(content)




# 程序的入口
if __name__ == '__main__':
    start_page = int(input('请输入起始的页码'))
    end_page = int(input('请输入结束的页面'))

    for page in range(start_page,end_page+1):
#         每一页都有自己的请求对象的定制
        request = create_request(page)
#         获取响应的数据
        content = get_content(request)
#         下载
        down_load(page,content)




# 1页
# http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=cname
# post
# cname: 北京
# pid:
# pageIndex: 1
# pageSize: 10


# 2页
# http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=cname
# post
# cname: 北京
# pid:
# pageIndex: 2
# pageSize: 10

import urllib.request
import urllib.parse

def create_request(page):
    base_url = 'http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=cname'

    data = {
        'cname': '北京',
        'pid':'',
        'pageIndex': page,
        'pageSize': '10'
    }

    data = urllib.parse.urlencode(data).encode('utf-8')

    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'
    }

    request = urllib.request.Request(url=base_url,headers=headers,data=data)

    return request

def get_content(request):
    response = urllib.request.urlopen(request)
    content = response.read().decode('utf-8')
    return content


def down_load(page,content):
    with open('kfc_' + str(page) + '.json','w',encoding='utf-8')as fp:
        fp.write(content)



if __name__ == '__main__':
    start_page = int(input('请输入起始页码'))
    end_page = int(input('请输入结束页码'))

    for page in range(start_page,end_page+1):
        # 请求对象的定制
        request = create_request(page)
        # 获取网页源码
        content = get_content(request)
        # 下载
        down_load(page,content)


import urllib.request
import urllib.error

# url = 'https://blog.csdn.net/sulixu/article/details/1198189491'

url = 'http://www.doudan1111.com'

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'
}

try:
    request = urllib.request.Request(url = url, headers = headers)

    response = urllib.request.urlopen(request)

    content = response.read().decode('utf-8')

    print(content)
except urllib.error.HTTPError:
    print('系统正在升级。。。')
except urllib.error.URLError:
    print('我都说了 系统正在升级。。。')
# 适用的场景:数据采集的时候 需要绕过登陆 然后进入到某个页面
# 个人信息页面是utf-8  但是还报错了编码错误  因为并没有进入到个人信息页面 而是跳转到了登陆页面
# 那么登陆页面不是utf-8  所以报错

# 什么情况下访问不成功?
# 因为请求头的信息不够  所以访问不成功

import urllib.request

url = 'https://weibo.cn/6451491586/info'

headers = {
# ':authority': 'weibo.cn',
# ':method': 'GET',
# ':path': '/6451491586/info',
# ':scheme': 'https',
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
# 'accept-encoding': 'gzip, deflate, br',
'accept-language': 'zh-CN,zh;q=0.9',
'cache-control': 'max-age=0',
#     cookie中携带着你的登陆信息   如果有登陆之后的cookie  那么我们就可以携带着cookie进入到任何页面
'cookie': '_T_WM=24c44910ba98d188fced94ba0da5960e; SUBP=0033WrSXqPxfM725Ws9jqgMF55529P9D9WFxxfgNNUmXi4YiaYZKr_J_5NHD95QcSh-pSh.pSKncWs4DqcjiqgSXIgvVPcpD; SUB=_2A25MKKG_DeRhGeBK7lMV-S_JwzqIHXVv0s_3rDV6PUJbktCOLXL2kW1NR6e0UHkCGcyvxTYyKB2OV9aloJJ7mUNz; SSOLoginState=1630327279',
# referer  判断当前路径是不是由上一个路径进来的    一般情况下 是做图片防盗链
'referer': 'https://weibo.cn/',
'sec-ch-ua': '"Chromium";v="92", " Not A;Brand";v="99", "Google Chrome";v="92"',
'sec-ch-ua-mobile': '?0',
'sec-fetch-dest': 'document',
'sec-fetch-mode': 'navigate',
'sec-fetch-site': 'same-origin',
'sec-fetch-user': '?1',
'upgrade-insecure-requests': '1',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36',
}
# 请求对象的定制
request = urllib.request.Request(url=url,headers=headers)
# 模拟浏览器向服务器发送请求
response = urllib.request.urlopen(request)
# 获取响应的数据
content = response.read().decode('utf-8')

# 将数据保存到本地
with open('weibo.html','w',encoding='utf-8')as fp:
    fp.write(content)


# 需求 使用handler来访问百度  获取网页源码

import urllib.request

url = 'http://www.baidu.com'

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'
}

request = urllib.request.Request(url = url,headers = headers)

# handler   build_opener  open

# (1)获取hanlder对象
handler = urllib.request.HTTPHandler()

# (2)获取opener对象
opener = urllib.request.build_opener(handler)

# (3) 调用open方法
response = opener.open(request)

content = response.read().decode('utf-8')

print(content)
import urllib.request

url = 'http://www.baidu.com/s?wd=ip'

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'
}

# 请求对象的定制
request = urllib.request.Request(url = url,headers= headers)

# 模拟浏览器访问服务器
# response = urllib.request.urlopen(request)

proxies = {
    'http':'118.24.219.151:16817'
}
# handler  build_opener  open
handler = urllib.request.ProxyHandler(proxies = proxies)

opener = urllib.request.build_opener(handler)

response = opener.open(request)

# 获取响应的信息
content = response.read().decode('utf-8')

# 保存
with open('daili.html','w',encoding='utf-8')as fp:
    fp.write(content)

import urllib.request

proxies_pool = [
    {'http':'118.24.219.151:16817'},
    {'http':'118.24.219.151:16817'},
]

import random

proxies = random.choice(proxies_pool)

url = 'http://www.baidu.com/s?wd=ip'

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'
}

request = urllib.request.Request(url = url,headers=headers)

handler = urllib.request.ProxyHandler(proxies=proxies)

opener = urllib.request.build_opener(handler)

response = opener.open(request)

content = response.read().decode('utf-8')

with open('daili.html','w',encoding='utf-8')as fp:
    fp.write(content)
from lxml import etree

# xpath解析
# (1)本地文件                                                etree.parse
# (2)服务器响应的数据  response.read().decode('utf-8') *****   etree.HTML()

# xpath解析本地文件
tree = etree.parse('070_尚硅谷_爬虫_解析_xpath的基本使用.html')

#tree.xpath('xpath路径')

# 查找ul下面的li
# li_list = tree.xpath('//body/ul/li')


# 查找所有有id的属性的li标签
# text()获取标签中的内容
# li_list = tree.xpath('//ul/li[@id]/text()')

# 找到id为l1的li标签  注意引号的问题
# li_list = tree.xpath('//ul/li[@id="l1"]/text()')

# 查找到id为l1的li标签的class的属性值
# li = tree.xpath('//ul/li[@id="l1"]/@class')

# 查询id中包含l的li标签
# li_list = tree.xpath('//ul/li[contains(@id,"l")]/text()')

# 查询id的值以l开头的li标签
# li_list = tree.xpath('//ul/li[starts-with(@id,"c")]/text()')

#查询id为l1和class为c1的
# li_list = tree.xpath('//ul/li[@id="l1" and @class="c1"]/text()')

li_list = tree.xpath('//ul/li[@id="l1"]/text() | //ul/li[@id="l2"]/text()')

# 判断列表的长度
print(li_list)
print(len(li_list))




# (1) 获取网页的源码
# (2) 解析   解析的服务器响应的文件  etree.HTML
# (3)  打印

import urllib.request

url = 'https://www.baidu.com/'

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'
}

# 请求对象的定制
request = urllib.request.Request(url = url,headers = headers)

# 模拟浏览器访问服务器
response = urllib.request.urlopen(request)

# 获取网页源码
content = response.read().decode('utf-8')

# 解析网页源码 来获取我们想要的数据
from lxml import etree

# 解析服务器响应的文件
tree = etree.HTML(content)

# 获取想要的数据  xpath的返回值是一个列表类型的数据
result = tree.xpath('//input[@id="su"]/@value')[0]

print(result)


# (1) 请求对象的定制
# (2)获取网页的源码
# (3)下载


# 需求 下载的前十页的图片
# https://sc.chinaz.com/tupian/qinglvtupian.html   1
# https://sc.chinaz.com/tupian/qinglvtupian_page.html

import urllib.request
from lxml import etree

def create_request(page):
    if(page == 1):
        url = 'https://sc.chinaz.com/tupian/qinglvtupian.html'
    else:
        url = 'https://sc.chinaz.com/tupian/qinglvtupian_' + str(page) + '.html'

    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36',
    }

    request = urllib.request.Request(url = url, headers = headers)
    return request

def get_content(request):
    response = urllib.request.urlopen(request)
    content = response.read().decode('utf-8')
    return content


def down_load(content):
#     下载图片
    # urllib.request.urlretrieve('图片地址','文件的名字')
    tree = etree.HTML(content)

    name_list = tree.xpath('//div[@id="container"]//a/img/@alt')

    # 一般设计图片的网站都会进行懒加载
    src_list = tree.xpath('//div[@id="container"]//a/img/@src2')

    for i in range(len(name_list)):
        name = name_list[i]
        src = src_list[i]
        url = 'https:' + src

        urllib.request.urlretrieve(url=url,filename='./loveImg/' + name + '.jpg')




if __name__ == '__main__':
    start_page = int(input('请输入起始页码'))
    end_page = int(input('请输入结束页码'))

    for page in range(start_page,end_page+1):
        # (1) 请求对象的定制
        request = create_request(page)
        # (2)获取网页的源码
        content = get_content(request)
        # (3)下载
        down_load(content)

{ "store": {
    "book": [
      { "category": "修真",
        "author": "六道",
        "title": "坏蛋是怎样练成的",
        "price": 8.95
      },
      { "category": "修真",
        "author": "天蚕土豆",
        "title": "斗破苍穹",
        "price": 12.99
      },
      { "category": "修真",
        "author": "唐家三少",
        "title": "斗罗大陆",
        "isbn": "0-553-21311-3",
        "price": 8.99
      },
      { "category": "修真",
        "author": "南派三叔",
        "title": "星辰变",
        "isbn": "0-395-19395-8",
        "price": 22.99
      }
    ],
    "bicycle": {
      "author": "老马",
      "color": "黑色",
      "price": 19.95
    }
  }
}

import json
import jsonpath


obj = json.load(open('073_尚硅谷_爬虫_解析_jsonpath.json','r',encoding='utf-8'))

# 书店所有书的作者
# author_list = jsonpath.jsonpath(obj,'$.store.book[*].author')
# print(author_list)

# 所有的作者
# author_list = jsonpath.jsonpath(obj,'$..author')
# print(author_list)

# store下面的所有的元素
# tag_list = jsonpath.jsonpath(obj,'$.store.*')
# print(tag_list)

# store里面所有东西的price
# price_list = jsonpath.jsonpath(obj,'$.store..price')
# print(price_list)

# 第三个书
# book = jsonpath.jsonpath(obj,'$..book[2]')
# print(book)

# 最后一本书
# book = jsonpath.jsonpath(obj,'$..book[(@.length-1)]')
# print(book)

# 	前面的两本书
# book_list = jsonpath.jsonpath(obj,'$..book[0,1]')
# book_list = jsonpath.jsonpath(obj,'$..book[:2]')
# print(book_list)

# 条件过滤需要在()的前面添加一个?
# 	 过滤出所有的包含isbn的书。
# book_list = jsonpath.jsonpath(obj,'$..book[?(@.isbn)]')
# print(book_list)


# 哪本书超过了10块钱
book_list = jsonpath.jsonpath(obj,'$..book[?(@.price>10)]')
print(book_list)


import urllib.request


url = 'https://dianying.taobao.com/cityAction.json?activityId&_ksTS=1629789477003_137&jsoncallback=jsonp138&action=cityAction&n_s=new&event_submit_doGetAllRegion=true'

headers = {
    # ':authority': 'dianying.taobao.com',
    # ':method': 'GET',
    # ':path': '/cityAction.json?activityId&_ksTS=1629789477003_137&jsoncallback=jsonp138&action=cityAction&n_s=new&event_submit_doGetAllRegion=true',
    # ':scheme': 'https',
    'accept': 'text/javascript, application/javascript, application/ecmascript, application/x-ecmascript, */*; q=0.01',
    # 'accept-encoding': 'gzip, deflate, br',
    'accept-language': 'zh-CN,zh;q=0.9',
    'cookie': 'cna=UkO6F8VULRwCAXTqq7dbS5A8; miid=949542021157939863; sgcookie=E100F01JK9XMmyoZRigjfmZKExNdRHQqPf4v9NIWIC1nnpnxyNgROLshAf0gz7lGnkKvwCnu1umyfirMSAWtubqc4g%3D%3D; tracknick=action_li; _cc_=UIHiLt3xSw%3D%3D; enc=dA18hg7jG1xapfVGPHoQCAkPQ4as1%2FEUqsG4M6AcAjHFFUM54HWpBv4AAm0MbQgqO%2BiZ5qkUeLIxljrHkOW%2BtQ%3D%3D; hng=CN%7Czh-CN%7CCNY%7C156; thw=cn; _m_h5_tk=3ca69de1b9ad7dce614840fcd015dcdb_1629776735568; _m_h5_tk_enc=ab56df54999d1d2cac2f82753ae29f82; t=874e6ce33295bf6b95cfcfaff0af0db6; xlly_s=1; cookie2=13acd8f4dafac4f7bd2177d6710d60fe; v=0; _tb_token_=e65ebbe536158; tfstk=cGhRB7mNpnxkDmUx7YpDAMNM2gTGZbWLxUZN9U4ulewe025didli6j5AFPI8MEC..; l=eBrgmF1cOsMXqSxaBO5aFurza77tzIRb8sPzaNbMiInca6OdtFt_rNCK2Ns9SdtjgtfFBetPVKlOcRCEF3apbgiMW_N-1NKDSxJ6-; isg=BBoas2yXLzHdGp3pCh7XVmpja8A8S54lyLj1RySTHq14l7vRDNufNAjpZ2MLRxa9',
    'referer': 'https://dianying.taobao.com/',
    'sec-ch-ua': '"Chromium";v="92", " Not A;Brand";v="99", "Google Chrome";v="92"',
    'sec-ch-ua-mobile': '?0',
    'sec-fetch-dest': 'empty',
    'sec-fetch-mode': 'cors',
    'sec-fetch-site': 'same-origin',
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36',
    'x-requested-with': 'XMLHttpRequest',
}

request = urllib.request.Request(url = url, headers = headers)

response = urllib.request.urlopen(request)

content = response.read().decode('utf-8')

# split 切割
content = content.split('(')[1].split(')')[0]

with open('074_尚硅谷_爬虫_解析_jsonpath解析淘票票.json','w',encoding='utf-8')as fp:
    fp.write(content)

import json
import jsonpath

obj = json.load(open('074_尚硅谷_爬虫_解析_jsonpath解析淘票票.json','r',encoding='utf-8'))

city_list = jsonpath.jsonpath(obj,'$..regionName')

print(city_list)




from bs4 import BeautifulSoup


# 通过解析本地文件 来将bs4的基础语法进行讲解
# 默认打开的文件的编码格式是gbk 所以在打开文件的时候需要指定编码
soup = BeautifulSoup(open('075_尚硅谷_爬虫_解析_bs4的基本使用.html',encoding='utf-8'),'lxml')

# 根据标签名查找节点
# 找到的是第一个符合条件的数据
# print(soup.a)
# 获取标签的属性和属性值
# print(soup.a.attrs)

# bs4的一些函数
# (1)find
# 返回的是第一个符合条件的数据
# print(soup.find('a'))

# 根据title的值来找到对应的标签对象
# print(soup.find('a',title="a2"))

# 根据class的值来找到对应的标签对象  注意的是class需要添加下划线
# print(soup.find('a',class_="a1"))


# (2)find_all  返回的是一个列表 并且返回了所有的a标签
# print(soup.find_all('a'))

# 如果想获取的是多个标签的数据 那么需要在find_all的参数中添加的是列表的数据
# print(soup.find_all(['a','span']))

# limit的作用是查找前几个数据
# print(soup.find_all('li',limit=2))


# (3)select(推荐)
# select方法返回的是一个列表  并且会返回多个数据
# print(soup.select('a'))

# 可以通过.代表class  我们把这种操作叫做类选择器
# print(soup.select('.a1'))

# print(soup.select('#l1'))


# 属性选择器---通过属性来寻找对应的标签
# 查找到li标签中有id的标签
# print(soup.select('li[id]'))

# 查找到li标签中id为l2的标签
# print(soup.select('li[id="l2"]'))


# 层级选择器
#  后代选择器
# 找到的是div下面的li
# print(soup.select('div li'))

# 子代选择器
#  某标签的第一级子标签
# 注意:很多的计算机编程语言中 如果不加空格不会输出内容  但是在bs4中 不会报错 会显示内容
# print(soup.select('div > ul > li'))


# 找到a标签和li标签的所有的对象
# print(soup.select('a,li'))

# 节点信息
#    获取节点内容
# obj = soup.select('#d1')[0]
# 如果标签对象中 只有内容 那么string和get_text()都可以使用
# 如果标签对象中 除了内容还有标签 那么string就获取不到数据 而get_text()是可以获取数据
# 我们一般情况下  推荐使用get_text()
# print(obj.string)
# print(obj.get_text())

# 节点的属性
# obj = soup.select('#p1')[0]
# name是标签的名字
# print(obj.name)
# 将属性值左右一个字典返回
# print(obj.attrs)

# 获取节点的属性
obj = soup.select('#p1')[0]

print(obj.attrs.get('class'))
print(obj.get('class'))
print(obj['class'])



import urllib.request

url = 'https://www.starbucks.com.cn/menu/'

response = urllib.request.urlopen(url)

content = response.read().decode('utf-8')


from bs4 import BeautifulSoup

soup = BeautifulSoup(content,'lxml')

# //ul[@class="grid padded-3 product"]//strong/text()
name_list = soup.select('ul[class="grid padded-3 product"] strong')

for name in name_list:
    print(name.get_text())

import urllib.request

url = 'https://www.jd.com/'

response = urllib.request.urlopen(url)

content = response.read().decode('utf-8')

print(content)

# (1)导入selenium
from selenium import webdriver

# (2) 创建浏览器操作对象

path = 'chromedriver.exe'

browser = webdriver.Chrome(path)

# (3)访问网站
# url = 'https://www.baidu.com'
#
# browser.get(url)

url = 'https://www.jd.com/'

browser.get(url)

# page_source获取网页源码
content = browser.page_source
print(content)




from selenium import webdriver

path = 'chromedriver.exe'
browser = webdriver.Chrome(path)

url = 'https://www.baidu.com'
browser.get(url)

# 元素定位

# 根据id来找到对象
# button = browser.find_element_by_id('su')
# print(button)

# 根据标签属性的属性值来获取对象的
# button = browser.find_element_by_name('wd')
# print(button)

# 根据xpath语句来获取对象
# button = browser.find_elements_by_xpath('//input[@id="su"]')
# print(button)

# 根据标签的名字来获取对象
# button = browser.find_elements_by_tag_name('input')
# print(button)

# 使用的bs4的语法来获取对象
# button = browser.find_elements_by_css_selector('#su')
# print(button)

# button = browser.find_element_by_link_text('直播')
# print(button)


from selenium import webdriver

path = 'chromedriver.exe'
browser = webdriver.Chrome(path)


url = 'http://www.baidu.com'
browser.get(url)


input = browser.find_element_by_id('su')

# 获取标签的属性
print(input.get_attribute('class'))
# 获取标签的名字
print(input.tag_name)

# 获取元素文本
a = browser.find_element_by_link_text('新闻')
print(a.text)




from selenium import webdriver

# 创建浏览器对象
path = 'chromedriver.exe'
browser = webdriver.Chrome(path)

# url
url = 'https://www.baidu.com'
browser.get(url)

import time
time.sleep(2)

# 获取文本框的对象
input = browser.find_element_by_id('kw')

# 在文本框中输入周杰伦
input.send_keys('周杰伦')

time.sleep(2)

# 获取百度一下的按钮
button = browser.find_element_by_id('su')

# 点击按钮
button.click()

time.sleep(2)

# 滑到底部
js_bottom = 'document.documentElement.scrollTop=100000'
browser.execute_script(js_bottom)

time.sleep(2)

# 获取下一页的按钮
next = browser.find_element_by_xpath('//a[@class="n"]')

# 点击下一页
next.click()

time.sleep(2)

# 回到上一页
browser.back()

time.sleep(2)

# 回去
browser.forward()

time.sleep(3)

# 退出
browser.quit()


from selenium import webdriver

path = 'phantomjs.exe'

browser = webdriver.PhantomJS(path)


url = 'https://www.baidu.com'
browser.get(url)

browser.save_screenshot('baidu.png')

import time
time.sleep(2)

input = browser.find_element_by_id('kw')
input.send_keys('昆凌')

time.sleep(3)

browser.save_screenshot('kunling.png')

# from selenium import webdriver
# from selenium.webdriver.chrome.options import Options
#
# chrome_options = Options()
# chrome_options.add_argument('--headless')
# chrome_options.add_argument('--disable-gpu')
#
# # path是你自己的chrome浏览器的文件路径
# path = r'C:\Program Files (x86)\Google\Chrome\Application\chrome.exe'
# chrome_options.binary_location = path
#
# browser = webdriver.Chrome(chrome_options=chrome_options)
#
#
# url = 'https://www.baidu.com'
#
# browser.get(url)
#
# browser.save_screenshot('baidu.png')

# 封装的handless


from selenium import webdriver
from selenium.webdriver.chrome.options import Options

def share_browser():
    chrome_options = Options()
    chrome_options.add_argument('--headless')
    chrome_options.add_argument('--disable-gpu')

    # path是你自己的chrome浏览器的文件路径
    path = r'C:\Program Files (x86)\Google\Chrome\Application\chrome.exe'
    chrome_options.binary_location = path

    browser = webdriver.Chrome(chrome_options=chrome_options)
    return browser

browser = share_browser()

url = 'https://www.baidu.com'

browser.get(url)



import requests


url = 'http://www.baidu.com'


response = requests.get(url=url)

# 一个类型和六个属性
# Response类型
# print(type(response))

# 设置响应的编码格式
# response.encoding = 'utf-8'

# 以字符串的形式来返回了网页的源码
# print(response.text)

# 返回一个url地址
# print(response.url)

# 返回的是二进制的数据
# print(response.content)

# 返回响应的状态码
# print(response.status_code)

# 返回的是响应头
print(response.headers)

# urllib
# (1) 一个类型以及六个方法
# (2)get请求
# (3)post请求   百度翻译
# (4)ajax的get请求
# (5)ajax的post请求
# (6)cookie登陆 微博
# (7)代理


# requests
# (1)一个类型以及六个属性
# (2)get请求
# (3)post请求
# (4)代理
# (5)cookie  验证码


import requests

url = 'https://www.baidu.com/s'

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'
}

data = {
    'wd':'北京'
}


# url  请求资源路径
# params 参数
# kwargs 字典
response = requests.get(url=url,params=data,headers=headers)

content = response.text

print(content)

# 总结:
# (1)参数使用params传递
# (2)参数无需urlencode编码
# (3)不需要请求对象的定制
# (4)请求资源路径中的?可以加也可以不加


import requests

url = 'https://fanyi.baidu.com/sug'

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'
}

data = {
    'kw': 'eye'
}

# url 请求地址
# data 请求参数
# kwargs 字典
response = requests.post(url=url,data=data,headers=headers)

content =response.text

import json

obj = json.loads(content,encoding='utf-8')
print(obj)

# 总结:
# (1)post请求 是不需要编解码
# (2)post请求的参数是data
# (3)不需要请求对象的定制


import requests

url = 'http://www.baidu.com/s?'

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36',
}

data = {
    'wd':'ip'
}


proxy = {
    'http':'212.129.251.55:16816'
}

response = requests.get(url = url,params=data,headers = headers,proxies = proxy)

content = response.text

with open('daili.html','w',encoding='utf-8')as fp:
    fp.write(content)
# 通过登陆  然后进入到主页面


# 通过找登陆接口我们发现 登陆的时候需要的参数很多
# _VIEWSTATE: /m1O5dxmOo7f1qlmvtnyNyhhaUrWNVTs3TMKIsm1lvpIgs0WWWUCQHl5iMrvLlwnsqLUN6Wh1aNpitc4WnOt0So3k6UYdFyqCPI6jWSvC8yBA1Q39I7uuR4NjGo=
# __VIEWSTATEGENERATOR: C93BE1AE
# from: http://so.gushiwen.cn/user/collect.aspx
# email: 595165358@qq.com
# pwd: action
# code: PId7
# denglu: 登录

# 我们观察到_VIEWSTATE   __VIEWSTATEGENERATOR  code是一个可以变化的量

# 难点:(1)_VIEWSTATE   __VIEWSTATEGENERATOR  一般情况看不到的数据 都是在页面的源码中
#     我们观察到这两个数据在页面的源码中 所以我们需要获取页面的源码 然后进行解析就可以获取了
#     (2)验证码

import requests


# 这是登陆页面的url地址
url = 'https://so.gushiwen.cn/user/login.aspx?from=http://so.gushiwen.cn/user/collect.aspx'

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36'
}

# 获取页面的源码
response = requests.get(url = url,headers = headers)
content = response.text

# 解析页面源码  然后获取_VIEWSTATE   __VIEWSTATEGENERATOR
from bs4 import BeautifulSoup

soup = BeautifulSoup(content,'lxml')

# 获取_VIEWSTATE
viewstate = soup.select('#__VIEWSTATE')[0].attrs.get('value')

# 获取__VIEWSTATEGENERATOR
viewstategenerator = soup.select('#__VIEWSTATEGENERATOR')[0].attrs.get('value')


# 获取验证码图片
code = soup.select('#imgCode')[0].attrs.get('src')
code_url = 'https://so.gushiwen.cn' + code

# 有坑
# import urllib.request
# urllib.request.urlretrieve(url=code_url,filename='code.jpg')
# requests里面有一个方法 session()  通过session的返回值 就能使用请求变成一个对象

session = requests.session()
# 验证码的url的内容
response_code = session.get(code_url)
# 注意此时要使用二进制数据  因为我们要使用的是图片的下载
content_code = response_code.content
# wb的模式就是将二进制数据写入到文件
with open('code.jpg','wb')as fp:
    fp.write(content_code)




# 获取了验证码的图片之后 下载到本地 然后观察验证码  观察之后 然后在控制台输入这个验证码 就可以将这个值给
# code的参数 就可以登陆

code_name = input('请输入你的验证码')


# 点击登陆
url_post = 'https://so.gushiwen.cn/user/login.aspx?from=http%3a%2f%2fso.gushiwen.cn%2fuser%2fcollect.aspx'

data_post = {
    '__VIEWSTATE': viewstate,
    '__VIEWSTATEGENERATOR': viewstategenerator,
    'from': 'http://so.gushiwen.cn/user/collect.aspx',
    'email': '595165358@qq.com',
    'pwd': 'action',
    'code': code_name,
    'denglu': '登录',
}

response_post = session.post(url = url, headers = headers, data = data_post)

content_post = response_post.text

with open('gushiwen.html','w',encoding= ' utf-8')as fp:
    fp.write(content_post)


# 难点
# (1) 隐藏域
# (2) 验证码


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

import requests
from hashlib import md5

class Chaojiying_Client(object):

    def __init__(self, username, password, soft_id):
        self.username = username
        password =  password.encode('utf8')
        self.password = md5(password).hexdigest()
        self.soft_id = soft_id
        self.base_params = {
            'user': self.username,
            'pass2': self.password,
            'softid': self.soft_id,
        }
        self.headers = {
            'Connection': 'Keep-Alive',
            'User-Agent': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)',
        }

    def PostPic(self, im, codetype):
        """
        im: 图片字节
        codetype: 题目类型 参考 http://www.chaojiying.com/price.html
        """
        params = {
            'codetype': codetype,
        }
        params.update(self.base_params)
        files = {'userfile': ('ccc.jpg', im)}
        r = requests.post('http://upload.chaojiying.net/Upload/Processing.php', data=params, files=files, headers=self.headers)
        return r.json()

    def ReportError(self, im_id):
        """
        im_id:报错题目的图片ID
        """
        params = {
            'id': im_id,
        }
        params.update(self.base_params)
        r = requests.post('http://upload.chaojiying.net/Upload/ReportError.php', data=params, headers=self.headers)
        return r.json()


if __name__ == '__main__':
	chaojiying = Chaojiying_Client('超级鹰用户名', '超级鹰用户名的密码', '96001')	#用户中心>>软件ID 生成一个替换 96001
	im = open('a.jpg', 'rb').read()													#本地图片文件路径 来替换 a.jpg 有时WIN系统须要//
	print(chaojiying.PostPic(im, 1902))											#1902 验证码类型  官方网站>>价格体系 3.4+版 print 后要加()


# (1) pip install scrapy
# (2) 报错1: building 'twisted.test.raiser' extension
#              error: Microsoft Visual C++ 14.0 is required. Get it with "Microsoft Visual C++
#              Build Tools": http://landinghub.visualstudio.com/visual-cpp-build-tools
#     解决1
#       http://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted
#       Twisted‑20.3.0‑cp37‑cp37m‑win_amd64.whl
#       cp是你的python版本
#       amd是你的操作系统的版本
#       下载完成之后 使用pip install twisted的路径  安装
#       切记安装完twisted 再次安装scrapy

# (3) 报错2  提示python -m pip install --upgrade pip
#      解决2   运行python -m pip install --upgrade pip

# (4) 报错3   win32的错误
#      解决3   pip install pypiwin32

# (5) anaconda
# 进入到scrapy shell的终端  直接在window的终端中输入scrapy shell 域名
# 如果想看到一些高亮 或者 自动补全  那么可以安装ipython  pip install ipython


# scrapy shell www.baidu.com

scrapy代码示例

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

from scrapy import signals

# useful for handling different item types with a single interface
from itemadapter import is_item, ItemAdapter


class ScrapyBaidu091SpiderMiddleware:
    # Not all methods need to be defined. If a method is not defined,
    # scrapy acts as if the spider middleware does not modify the
    # passed objects.

    @classmethod
    def from_crawler(cls, crawler):
        # This method is used by Scrapy to create your spiders.
        s = cls()
        crawler.signals.connect(s.spider_opened, signal=signals.spider_opened)
        return s

    def process_spider_input(self, response, spider):
        # Called for each response that goes through the spider
        # middleware and into the spider.

        # Should return None or raise an exception.
        return None

    def process_spider_output(self, response, result, spider):
        # Called with the results returned from the Spider, after
        # it has processed the response.

        # Must return an iterable of Request, or item objects.
        for i in result:
            yield i

    def process_spider_exception(self, response, exception, spider):
        # Called when a spider or process_spider_input() method
        # (from other spider middleware) raises an exception.

        # Should return either None or an iterable of Request or item objects.
        pass

    def process_start_requests(self, start_requests, spider):
        # Called with the start requests of the spider, and works
        # similarly to the process_spider_output() method, except
        # that it doesn’t have a response associated.

        # Must return only requests (not items).
        for r in start_requests:
            yield r

    def spider_opened(self, spider):
        spider.logger.info('Spider opened: %s' % spider.name)


class ScrapyBaidu091DownloaderMiddleware:
    # Not all methods need to be defined. If a method is not defined,
    # scrapy acts as if the downloader middleware does not modify the
    # passed objects.

    @classmethod
    def from_crawler(cls, crawler):
        # This method is used by Scrapy to create your spiders.
        s = cls()
        crawler.signals.connect(s.spider_opened, signal=signals.spider_opened)
        return s

    def process_request(self, request, spider):
        # Called for each request that goes through the downloader
        # middleware.

        # Must either:
        # - return None: continue processing this request
        # - or return a Response object
        # - or return a Request object
        # - or raise IgnoreRequest: process_exception() methods of
        #   installed downloader middleware will be called
        return None

    def process_response(self, request, response, spider):
        # Called with the response returned from the downloader.

        # Must either;
        # - return a Response object
        # - return a Request object
        # - or raise IgnoreRequest
        return response

    def process_exception(self, request, exception, spider):
        # Called when a download handler or a process_request()
        # (from other downloader middleware) raises an exception.

        # Must either:
        # - return None: continue processing this exception
        # - return a Response object: stops process_exception() chain
        # - return a Request object: stops process_exception() chain
        pass

    def spider_opened(self, spider):
        spider.logger.info('Spider opened: %s' % spider.name)
# Define here the models for your scraped items
#
# See documentation in:
# https://docs.scrapy.org/en/latest/topics/items.html

import scrapy


class ScrapyBaidu091Item(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    pass

# 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


# useful for handling different item types with a single interface
from itemadapter import ItemAdapter


class ScrapyBaidu091Pipeline:
    def process_item(self, item, spider):
        return item

# Scrapy settings for scrapy_baidu_091 project
#
# For simplicity, this file contains only settings considered important or
# commonly used. You can find more settings consulting the documentation:
#
#     https://docs.scrapy.org/en/latest/topics/settings.html
#     https://docs.scrapy.org/en/latest/topics/downloader-middleware.html
#     https://docs.scrapy.org/en/latest/topics/spider-middleware.html

BOT_NAME = 'scrapy_baidu_091'

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


# Crawl responsibly by identifying yourself (and your website) on the user-agent
#USER_AGENT = 'scrapy_baidu_091 (+http://www.yourdomain.com)'

# Obey robots.txt rules
# 注释掉之后 那么就不遵守robots协议了  他是一个君子协议 一般情况下 我们不用遵守
# ROBOTSTXT_OBEY = True

# Configure maximum concurrent requests performed by Scrapy (default: 16)
#CONCURRENT_REQUESTS = 32

# Configure a delay for requests for the same website (default: 0)
# See https://docs.scrapy.org/en/latest/topics/settings.html#download-delay
# See also autothrottle settings and docs
#DOWNLOAD_DELAY = 3
# The download delay setting will honor only one of:
#CONCURRENT_REQUESTS_PER_DOMAIN = 16
#CONCURRENT_REQUESTS_PER_IP = 16

# Disable cookies (enabled by default)
#COOKIES_ENABLED = False

# Disable Telnet Console (enabled by default)
#TELNETCONSOLE_ENABLED = False

# Override the default request headers:
#DEFAULT_REQUEST_HEADERS = {
#   'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
#   'Accept-Language': 'en',
#}

# Enable or disable spider middlewares
# See https://docs.scrapy.org/en/latest/topics/spider-middleware.html
#SPIDER_MIDDLEWARES = {
#    'scrapy_baidu_091.middlewares.ScrapyBaidu091SpiderMiddleware': 543,
#}

# Enable or disable downloader middlewares
# See https://docs.scrapy.org/en/latest/topics/downloader-middleware.html
#DOWNLOADER_MIDDLEWARES = {
#    'scrapy_baidu_091.middlewares.ScrapyBaidu091DownloaderMiddleware': 543,
#}

# Enable or disable extensions
# See https://docs.scrapy.org/en/latest/topics/extensions.html
#EXTENSIONS = {
#    'scrapy.extensions.telnet.TelnetConsole': None,
#}

# Configure item pipelines
# See https://docs.scrapy.org/en/latest/topics/item-pipeline.html
#ITEM_PIPELINES = {
#    'scrapy_baidu_091.pipelines.ScrapyBaidu091Pipeline': 300,
#}

# Enable and configure the AutoThrottle extension (disabled by default)
# See https://docs.scrapy.org/en/latest/topics/autothrottle.html
#AUTOTHROTTLE_ENABLED = True
# The initial download delay
#AUTOTHROTTLE_START_DELAY = 5
# The maximum download delay to be set in case of high latencies
#AUTOTHROTTLE_MAX_DELAY = 60
# The average number of requests Scrapy should be sending in parallel to
# each remote server
#AUTOTHROTTLE_TARGET_CONCURRENCY = 1.0
# Enable showing throttling stats for every response received:
#AUTOTHROTTLE_DEBUG = False

# Enable and configure HTTP caching (disabled by default)
# See https://docs.scrapy.org/en/latest/topics/downloader-middleware.html#httpcache-middleware-settings
#HTTPCACHE_ENABLED = True
#HTTPCACHE_EXPIRATION_SECS = 0
#HTTPCACHE_DIR = 'httpcache'
#HTTPCACHE_IGNORE_HTTP_CODES = []
#HTTPCACHE_STORAGE = 'scrapy.extensions.httpcache.FilesystemCacheStorage'

星巴克代码示例:
import urllib.request


url='https://im.qq.com/index'
respone=urllib.request.urlopen(url)

content=respone.read().decode('utf-8')

print(content)


from bs4 import BeautifulSoup
# soup=BeautifulSoup(content,'lxml')
# name_list=soup.select('https://qq-web.cdn-go.cn/im.qq.com_hybrid_h5_v2/92f39c89/app/news/dist/cdn/index.bundle.js')

78.基本使用:



# from selenium import webbrowser

# browser=webbrowser.Edge()
# browser.get('https://www.baidu.com')

# 导入selenium
from selenium import webdriver

browser = webdriver.Edge()

# 定义并且写入url
browser.get('https://www.baidu.com')
browser.quit()








# 导入selenium
from selenium import webdriver

browser = webdriver.Edge()

# 定义并且写入url
browser.get('https://www.jd.com')
browser.quit()

# 使用:page_source获取网页源码
content=browser.page_source
print(content)

79.元素单位

091DownloaderMiddleware:
# Not all methods need to be defined. If a method is not defined,
# scrapy acts as if the downloader middleware does not modify the
# passed objects.

@classmethod
def from_crawler(cls, crawler):
    # This method is used by Scrapy to create your spiders.
    s = cls()
    crawler.signals.connect(s.spider_opened, signal=signals.spider_opened)
    return s

def process_request(self, request, spider):
    # Called for each request that goes through the downloader
    # middleware.

    # Must either:
    # - return None: continue processing this request
    # - or return a Response object
    # - or return a Request object
    # - or raise IgnoreRequest: process_exception() methods of
    #   installed downloader middleware will be called
    return None

def process_response(self, request, response, spider):
    # Called with the response returned from the downloader.

    # Must either;
    # - return a Response object
    # - return a Request object
    # - or raise IgnoreRequest
    return response

def process_exception(self, request, exception, spider):
    # Called when a download handler or a process_request()
    # (from other downloader middleware) raises an exception.

    # Must either:
    # - return None: continue processing this exception
    # - return a Response object: stops process_exception() chain
    # - return a Request object: stops process_exception() chain
    pass

def spider_opened(self, spider):
    spider.logger.info('Spider opened: %s' % spider.name)

Define here the models for your scraped items

See documentation in:

https://docs.scrapy.org/en/latest/topics/items.html

import scrapy

class ScrapyBaidu091Item(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
pass

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

useful for handling different item types with a single interface

from itemadapter import ItemAdapter

class ScrapyBaidu091Pipeline:
def process_item(self, item, spider):
return item

Scrapy settings for scrapy_baidu_091 project

For simplicity, this file contains only settings considered important or

commonly used. You can find more settings consulting the documentation:

https://docs.scrapy.org/en/latest/topics/settings.html

https://docs.scrapy.org/en/latest/topics/downloader-middleware.html

https://docs.scrapy.org/en/latest/topics/spider-middleware.html

BOT_NAME = ‘scrapy_baidu_091’

SPIDER_MODULES = [‘scrapy_baidu_091.spiders’]
NEWSPIDER_MODULE = ‘scrapy_baidu_091.spiders’

Crawl responsibly by identifying yourself (and your website) on the user-agent

#USER_AGENT = ‘scrapy_baidu_091 (+http://www.yourdomain.com)’

Obey robots.txt rules

注释掉之后 那么就不遵守robots协议了 他是一个君子协议 一般情况下 我们不用遵守

ROBOTSTXT_OBEY = True

Configure maximum concurrent requests performed by Scrapy (default: 16)

#CONCURRENT_REQUESTS = 32

Configure a delay for requests for the same website (default: 0)

See https://docs.scrapy.org/en/latest/topics/settings.html#download-delay

See also autothrottle settings and docs

#DOWNLOAD_DELAY = 3

The download delay setting will honor only one of:

#CONCURRENT_REQUESTS_PER_DOMAIN = 16
#CONCURRENT_REQUESTS_PER_IP = 16

Disable cookies (enabled by default)

#COOKIES_ENABLED = False

Disable Telnet Console (enabled by default)

#TELNETCONSOLE_ENABLED = False

Override the default request headers:

#DEFAULT_REQUEST_HEADERS = {

‘Accept’: ‘text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8’,

‘Accept-Language’: ‘en’,

#}

Enable or disable spider middlewares

See https://docs.scrapy.org/en/latest/topics/spider-middleware.html

#SPIDER_MIDDLEWARES = {

‘scrapy_baidu_091.middlewares.ScrapyBaidu091SpiderMiddleware’: 543,

#}

Enable or disable downloader middlewares

See https://docs.scrapy.org/en/latest/topics/downloader-middleware.html

#DOWNLOADER_MIDDLEWARES = {

‘scrapy_baidu_091.middlewares.ScrapyBaidu091DownloaderMiddleware’: 543,

#}

Enable or disable extensions

See https://docs.scrapy.org/en/latest/topics/extensions.html

#EXTENSIONS = {

‘scrapy.extensions.telnet.TelnetConsole’: None,

#}

Configure item pipelines

See https://docs.scrapy.org/en/latest/topics/item-pipeline.html

#ITEM_PIPELINES = {

‘scrapy_baidu_091.pipelines.ScrapyBaidu091Pipeline’: 300,

#}

Enable and configure the AutoThrottle extension (disabled by default)

See https://docs.scrapy.org/en/latest/topics/autothrottle.html

#AUTOTHROTTLE_ENABLED = True

The initial download delay

#AUTOTHROTTLE_START_DELAY = 5

The maximum download delay to be set in case of high latencies

#AUTOTHROTTLE_MAX_DELAY = 60

The average number of requests Scrapy should be sending in parallel to

each remote server

#AUTOTHROTTLE_TARGET_CONCURRENCY = 1.0

Enable showing throttling stats for every response received:

#AUTOTHROTTLE_DEBUG = False

Enable and configure HTTP caching (disabled by default)

See https://docs.scrapy.org/en/latest/topics/downloader-middleware.html#httpcache-middleware-settings

#HTTPCACHE_ENABLED = True
#HTTPCACHE_EXPIRATION_SECS = 0
#HTTPCACHE_DIR = ‘httpcache’
#HTTPCACHE_IGNORE_HTTP_CODES = []
#HTTPCACHE_STORAGE = ‘scrapy.extensions.httpcache.FilesystemCacheStorage’


星巴克代码示例:
import urllib.request

url=‘https://im.qq.com/index’
respone=urllib.request.urlopen(url)

content=respone.read().decode(‘utf-8’)

print(content)

from bs4 import BeautifulSoup

soup=BeautifulSoup(content,‘lxml’)

name_list=soup.select(‘https://qq-web.cdn-go.cn/im.qq.com_hybrid_h5_v2/92f39c89/app/news/dist/cdn/index.bundle.js’)


# 78.基本使用:

from selenium import webbrowser

browser=webbrowser.Edge()

browser.get(‘https://www.baidu.com’)

导入selenium

from selenium import webdriver

browser = webdriver.Edge()

定义并且写入url

browser.get(‘https://www.baidu.com’)
browser.quit()

导入selenium

from selenium import webdriver

browser = webdriver.Edge()

定义并且写入url

browser.get(‘https://www.jd.com’)
browser.quit()

使用:page_source获取网页源码

content=browser.page_source
print(content)


79.元素单位


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值