python——自学入门

识python
python:面向对象(对象之间交互数据,各对象协同操作), 解释性语言。简单,功能强大
功能:
学习路线:
初级:初识—语法—运算符、表达式—控制流—函数—模块—数据结构—面向对象—文件、异常处理—标准库
进阶:正则表达式、多线程、网络编程、客户端编程、图形界面编程
高级:网络编程、wxpython

特点:严格区分大小写
          简单,面向对象
      开源
       库非常丰富(标准库、)
       跨平台使用
       解释性语言(区别编译性语言c++,编译器编译为二进制,进入系统内存执行),通过解释器解释为字符码。
       高级语言
目录:lib:放模块,自定义模块也在这里。


一、windows下环境配置
1.进入 https://www.python.org/      点击downloads
3.。。的版本有新特性
2.。。的版本运行速度快。 现在多用其开发
安装都是next默认值

2.系统变量
用户变量:选择tmp(tmp和temp区别:tmp解决dos兼容性问题。两个一样,都可以选择 )
系统变量:path:E:\python

3.集成开发环境  http://www.jetbrains.com/网站最下方(java语言开发)

用professional的版本
默认安装。快捷键(keymap)用eclipse的
4.java jdk环境(pycharm也是java开发)

二、osx系统下搭建python
1.下载集成开发环境pycharm  http://www.jetbrains.com/

三、linux系统下搭建python
1.测试linux是否安装python。打开终端:输入python查看版本
2.下载集成开发环境pycharm  http://www.jetbrains.com/
3.





四。python的helloworld
(1)cmd中编写 python
命令行下运行源文件的使用

(2)集成开发环境pycharm中编写
编辑器:python自带:IDLE。
                多行代码:ctrl+n弹出的窗口可以换行
                退出编辑模式:ctrl+z
                源码以.py结尾
        aptana
        pycharm


五、python基本语法
1.定义常量与变量、数与字符串
常量:程序运行中不可变。7,a,b,c,a=1。一旦绑定不可更改。
    定义常量用对象的方法创建

变量:程序运行中可改变。赋值:“=”
i=5
print i
i+=1
print i
i+=2
print i
i+=3
print i
输出:5    6    8    11

a=10
b=2
c=a+b
print(c)
//easy.语言很简单

数的类型: int:0、1、-1、1009、-290
               long(长整型):87887l、-90990、
            float:2.778、3.277、8.88
            bool:true、false
            complex(复数型):4+2j、-9+20j
        
字符串: 引号引起来的字符集。"hello"、'my python'

引号的使用(单双引号可以交叉使用)
        单引号:单引号里可以使用双引号,并且双引号可以输出,双引号中不能使用双引号       
         c1 = 'ok'
         print  c1
         c2= 'It is "ok"!'
         print  c2
         输出:ok
              It is "ok"!
    双引号:双引号中可以使用单引号
         c1 = "ok"
         print  c1
         c2= "It is 'ok'!"
         print  c2
         输出:ok
              It is ‘ok’!
       三引号:三个单引号,或者三个双引号,执行结果一样。且单双引号不可交叉使用。三引号包裹的字符串可以换行。
         c1 = '''I
         am
         a beautiful
         girl
         do you know?'''
         print  c1
        输出:I
               am
               a beautiful
               girl
               do you know?
            
转义符:主要用在字符串中
        "\":想输出:it's a dog
        a.print "it's a dog"
        b.print 'it\'s a dog'
        "\n":换行
            print "hello boy\nhello boy"
            输出:hello boy
                   hello boy

自然字符串:保留转义符的样式,原样输出,不进行任何处理,使用自然字符串,在引号前加r
         print  "hello caoge \n hello gezi"
         print  r"hello caoge\nhello gezi"
        输出:hello caoge
               hello gezi
               hello caoge\nhello gezi

 字符串的重复:输出“hello”20次, 可使用重复运算符“*”
         print  "hello" * 10
        输出:hellohellohellohellohellohellohellohellohellohello

子字符串:jikexueyuan中“ji”、“yu”都是“jikexueyuan”的子字符串。一个大字符串中,抽出连续字符串。 两种方法:索引运算法[](从0开始索引,返回一个字符)、切片运算法[a:b](从a下标开始,到b-1下标。第一位的下标为0)
         c1= "jikexueyuan"
         c2=c1[ 0 ]
         c3=c1[ 7 ]
         c4=c1[: 3 ]    #从最左边一直到b-1
         c5=c1[ 3 :]    #从第3歌下标一直到最右边
         c6 =c1[ 3 : 7 ]
         print  c2
         print  c3
         print  c4
         print  c5
         print  c6
        输出:j
               y
               jik
               exueyuan
               exue

2.  判断语句
score  =  20
if  score >= 80 :
     print ( "很好" )
elif  score >= 60 :
     print ( "及格" )
elif  score >= 30 :
     print ( "不及格" )
else :
     print ( "很差" )
中文编码问题
开头加入 :#coding:utf-8 或者 #coding=utf-8

3.   循环
for  in  range ( 0 , 10 ):
     print (i)                   
输出:0123456789

for  in  range ( 0 , 10 ):
     print ( "Item{0}" .format(i))
输出:Item0   Item1   Item2   Item3   Item4   Item5
      Item6   Item7   Item8   Item9

for  in  range ( 0 , 10 ):
     print ( "Item{0},{1}" .format(i, "hello python" ))
输出:Item0,hello python   Item1,hello python   Item2,hello python   Item3,hello python
      Item4,hello python   Item5,hello python   Item6,hello python   Item7,hello python
      Item8,hello python   Item9,hello python

4.定义函数
def  sayHello(): #小括号里可写传入参数
     print ( "hello world" )
sayHello() #执行函数

def  max(a,b): #带参数的函数
     if  a>b:
         return  a
     else :
         return  b
print (max( 2 , 3 ))
#5.定义函数

5.面向对象(定义类)
class  Hello: #定义类
     def  sayHello( self ): #定义方法
         print ( "Hello Python" )
h=Hello()
h.sayHello() #创建实例
输出:Hello Python

class  Hello: #定义类
     def  __init__ ( self ,name): #构造方法
         self ._name = name
     def  sayHello( self ): #定义方法
         print ( "Hello {0}" .format( self ._name))
h=Hello( "caoge" )
h.sayHello() #创建实例
输出:Hello caoge

class  Hello: #定义类
     def  __init__ ( self ,name): #构造方法
         self ._name = name
     def  sayHello( self ): #定义方法
         print ( "Hello {0}" .format( self ._name))

class  Hi(Hello): #继承自hello
     def  __init__ ( self , name):
        Hello. __init__ ( self ,name)
     def  sayHi( self ):
         print ( "Hi {0}" .format( self ._name))
h = Hello( "caoge" )
h.sayHello() #创建实例

h1 = Hi( "gezi" )
h1.sayHi()
输出:Hello caoge
       Hi gezi
    
    
6.引入python文本
loadlib.py
#import mylib
#h = mylib.Hello()
#h.sayHello()

from  mylib  import  Hello
h = Hello()
h.sayHello()

mylib.py
class  Hello:
     def  sayHello( self ):
         print ( "Hello everybody" )
运行:loadlib.py
输出:Hello everybody

web2py:python语言web的开发框架。一个完整的网络模板

六、python数据类型
 基本数据类型:数和字符串

 python没有数组的概念,只有列表和元组的概念
     列表:是存储一连串元素的容器。用[]表示,可以修改内容
         students =[ "小明" , "jone" , "向冲" , "mary" , "alice" ]
         #列表中的每一项是元素,元素是有顺序的,第一个元素下标为0
         print  students [ 2 ] #利用索引运算符选取元素
         #列表可以修改内容
         students[ 2 ]= "王八蛋"
         print  students[ 2 ]
         输出:向冲
                王八蛋
    
     元组:与列表类似
         区别:1.使用()包含元素,2.不能修改内容,只能读取内容
         students =( "小明" , "jone" , "向冲" , "mary" , "alice" )
         print  students [ 2 ]
         输出:向冲
        
集合:1.建立关系。2.消除重复元素
         格式:set(元素)
     #集合
     a= set ( "adfasfbsb" )
     b= set ( "affg" )
     x=a&b #交集
     print  x
     y=a|b #并集
     print  y
     z=a-b #差集 a中有,b没有
     print  z
     new = set (a) #去除重复元素:集合里的元素是唯一的,把字符串a变为一个集合赋值给new,输出new
     print  new
     输出:set(['a', 'f'])
            set(['a', 'b', 'd', 'g', 'f', 's'])
            set(['s', 'b', 'd'])
            set(['a', 's', 'b', 'd', 'f'])
        
字典:关联数组,通过":"进行关联。字典里面包含一整个事情,事情里面包含各方面的具体信息
        格式:zidian={'name':'caoge','home':'niaoshi','like':''book'}
         #字典
         k={ "名字" : "鸽子" , "籍贯" : "新疆" }
         print  k[ "籍贯" ]
         #添加字典内容,原子典不变
         k[ "星座" ]= "鱼鱼"
         print  k[ "名字" ]
         print  k[ "星座" ]
         print  k[ "籍贯" ]
         输出:新疆
                鸽子
                鱼鱼
                新疆
            
七、什么是标识符
标识符:起的名字叫做标识符。变量,常亮的名字就是标识符的一种。根据命名规则命名的可以使用的标识符叫做有效标识符。否则是无效标识符
命名规则:a、第一个字符只能是字母或是下划线
           b、其他部分可以是字母或者下划线或者数字
           c、标识符大小写敏感
         ssd_1 = 223
         print  ssd_1  输出:223
         1 ssd= 223
         print  1 ssd   输出:报错
         _1ssd= 223
         print  _1ssd 输出:223
        
python关键字:系统自带的有特定的含义的标识符。共28种
主要有:and、elif、global、or、else、pass、break、continue、import、class、return、for、while

八、python的对象
python的内置对象:数字、字符串、列表、元组、字典、集合等。一切皆为对象

详解pickle腌制
需要持久性存储的对象,并且不丢失对象的类型与数据。我们将这个对象进行序列化,存储在内存或第三方文件中,需要使用的时候再恢复为原来的数据。
序列化的过程:pickle腌制。恢复的过程:反的pickle腌制
     import  pickle   #导入pickle模块
     #dumps(object)将对象序列化
     lista=[ "xiangchong" , "shi" , "wangbadan" ]
     listb=pickle.dumps(lista)
     print  listb
     输出:(lp0
              S'xiangchong'
              p1
              aS'shi'
              p2
              aS'wangbadan'
              p3
              a.
    
     #loads(string)将对象的类型,数据原样恢复为原来的格式
     listc=pickle.loads(listb)
     print  listc
     输出:['xiangchong', 'shi', 'wangbadan']
    
     #dump(object,file)将对象序列化,存储在文件里
     group1=( "caoge" , "jiuxihuan" )
     f1= file ( '1.pk1' , 'wb' ) #wb:写入
     pickle.dump(group1,f1, True )
     f1.close()#关闭文件

     #load(object,file)恢复数据
     f2= file ( '1.pk1' , 'rb' )
     t=pickle.load(f2)
     print  t
     f2.close()
     输出:('caoge', 'jiuxihuan')
    
九、行与缩进
    逻辑行与物理行
    逻辑行:一段代码在意义上的行数
    物理行:实际看到的行数
         #三个物理行
         print  "abc"
         print  "123"
         print   "777"
         #1个物理行,3个逻辑行
         print  "abc" ; print  "123" ; print  "777"
         #1个逻辑行,3个物理行
         print  '''这里是
         曹歌的
         代码'''
    行中分号使用规则
        一个物理行中可以有多个逻辑行,用分号隔开。如果一个逻辑行占了物理行的最后,这个逻辑行可以省略分号
         #所有的逻辑行后均应使用分号
         print  "123" ; print  "111" ;
         print  "asd" ;
         #行末的分号可以省略
         print  "123" ; print  "111"
         print  "asd"
    行连接:一个逻辑行分为几个物理行写时,使用行连接,在行的最后加\
         print  "我们都是\
         好孩子"
        输出:我们都是好孩子
    缩进:逻辑行行首的空白有规定,不对时程序不能运行
    缩进要求:1、一般逻辑行行首没有空白
               2、if/while语句缩进方法
             #if语句
             a= 7
             if  a> 0 :
     print  "hello" #缩进一个tab字符
             #while缩进
             a= 0
             while  a< 7 :
      print  a
     a+= 1
            输出:hello
            0
            1
            2
            3
            4
            5
            
十、python运算符与表达式
    运算符:对一个数字或者多个数字进行操作,对一个或多个字符串进行操作。也叫运算符
    +、-、*、/、**(冥运算)、<、>、!=(不等于)、//(商的整数部分)、%(余数部分)、&、|、^、~、>>(右移)、<<(左移)、<=、>=、==、not、and、or
     #”+“两个对象相加
     a= 7 + 8
     print  a 输出:15
     b= "xiang" + "chong" #"+"是两个字符串的连接符号
     print  b 输出: xiangchong
    
     #“-”取一个数字的相反数,两个数字相减
     a=- 7 #取相反数
     print  a 输出:-7
     b=-(- 8 )
     print  b 输出:8
     c= 11 - 12
     print  c 输出:-1

     #两个数相乘、字符串重复
     a= 4 * 7
     print  a 输出:28
     b= "cao" * 3
     print  b 输出:caocaocao

#"/":两个数字相除
a= 7 / 2
print  a #除数或者被除数有一个是小数得到的结果就是小数,都是整数得到的结果就是整数输出:3
b= 7.0 / 2
print  b 输出:3.5
c= 7 / 2.0
print  c 输出:3.5

#"**":求幂运算
a= 2 ** 3 #2的三次幂,2*2*2
print  a 输出:8

#”<“小于号,返回一个bool值
a= 3 < 7
print  a 输出: True
     b= 3 < 3
print  b 输出: False

#">":大于号,返回一个bool值
a= 3 > 7
print  a 输出:False
b= 3 > 1
print  b 输出:True

#"!=":不等于,返回bool值
a= 2 != 3
print  a 输出:True
b= 2 != 2
print  b 输出:False

#"//":商的整数部分
a= 10 // 3
print  a 输出:3

#"%":取商的余数部分
b= 10 % 3
print  b 输出:1
a= 10 % 1 #没有余数的时候
print  a 输出:0
a= 10 // 3
b= 10 % 3
c= 3 *a+b #c为除数乘以商的整数部分加上余数,c为被除数
print  c 输出:10

#"&":按位的与运算。按位与是指一个数字转化为二进制,然后这些二进制的数按位来进行与运算
a= 7 & 18 #与运算只有1,1为1
print  a 输出:2
'''将7转化为二进制:111;自动补齐8位:00000111;
将18转化为二进制10010,自动补齐为0010010
将00000111
..00010010按位与进行运算,得到00000010,将00000010转化为十进制,得到2'''

#"\":按位或运算,将数字转化为二进制后按位进行或运算
a= 7 | 18 #或运算只有0,0为0
print  a 输出:23
'''将7转化为二进制:111;自动补齐8位:00000111;
将18转化为二进制10010,自动补齐为0010010
将00000111
..00010010按位或进行运算,得到00010111,将00010111转化为十进制,得到23'''

#"^"按位异或,不相同为1,相同为0
a= 7 ^ 18
print  a 输出:21
'''将7转化为二进制:111;自动补齐8位:00000111;
将18转化为二进制10010,自动补齐为0010010
将00000111
..00010010按位或进行运算,得到00010101,将00010101转化为十进制,得到21'''

#"~":按位翻转.~x=-(x+1)
a=~ 18   #~18=-(18+1)
print  a 输出:-19

#"<<":左移
'''18左移,将他的二进制形式00010010左移,成为00100100(右边缺少默认补0)
,成为36,左移一个单位相当于乘2左移两位相当于乘4,三位相当于乘8,N个单位相当于乘2的N次幂'''
a= 18 << 1
print  a 输出:36
b = 3 << 3
print  b 输出:24

#“>>”:右移,右移是左移的逆运算,结果取商的整数部分
'''18左移,将他的二进制形式00010010左移,成为0001001(右边缺少默认补0)
,成为36,右移一个单位相当于除以2,右移两位相当于除以4,三位相当于除以8,N个单位相当于除以2的N次幂'''
a= 18 >> 1
print  a 输出:9
b= 18 >> 2
print  b 输出:4

#"<=":小于等于,比较运算,小于或等于,返回bool值
a= 3 <= 3
print  a 输出:True
b= 4 <= 3
print  b 输出:False

#">=":大于等于,比较运算,大于或等于,返回bool值
a= 1 >= 3
print  a 输出:False
False
b= 4 >= 3
print  b 输出:True

#"==":比较两个对象是否相等,返回bool值
a= 12 == 13
print  a 输出:False

b= "hello" == "hello"
print  b 输出:True

#"not":逻辑非,true的值非运算后为false
a= True
b= not  a
print  b 输出:False

c= False
print not  c 输出:True

#"and":逻辑与
'''
True and True==True
True and False==False
False and False==False'''
print  True  and  True 输出:True

#“or”:逻辑或
'''
True or True==True
True or False==True
False or False==False'''
print  True  or  False 输出:True

优先级:python的优先级有两种,程序的优先级和运算符的优先级
#优先级的作用,不同运算符优先级不同,优先执行某些运算符
a = 2 + 7 * 8
print  a #优先执行* 输出:
b= 9 > 7
print  b # 输出:

#优先级使用实战
#第一名:函数调用/寻址/下标
#第二名:幂运算**
a = 4 * 2 ** 3
print  a 输出:32
#第三名:翻转运算~
#第四名:正负号
print  2 + 4 *- 2 输出:-6
#第五名:*,/,%
print  2 + 4 * 2 / 4 输出:4
#第六名:+,-
print  3 << 2 + 1 输出:24
#第七名:<<,>>
#第八名:按位&,^,\
#第九名:比较运算符
a = 2 * 3 + 5 <= 5 + 1 * 2
     print  a 输出:False
#第十名:逻辑的与或非and,or,not
     #第十一名:lambda表达式
    
运算符使用规律:
#1,一般是左结合的
  print  4 + 5 + 5 * 6 + 6 输出:45
  #2,出现赋值的时候一般是右结合
  a = 5 + 5
  print  a 输出:10

优先级记忆方法:
函数寻址下标一
幂运算小二笑嘻嘻
全体单元第三位(连接一个对象的运算符~,-,+)
乘除求余四千里

乘除完了五加减
六娃玩耍左右移
七是按位或跟与
八仙生气要比敌

倒数第一逻辑或非与

实在不记得优先级时,用小括号。括号内的优先级最高
a =( 2 + 5 )* 6
print  a 输出:42
b=(( 2 + 5 )+ 5 )* 2
print  b 输出:24

表达式:值,变量和运算符中的一个或多个组成
#1字符串表达式
"hello"
#2.运算表达式
25 + 7
#3.变量,值组成
a= 67
#4.值,运算符,变量
a= "hello"

#表达式在单行命令中的使用,一输入会执行,但在多行命令行中不会执行,所以在本文件(源程序,又叫多行命令行)中不会执行,在IDLE中可执行
#值表达式:8,执行结果任是值
8
#变量表达式
a= "OK"
a= 7
#计算表达式:输出结果是计算后的值
7 + 8
#字符串表达式
"HELLO" #输出'HELLO'

#表达式在源程序中的使用

#表达式执行结果与print的区别,字符串执行结果有单引号,打印结果没有单引号,数字执行结果和打印结果都是数字
#表达式:输入"qq",输出'qq'
#print:输入:print "qq" 输出:qq
#表达式:输入:a=7 回车 输入:a,输出:7
#print:输入:print a 输出:7


十一、控制流
程序代码的执行是有顺序的,从上到下,跳转执行,分支执行,循环执行。控制语句能控制代码段的执行方式,不同功能的控制语句为控制流
    三种控制流: 顺序结构(通常情况),分支结构,循环结构
    分支结构if:判断执行哪个语句块
         #IF语句,分支结构,只满足一个分支.各分支尽量不要重复,并且尽量包含全部可能性
'''
if 是这样:
    执行该部分语句
elif 或者是这样:
    执行elif部分语句
else 以上情况都不是:
    执行这部分语句
'''
#一种情况的if
a= 8
if  a== 8 :
     print  "caoge"

if  a!= 8 :
     print  "hehe"
#两种情况的if
a= 8
if  a== 8 :
     print  "caoge"
else :
     print  "xiangchong"

#三种情况下的if
a= 8
if  a== 7 :
     print  "xiang"
elif  a> 7 :
     print  "cao"
else :
     print  "fenshou"

a= 80
b= 0
if  0 <a<= 80 :
     print  "差"
elif  80 <=a<= 100 :
     print  "好"
#程序问题:1.b没有用到,消耗内存。2.80在两个分支里都有,不准确,输出是哪个条件在上面,,就输出哪个结果
循环结构while:控制一个语句循环执行
         #循环结构
'''
while 条件为真:
    循环执行“该部分语句
    该部分语句“
else:条件为假,执行该部分语句
    '''
#死循环
'''a=True
while a:
    print "wangbadan"
'''
#不会循环输出,else部分不循环输出,只有while部分循环输出
b= False
while  b:
     print  "xiangchong"
else :
     print  "caoge" 输出:caoge
#有嵌套的while语句
a= 1
while  a< 10 :
     if  a<= 5 :
         print  a
     else :
         print  "hello"
     a=a+ 1
else :
     print  "test"
输出:1
   2
   3
   4
   5
   hello
   hello
   hello
   hello
   test

    
    循环结构for:变量依次取集合里的元素,执行循环部分
         '''
for语句格式:
for i in 集合
    执行该部分
else:
    执行该部分
'''

for  in  [ 1 , 2 , 8 , 9 , 0 ]:
     print  i 输出:12890

#range函数,生成一个集合的序列,个数为7-1,步长默认为1
for  in  range ( 1 , 7 ):
     print  "hello" 输出:hellohellohellohellohellohello

a= range ( 2 , 5 )
print  a 输出:[2, 3, 4]
#range中第三个参数代表步长,生成集合为1,3,5,7,9
for  in  range ( 1 , 10 , 2 ):
     print  i 输出:13579
#带嵌套的for语句,优先执行里面的语句,外层只做控制
for  in  range ( 1 , 10 ):
     if  i% 2 == 0 :
         print  i
         print  "偶数"
     else :
         print  i
         print  "基数"
        输出:1
               基数
               2
               偶数
               3
               基数
               4
               偶数
               5
               基数
               6
               偶数
               7
               基数
               8
               偶数
               9
               基数

    break语句:循环语句中,打破循环,强制停止
             #break在while中
a= 1
while  a:
     print  a
    a=a+ 1
     if  a== 5 :
         break 输出:1234

#break在for中
for  in  range ( 5 , 9 ):
     print  i
     if  i> 8 :
         break 输出:5678

#break在双层循环中
a= 10
while  a<= 12 :
    a=a+ 1
     for  in  range ( 1 , 7 , 2 ):
         print  i
         if  i== 5 :
             break 输出:135135135

a= 10
while  a<= 12 :
    a=a+ 1
     for  in  range ( 1 , 7 ):
         print  i
         if  i== 5 :
             break
    if  a== 12 :
         break 输出:1234512345
    
continue语句:强制停止循环中的一次执行
     #continue
a= 1
while  a< 7 :
    a=a+ 1
     if  a== 3 :
         continue
    print  a 输出:24567

#for循环中的continue,a程序和b程序
for  i   in  range ( 1 , 7 ):
     if  i == 3 :
         continue
    print  i 输出:12456

for  i   in  range ( 1 , 7 ):
     print  i
     if  i == 3 :
         continue #没起作用,想控制语句要把xontinue放上面,不想控制放下面
    输出:123456
#continue在双层循环语句中,for循环先循环
a= 1
while  a< 7 :
    a=a+ 1
     if  a== 4 :
         continue
    for  i   in  range ( 7 , 10 ):
         if  i == 9 :
             continue
        print  i
输出:7878787878
#continue与break的区别
'''continue终止某一次循环
break直接结束循环'''

for  i   in  range ( 10 , 19 ):
     if  i == 15 :
         continue
    print  i
输出:1011121314161718
for  i   in  range ( 10 , 19 ):
     if  i == 15 :
         break
    print  i
输出:1011121314

十二、函数
    函数function:用来封装特定功能。包括系统自带函数(不用我们编写,自由度低,方便)和自定义函数(自由度高,需要我们编写功能,需要使用的时候调用函数)
        函数的功能:
             #1.实现去字符串长度的功能
a= "xinagchongshigewangbadantaoyanta"
print  len (a) 输出:32

#2.实现字符串的切割,赋值给b
a= "xiangchong"
b=a.split( "a" )
print  b 输出:['xi', 'ngchong']

#3.自定义的函数
def  a():
     print  "xiangchong" ; print  777
a()
     输出:xiangchong
          777
函数的定义:1.声明指定部分是函数
             2.定义这个函数所包含的功能
             def  函数名():
    函数内容;函数内容

def  function():
    a= 8
     print  a
    形参与实参
         参数:函数执行功能时所用到的数据
         print  len () #取数据的1函数中无参数,报错,函数无意义
         形式参数:发生在函数定义的过程中,一般代表参数的名称,不代表参数值,没有实际值
         def  function(a,b): #a,b是形式参数,代表第一个位置是a,第二个位置是b
     if  a>b:
         print  a
     else :
         print  b
function( 1 , 3 ) #1,3是实际参数,在函数的调用部分,a的位置实际值为1,b的位置实际值为3
#1传递给function中的a,3传递给funbtion中的b。一一对应传递
         实参:是在函数调用的过程中出现,一般具有实际参数
         传递方式:参数传递有使用顺序
         关键参数:一个函数中出现多个参数时,可以通过名字直接给参数直接赋值
             def  function(a= 1 ,b= 6 ,c= 7 ): #赋值传递,初始化
     print  a
     print  b
     print  c
function( 5 ) #自动赋值给最左边 输出:567
function( b = 7 , a = 8 ) #b与b对应,不考虑位置关系。关键参数 输出:877
function( 5 , c = 2 , b = 3 ) #默认5传递给第一个位置 输出:532
funvtion( b = 4 , c = 2 , a = 1 ) #按照关键词传递,不考虑位置 输出:142
    全局变量与局部变量
        作用域:变量的作用范围
         def  func():
     f = 8
#print f #会报错,显示f没有定义。原因:f在func函数内,作用域也在函数内
#print j  #会报错,j的作用域是定义j=9之后,以下的部分,函数部分在他的上面,所以报错
j= 9
print  j   #对了
        局部变量:变量的作用域在一定范围内,不是全局起作用。没有声明是全局变量的变量,默认是局部变量,只要在函数内部的变量就是局部变量
         def  func2( a ):
    i= 7 #局部变量只在局部起作用,只在函数里起作用
     print  i
i=
func2(i)   # i=9传递给a,函数内部i=7,所以输出7
print  #没有调用函数,输出函数外面的结果
        输出:79
        
        全局变量:作用域为全局,需要全局声明
         def  func3():  #定义函数
     global  #声明全局变量,i的作用域在全局,函数外面也能用
     i= 7
     print  #局部变量
i= 9
func3()
print  i 输出:77

def  func3():  #定义函数
     global  #声明全局变量,i的作用域在全局,函数外面也能用
     i= 7
     print  #局部变量
func3()
i= 9 #i的值改变
print  i 输出:79

    函数的使用与返回值
        函数的调用:直接输入函数名,调用参数的时候,在括号里输入参数就行
         def  a():
     i = 1
a()
        函数的返回值:有的函数有,有的函数没有。返回可以一个值或多个值
             #函数的返回值是通过return实现的
def  test():
    i= 7
     return  #函数的整体值是I,使函数成为一个是值的函数,给函数赋予值
print  test() 输出:7

#多个返回值
def  test2(i,j):
    k=i*j
     return  (i,j,k)
x=test2( 4 , 5 ) #把4,5传递给i,j。x:以元组的形式存储多个元素
print  x 输出:(4, 5, 20)
def  test3(i,j):
    k=i*j
     return  (i,j,k)
y ,z,m=test3( 4 , 5 ) #分别存储
print  y 输出:4
    文档字符串:由于函数过多,造成分析困难,浪费时间的问题。解决办法:1.写说明文档,一个函数一个。2.使用文档字符串,每个函数开头写文档字符串
    1.紧挨冒号
    2.使用三引号
    3.第二行必须空开,第三行开始是具体功能的描述
    4.句末是句号,第一个字母必须大写
    使用方法:print d.___doc__,函数d的文档字符串
               help(d):输出帮助信息,输出文档字符串和参数信息
            
十三、模块
    模块:函数功能的扩展,实现一项或多项功能的程序块。模块里可以重用多个函数。实现的是一类功能。
        目录:lib:放模块,自定义模块也在这里。
    
        导入模块:导入模块后才能使用 ,关键字:import
             import  math #导入模块
             print  math.pi
        自带模块:标准库模块。有的与邮件,操作系统,系统功能等有关。其中标准库中与系统功能有关的模块叫sys模块

     #sys
import  sys
print  sys.version #版本信息
print  sys.executable #查看目录地址
print  sys.getwindowsversion() #返回win版本信息
print  sys.modules.keys() #返回导入模块列表的关键字
    字节编译:
        .pyc文件:机器识别二进制语言。所以python执行模块时有两种方式。1.现将模块里面的内容编译为二进制,这一过程叫字节编译,会产生.pyc二进制文件。2.直接执行模块对应的二进制语言程序,省略编译,执行速度快一些。
        字节编译与编译的区别:
            python的编译过程是在解释器中发生的,而编译型语言是指软件中就有一个独立的编译模块去编译程序。而python中的字节编译由解释器完成,所以python是解释型语言。
        两种.pyc文件的产生方式:执行一个模块时,如果有.pyc文件就执行文件。如果没有就进行字节编译,产生.pyc文件(运行一下import模块,就会产生文件或者在cmd中编译),执行它。
        
        .pyc文件的使用:1.加快模块运行速度、2.反编译等
        .pyc文件的查看:使用二进制文件阅读器Binary viewer等
    from...important:导入一个模块的一个方法,
         from  sys  import  version import  sys
         print  version print  sys.version #版本信息
    from...important*:导入一个模块的所有方法
    认识_name_属性
        主模块:函数中,一个函数调用其他函数,这个函数是主函数,没有调用其他函数的函数叫非主函数
                模块中,一个模块被其他模块调用,这个模块是非主模块,没有被调用模块,被直接使用的模块叫主模块。
                自己执行是主模块,被别人执行是非主模块。决定因素
                __name__属性的值是"__main__"就是主模块。帮助判断
        认识_name_属性:
             if  __name__== "__main__" :
     print  "主模块"
else :
     print  "不是主模块"
    自定义模块:自己定义的模块。
        创建:将文件保存在lib目录内,命名为ceshi.py。保证模块没有 逻辑和语法上的小错误:将模块内的形式参数参数初始化(i=0)或者声明变量类型(Int i)
         #coding:utf-8
i= 0 #初始化
j= 0 #初始化
#i,j形参,没有实际值,执行出错.只在模块外面赋值也会报错..解决办法:初始化,起码在逻辑上不会出错
def  add(i,j):
    k=i+j
     return  k
k=add(i,j)
print  k

    调用模块:    import  ceshi #生成.cpy文件
i= 1
j= 2
print  ceshi.add(i,j) 输出:3
    dir()函数:查看指定模块的功能列表
         import  sys
         print  dir (sys) #输出所有的功能,其他编辑器可以不加print 直接写dir(sys)
         print  sys.version #其他编辑器可以不加print
    dir()函数扩展:查看任意指定对象的功能列表
    空列表
    有元素的列表
    返回值一样,说明dir()只是返回属性和方法的列表,没有数据
    
十四、python数据结构
数据结构:一个或几个数据要组织起来有不同的组织方式(存储方式)。不同组织方式就是不同的结构。数据组织在一起的结构称为数据的结构。又为数据结构。
数据结构:列表,元组,字典,队列,栈,树等等。
python中数据的组织方式叫做python的数据结构
Python的内置数据结构:python定义好的,比如元组,列表等
python的扩展数据结构:python中没有直接定义,需要我们自己定义实现的组织方式:栈,队列。。。
#python的内置数据结构:元组,列表,字典
#三个物品,apple、orange、pear。存储起来
# 1.列表。按顺序分别存储到一个柜子中,这些物品可以取出来,发生改变。
[ "apple" , "orange" , "pear" ]
#2.元组,按顺序分别存储到一个柜子中,这些物品不可以取出来,不发生改变。
( "apple" , "orange" , "pear" )
# 3.字典。按顺序分别存储到一个柜子中,每个柜子有名称。
{ "sam" : "apple" , "jac" : "orange" , "mating" : "pear" }
数据结构和算法:
    数据结构是数据存储方式,是静态的
    算法:运算方法,是思维,是动态的。不同的运算方法是不同的算法
    数据结构是算法的基础,相同的数据结构1运用不同的算法有不同的效率

栈:一种数据结构,不是内置数据结构,属于扩展数据结构。
相当于一端开口一端封闭的容器。数据A进栈的过程叫做进栈。栈只能对栈顶的数据进行操作,栈顶到栈底的数据不能被操作,栈顶数据出栈后才能操作栈顶到栈底之间的数据
     #栈的实现
class  Stack(): #定义栈的类
     def  __init__ ( st ,size): #初始化,__init__:名称;st:主体;size:容量
         st .stack=[]; #基础属性:列表,列表里的数据可以随意修改
         st .size=size; #容量的参数赋值给栈
         st .top=- 1 ; #初始化栈顶,第一个进来的数字是0,那么最开始是栈顶的位置是-1

     def  push( st ,content): #入栈;st:主体;content:数据内容
         if  st .Full():
             print  "Stack is Full!"
         else :
             st .stack.append(content) #在栈里增加数据,append:增加内容
             st .top= st .top+ 1 #栈顶指针加一
     def  out( st ): #出栈操作
         if  st .Empty(): #判断空
             print  "Stack is Empty"
         else :
             st .top== st .top- 1
     def  Full( st ): #判断栈是否满了,满的时候栈顶指针跟栈的大小相等
         if  st .top== st .size:
             return  True
         else :
             return  False
     def  Empty( st ):
         if  st .top==- 1 : #栈顶为-1,栈空了
             print  True
         else :
             print  False

#栈的使用
q=Stack( 7 ) #给栈传递参数,初始化
q.Empty() #判断是否是空 输出:True
q.push( "Hello" ) #入栈
q.Empty() 输出:False
q.out() #出栈
q.Empty()
队列:两端都开通的容器;一段只能进行删除操作,另一端只能进行插入操作。
    进行插入操作的一段叫队尾,只能进;进行删除操作的叫队首,只能出
队尾进队首出。
     # 队列的实现
class  Queue():
     def  __init__ ( qu ,size): #初始化;qu:队列的主体;size:队列的容量
         qu .queue=[]; #列表里的元素可以修改,所以用队列作为主体
         qu .size=size
         qu .head=- 1
         qu .tail=- 1
     def  Empty( qu ):
         if  qu .head== qu .tail: #队尾队首指针重合
             return  True
         else :
             return  False
     def  Full( qu ):
         if  qu .tail- qu .head+ 1 == qu .size: #队首队尾指针的距离为容量
             return  True
         else :
             return  False
     def  enQueue( qu ,content):
         if  qu .Full():
             print  "Full"
         else :
             qu .queue.append(content) #数据放入队列
             qu .tail= qu .tail+ 1 #队尾指针加一
     def  outQueue( qu ):
         if  qu .Empty():
             print  "empty"
         else :
             qu .head= qu .head+ 1 #队尾指针不变,队尾指针加一

     #队列的使用
t=Queue( 7 )
t.Empty()
t.enQueue( "sfg" )
t.Empty()

十五、基本的正则表达式
    常用符号:点号,星号,问好,小括号
     .:匹配任意字符,换行符\n除外
     *:匹配前一个字符0次或无限次
     ?:匹配前一个字符0次或1次
     .*:贪心算法,吃尽可能的东西
     .*?:非贪心算法
     ():括号内的数据作为结果返回
         # 导入正则表达式的库文件 re
import  re

# 密码
secret_code= "hadkfexxIxxfasfjifa123xxlovexx23345sdfaxxyouxx8dfs"
#. 的使用
a= 'xz123'
b=re.findall( 'x.' ,a) #. 就是一个占位符,几个点就是几个符号
print  b 输出:['xz']
#* 的使用
a= 'xzx123'
b=re.findall( 'x*' ,a) #. 就是一个占位符,几个点就是几个符号
print  b 输出:['x', '', 'x', '', '', '', '']
#? 的使用
a= 'xzx123'
b=re.findall( 'x?' ,a) #. 就是一个占位符,几个点就是几个符号
print  b 输出:['x', '', '', '', '', '', '']
#.* 贪心算法
b=re.findall( 'xx.*' ,secret_code)
print  b 输出:['xxIxxfasfjifa123xxlovexx23345sdfaxxyouxx']
#.*? 非贪心算法
c=re.findall( 'xx.*?xx' ,secret_code)
print  c 输出:['xxIxx', 'xxlovexx', 'xxyouxx']
#(.*?)
d=re.findall( 'xx(.*?)xx' ,secret_code)
print  d 输出: ['I', 'love', 'you']
for  each  in  d:
     print  each 输出:I
                                   love
                                   you

    
    方法:findall,search,sub
     findall:匹配所有符合规律的内容,返回包含结果的列表。遍历整个文件
     Search:匹配并提取第一个符合规律的内容,返回一个正则表达式对象。找到所需,就不找了
     Sub:替换符合规律的内容,返回替换后的值
         s= '''aefadxxhelo
xxsdfdsdfxxwordxxsfds'''
e=re.findall( 'xx(.*?)xx' ,s)
print  e 输出:['sdfdsdf']

f=re.findall( 'xx(.*?)xx' ,s,re.S) #re.S 是为了包括换行符, s 是让点匹配任意字符包括新的一行在政策表达式的库文件中有介绍
print  f 输出:['helo\n', 'word']

# 对不 findall search 的区别
s2= 'sdfxxIxxafxxlovexxdfdfgxxxiangxxfdg'
#group 代表匹配的括号有几个
g=re.search( 'xx(.*?)xxafxx(.*?)xx' ,s2).group( 2 )
print  g 输出:love
g2=re.findall( 'xx(.*?)xxafxx(.*?)xx' ,s2)
print  g2[ 0 ][ 1 ] 输出:love

#sub
s= '123sadfsfdg123'
output = re.sub( '123(.*?)123' , '123789123' ,s)
print  output 输出:123789123
output1 = re.sub( '123(.*?)123' , '123%d123' % 789 ,s)
print  output1 输出:123789123


    常用技巧:
     import re推荐使用
     from re import*
     from re import findall,search,sub,S
     不需要compile
     使用\d+匹配纯数字
         # 匹配纯数字
a= 'asdfasf1234sdfaf777sadgf'
b =re.findall( '(\d+)' ,a)
print  b 输出:['1234', '777']
    
     # 正则表达式应用
# 注意:先抓大,在抓小
import  re
old_url= 'http://www.jikexueyuan.com/course/android/?pageNum=2'
total_page= 20 # 假设有 20

f= open ( 'text.txt' , 'r' ) # 打开文件
html=f.read() # 读取文件,保存至 html
f.close()

# 爬取标题 , 确认标题只有一个,用 search
title=re.search( '<title>(.*?)</title>' ,html,re.S).group( 1 )
print  title

# 爬取链接
links=re.findall( 'href="(.*?)"' ,html,re.S)
for  each  in  links:
     print  each

# 提取部分文字信息,先抓大,后小
# 抓取 ul 部分里的
text_fied=re.findall( '<ul>(.*?)</ul>' ,html,re.S)[ 0 ]
the_text=re.findall( '">(.*?)</a>' ,text_fied,re.S)
for  every_text  in  the_text:
     print  every_text

# 实现翻页
for  in  range ( 2 ,total_page+ 1 ):
    new_link = re.sub( 'pageNum=\d+' , 'pageNum=%d' %i,old_url,re.S)
     print  new_link

页面代码;text.txt
<html>
    <head>
        <title> 爬虫测试 </title>
    </head>
    <body>
        <div class="topic"><a href="http://jikexueyuan.com/welcome.html">huanying</a>
            <div class="list">
             <ul>
                 <li><a href="http://jikexueyuan.com/1.html">1 笨笨 </a></li>
                  <li><a href="http://jikexueyuan.com/2.html">2 软软 </a></li>
                  <li><a href="http://jikexueyuan.com/3.html">3 向冲 </a></li>
                </ul>
            </div>
        </div>
    </body>
</html>


     制作文本爬虫:
         目标网站: http://jikexueyuan.com
         目标内容:课程图片
         实现原理:1.保存网站源代码——手动获取:半自动爬虫,人肉爬虫
                   2.python读文件加载源代码
                   3.使用正则表达式提取图片网址
                   4.下载图片
     # 文本爬虫
     import  re
import  requests # 获取网页文件的利器

# 读取源文件
f= open ( 'textsource.txt' , 'r' )
html=f.read()
f.close()

# 匹配图片网址
pic_url=re.findall( 'img src="(.*?)" class="lessonimg"' ,html,re.S)
i= 0
for  each  in  pic_url:
     print  'now downloading:'  + each
    pic=requests.get(each)
    fp= open ( 'pic\\' + str (i)+ '.jpg' , 'wb' )
    fp.write(pic.content)
    fp.close()
    i+= 1

十六、单线程爬虫
爬取极客学院的课程库,爬取到的数据存储在文本文件中
requests的介绍,安装
requests:HTTP for Humans
  完美代替python的urllib2模块
  更多的自动化
  更友好的用户体验
  更完善的功能
安装:
win:pip install requests
linux:sudo pip install requests
第三方库安装技巧:少用easy_install,因为只能安装不能卸载
  多用pip方式安装
安装时撞墙怎么办:www.lfd.uci.edu/~gohlke/pythonlibs/
拥有所有python第三方库文件。找到requests,带有.whl的文件,下载。后缀改为zip,解压缩。将requests文件夹复制到Lib文件夹中
    
第一个网页爬虫
    request获取网页源代码
     直接获取网页源代码
             import  requests
# 获取 python 的首页源代码,输出的文字在页面查找,可以找到说明源代码获取成功
html=requests.get( 'http://tieba.baidu.com/f?ie=utf-8&kw=python' )
print  html.text
     修改http头获取源代码:反爬虫机制
             # 有些网站会检查访问的程序,需要修改 http 头文件
             import  requests
             #hea User-Agent 是面具,是个字典 . 让网站以为是浏览器在访问,而不是爬虫
'''
获取 User-Agent

1. 网站页面:审核元素。 2. 选择 network ,里面是空的,刷新页面。
3. 随便点击一个内容,在 headers 栏目中的 Request headers 中有 User-Agent 的值
'''
hea={ 'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36' }
html=requests.get( 'http://jp.tingroom.com/yuedu/yd300p' , headers =hea)
html.encoding= 'utf-8'
print  html. text
    使用requests与正则表达式找要的内容
         import  requests
import  re
hea={ 'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36' }
html=requests.get( 'http://jp.tingroom.com/yuedu/yd300p' , headers =hea)
html.encoding= 'utf-8'
title=re.findall( '"color: #039;">(.*?)</a>' ,html.text,re.S)
for  each  in  title:
     print  each
输出:300篇精选中日文对照阅读 289 挪威的森林(中日对照)第二章
   300篇精选中日文对照阅读 288  挪威的森林(中日对照)第一章
   300篇精选中日文对照阅读 287  藤野先生——名文选读
   300篇精选中日文对照阅读 286  夏目漱石 我是猫 第一章
   300篇精选中日文对照阅读 285 それお皿の絵柄よ
   300篇精选中日文对照阅读 284 つもり
等等。。。
            
向网页提交数据
    Get与Post(与服务器交互方式):
     Get:从服务器上获取数据
     Post:向服务器传送数据
     Get:通过构造url中的参数来实现功能
     Post:将数据放在header提交数据
    分析目标网站: https://www.crowdfunder.com/browse/deals
        点击更多,网站浏览器网址不变:说明网站是异步加载(先把网页框架加载起来,其他的内容慢慢加载)。
        加载进来的内容在源代码中找不到,1.运用打开审核元素反的network,点击更多,headers会有信息出现。2.查看request Method的值,发现是post,表明向网站发送了请求,请求地址是Request URL:。3.再查看From Data的page:的值,就是加载的页数。
        说明,如果我们能构造一个From Data,就能向网页请求提交信息了。
    Requests的表单提交:
        核心方法:requests.post
        核心步骤:构造表单-提交表单-获取返回信息
import  re
import  requests
# url='https://www.crowdfunder.com/browse/deals/'
# html=requests.get(url).text
# print html
url =  'https://www.crowdfunder.com/browse/deals&template=false'
data = {
     'entities_only' : 'true' ,
     'page' : '2'
}
html_post = requests.post(url, data =data)
title = re.findall( '"card-title">(.*?)</div>' ,html_post.text,re.S)
for  each  in  title:
     print  each
    
    
极客学院的课程爬虫
    目标网站:http://www.jikexueyuan.com/course/
    目标内容:课程名称,课程介绍,课程时间,课程等级,学习人数
    设计知识:requests获取网页
              re.sub换页
              正则表达式匹配内容
    分析网站:1.换页时URL发生变化:http://www.jikexueyuan.com/course/?pageNum=2
          http://www.jikexueyuan.com/course/?pageNum=3
          。。。。。
              2.查看源代码
      3.爬取思路:先源码down下来,之后先正则表达式遍历整个页面,分别爬课程名称,课程介绍,课程时间,课程等级,学习人数。
         用for循环将信息一一对应。问题:个别标签为空。使用for循环时对应有问题。
        解决方法:先抓大,后抓小
     import  re
import  requests
# 因为 pycharm 默认编码是 gbk ;网页的默认编码是 utf-8. 编码不匹配,容易乱码,所以以下三行代码将编码器强制转换
import  sys
reload (sys)
sys.setdefaultencoding( "utf-8" )

class  spider( object ):
     def  __init__ ( self ):
         print  u' 开始爬取内容。。。 '

#getsource 用来获取网页源代码
     def  getsource( self ,url):
        html = requests.get(url)
         return  html.text

#changepage 用来生产不同页数的链接
     def  changepage( self ,url,total_page):
         # 当前的页数
         now_page =  int (re.search( 'pageNum=(\d+)' ,url,re.S).group( 1 ))
         # 定义一个列表
         page_group = []
         for  in  range (now_page,total_page+ 1 ):
            link = re.sub( 'pageNum=\d+' , 'pageNum=%s' %i,url,re.S)
            page_group.append(link)
         return  page_group # 将网址保存在  page_group 的列表中,然后返回列表
#geteveryclass 用来抓取每个课程块的信息
     def  geteveryclass( self ,source):
        everyclass = re.findall( '(<li deg="".*?</li>)' ,source,re.S)
         return  everyclass
#getinfo 用来从每个课程块中提取出我们需要的信息
     def  getinfo( self ,eachclass):
        info = {} # 定义字典
         info[ 'title' ] = re.search( 'target="_blank">(.*?)</a>' ,eachclass,re.S).group( 1 )
        info[ 'content' ] = re.search( '</h2><p>(.*?)</p>' ,eachclass,re.S).group( 1 )
         # 有两个 em 标签,因此获取到的第一个是时间,第二个是等级
         timeandlevel = re.findall( '<em>(.*?)</em>' ,eachclass,re.S)
        info[ 'classtime' ] = timeandlevel[ 0 ]
        info[ 'classlevel' ] = timeandlevel[ 1 ]
        info[ 'learnnum' ] = re.search( '"learn-number">(.*?)</em>' ,eachclass,re.S).group( 1 )
         return  info
#saveinfo 用来保存结果到 info.txt 文件中
     def  saveinfo( self ,classinfo):
        f =  open ( 'info.txt' , 'a' ) #a :追加的方式打开
         for  each  in  classinfo:
            f.writelines( 'title:'  + each[ 'title' ] +  '\n' )
            f.writelines( 'content:'  + each[ 'content' ] +  '\n' )
            f.writelines( 'classtime:'  + each[ 'classtime' ] +  '\n' )
            f.writelines( 'classlevel:'  + each[ 'classlevel' ] +  '\n' )
            f.writelines( 'learnnum:'  + each[ 'learnnum' ] + '\n\n' )
        f.close()

if  __name__ ==  '__main__' :

    classinfo = [] # 得到一个空列表,用来保存信息
     url =  'http://www.jikexueyuan.com/course/?pageNum=1'
     jikespider = spider()
    all_links = jikespider.changepage(url, 20 )
     for  link  in  all_links:
         print  u' 正在处理页面: + link
        html = jikespider.getsource(link)
         # 获取每一条课程
         everyclass = jikespider.geteveryclass(html)
         for  each  in  everyclass:
            info = jikespider.getinfo(each) #getinfo :获取信息
             classinfo.append(info) #classinfo 这个列表里,保存了很多的字典
     jikespider.saveinfo(classinfo)
    输出:开始爬取内容。。。
    正在处理页面:http://www.jikexueyuan.com/course/?pageNum=1
    正在处理页面:http://www.jikexueyuan.com/course/?pageNum=2
    正在处理页面:http://www.jikexueyuan.com/course/?pageNum=3
    正在处理页面:http://www.jikexueyuan.com/course/?pageNum=4
    正在处理页面:http://www.jikexueyuan.com/course/?pageNum=5
    正在处理页面:http://www.jikexueyuan.com/course/?pageNum=6
    。。。。
    
十七、XPath与多线程爬虫
神器XPath:XML Path Language。一门语言,
   可以再xml文档中查找信息,提取信息,比正则表达式厉害,简单
   支持HTML,
   通过元素和属性进行导航
安装:安装lxml库,
      from lxml import etree
      Selector=etree.HTML
神器XPath的使用:
XPath与HTML结构:HTML:树状结构,逐层展开,逐层定位,寻找独立节点
获取网页元素的XPath:
            手动分析法
            chrome生成法
            copy值为://*[@id="useful"]/li[1]
            *:只有一个id=useful,所以用*
            li[1]:第一条信息,去除[1]将以列表的形式返回

应用XPath提取内容
             from  lxml  import  etree
html =  '''
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title> 测试 - 常规用法 </title>
</head>
<body>
<div id="content">
    <ul id="useful">
        <li> 这是第一条信息 </li>
        <li> 这是第二条信息 </li>
        <li> 这是第三条信息 </li>
    </ul>
    <ul id="useless">
        <li> 不需要的信息 1</li>
        <li> 不需要的信息 2</li>
        <li> 不需要的信息 3</li>
    </ul>

    <div id="url">
        <a href="http://jikexueyuan.com"> 极客学院 </a>
        <a href="http://jikexueyuan.com/course/" title=" 极客学院课程库 "> 点我打开课程库 </a>
    </div>
</div>

</body>
</html>
'''

selector = etree.HTML(html)  # 将多行字符串转化为 xpath 可以识别的对象

# 提取文本
content = selector.xpath( '//ul[@id="useful"]/li/text()' )
#==content = selector.xpath('//div/ul[@id="useful"]/li/text()')
#==content = selector.xpath('//div[@id="content"]/ul[@id="useful"]/li/text()')
for  each  in  content:
     print  each

# 提取属性
link = selector.xpath( '//a/@href' )
for  each  in  link:
     print  each

title = selector.xpath( '//a/@title' )
print  title[ 0 ]

text = selector.xpath( '//a/text()' )
print  text[ 0 ]
text = selector.xpath( '//a/text()' )
print  text[ 1 ]
神器XPath的特殊用法
        以相同的字符开头
         starts-with(@属性名臣,属性字符相同部分)
        
        标签套标签
         string(.)
         from  lxml  import  etree
# 提取所有文字
html1= '''
<html>
<head lang="en">
    <meta charset="utf-8">
</head>
<body>
    <div id="test-1"> 内容 1</div>
    <div id="test-2"> 内容 2</div>
    <div id="testfault"> 内容 3</div>
</body>
</html>
'''
# 提取所有文字
html2= '''
<html>
<head lang="en">
    <meta charset="utf-8">
</head>
<body>
    <div id="test3">
         我左青龙,
        <span id="tiger">
             右白虎,
            <ul> 上朱雀,
                <li> 下玄武。 </li>
            </ul>
             老牛在当中
        </span>
         龙头在胸口
    </div>
</body>
</html>
'''
selector=etree.HTML(html1)
content=selector.xpath( '//div[starts-with(@id,"test")]/text()' )
for  each  in  content:
     print  each

selector=etree.HTML(html2)
content2=selector.xpath( '//div[@id="test3"]/text()' )
for  each  in  content2:
     print  each
# 提取的只有 我左青龙,龙头在胸口

# 所以还是用先大后小的办法
selector=etree.HTML(html2)
data_big=selector.xpath( '//div[@id="test3"]' )[ 0 ]
data_small=data_big.xpath( 'string(.)' )
content3=data_small.replace( '\n' , ' ' ).replace( ' ' , ' ' )
print  content3
Python并行化介绍与演示
        并行化:python的多线程(不是真的多线程)。多个线程同时处理任务
         搞笑,快速
        
        使用map完成并行化:
         map:一手包办了序列操作,参数传递和结果保存等一系列操作
         from multiprocessing.dummy import Pool
         pool=Pool(4):四核计算机,写了效率更高
         results=pool.map(爬取函数,网址列表)
            
             from  multiprocessing.dummy  import  Pool  as  ThreadPool
#as ThreadPool :重命名为 ThreadPool
import  requests
import  time # 用来对比并行化后的时间

# 获取 url 的源代码
def  getcource(url):
     html =requests.get(url)

urls=[]
# 生成二十条网址,添加到 urls 的列表里
for  in  range ( 1 , 21 ):
    newpage= 'http://tieba.baidu.com/p/35223957187?pn='  str (i)
    urls.append(newpage)

time1=time.time() # 记录第一个时间
for  in  urls:
     print  getcource(i)
time2=time.time() # 终止计时
print  ' 单线程耗时: ' + str (time2-time1) # 计算时间差

pool=ThreadPool( 2 ) # 并行操作,初始化一个实例
time3=time.time()
results=pool.map(getcource,urls)
pool.close()
pool.join()
time4=time.time()
print  ' 并行耗时 ' + str (time4-time3)

pool=ThreadPool( 4 ) # 并行操作,初始化一个实例
time5=time.time() # 开始计时
results=pool.map(getcource,urls) # map getcource urls 连接起来
pool.close()
pool.join()
time6=time.time()
print  ' 并行耗时 ' + str (time5-time6)

输出:None
None
None
None
None
。。。。(二十个)
单线程耗时:2.03800010681
并行耗时1.31300020218
并行耗时-0.825000047684

实战——百度贴吧
    目标网站: http://tieba.baidu.com/p/4815845758
    目标内容:跟帖用户名,跟帖内容,跟帖时间(前二十页的内容)
    涉及知识:requests获取网页
     xpath提取内容
     map实现多线程爬虫
    爬取前分析:
     1.网站换页时,URL变为http://tieba.baidu.com/p/4815845758?pn=1
        http://tieba.baidu.com/p/4815845758?pn=2
        http://tieba.baidu.com/p/4815845758?pn=3
     2.使用审核元素功能;放大镜定位到内容,
        获取正文时;由于id中有用户ID号码,所以不能作为定位节点,往上找
         from  lxml  import  etree
import  requests
import  json # 因为网页中 data-field 保存数据是以 json 保存的,所以需要 json 解析格式,也可以用正则表达式
from  multiprocessing.dummy  import  Pool  as  ThreadPool
# 以下三行代码是为了转换格式
import  sys
reload (sys)
sys.setdefaultencoding( 'utf-8' )
''' 重新运行之前请删除 content.txt ,因为文件操作使用追加方式,会导致内容太多。 '''

# 将获取到的数据写到 content 文本文件中
def  towrite(contentdict):
    f.writelines( ' 回帖时间 ' + str (contentdict[ 'topic_reply_time' ])+
                  '/n' )
    f.writelines( ' 回复内容 ' + unicode (contentdict[ 'topic_reply_content' ])+ '/n' )
    f.writelines( ' 回帖人 ' +contentdict[ 'user_name' ]+ '/n' )

# 爬虫函数
def  spider(url):
    html=requests.get(url) # 获得源代码
     selector=etree.HTML(html.text) # 将源代码转换为 xpath 可以处理的对象
     # 先获取整个 div ,先抓大,再抓小
     content_field=selector.xpath( '//div[@class="l_post j_l_post l_post_bright"]' )
    item={} # 定义一个字典,用于存放爬取内容
     for  each  in  content_field:
         # 对每一条回帖获取 data-field 信息,并将其中转移字符换位空 . 因为直接从 content_field 中获取信息,所以不需要 “//”
        #json.load json 的格式,解析成字典的格式
         reply_info=json.load(each.xpath( '@data-field' )[ 0 ].replace( '"' , ' ' ))
         # 读取所需信息
         author=reply_info[ 'author' ][ 'user_name' ]
        content=each.xpath( 'div[@class="d_post_content_main"]/div/cc/div[@class="d_post_content j_d_post_content"]/text()' )[ 0 ]
        reply_time=reply_info[ 'content' ][ 'date' ]
         # 打印出来
         print  content
         print  reply_time
         print  author
        item[ 'user_name' ]=author
        item[ 'topic_reply_time' ]=reply_time
        item[ 'topic_reply_content' ]=content
        towrite(item)


if  __name__ ==  '__main__' :
    pool = ThreadPool( 2 )
    f =  open ( 'content.txt' , 'a' )
    page = []
     for  in  range ( 1 , 21 ):
        newpage =  'http://tieba.baidu.com/p/4815845758?pn='  str (i)
        page.append(newpage)

    results = pool.map(spider, page)
    pool.close()
    pool.join()
    f.close()


十八、python操作数据库——MySQL:
数据库种类概述
数据库分类:SQL(结构化查询);NoSQL(非关系型数据库)——json
    单机(数据库运行在一台服务器上);分布式(数据库运行在服务器集群上)
    文件型(硬盘上);内存型(内存型)
    (算是分布式的子分类)批处理(将SQL分成MR任务);交互式(分级查询之后汇总)
数据库产品:SQL:
     开源:MySQL(学习创业首选);RostgreSQL;
      商业:SQLServer,ORACLE
    NoSQL:mongeDB(支持集群)
   neo4j(图数据库,但性能方面有问题,处理数据量较小)
   elasticsearch:全文检索存储;适合大量检索,监控
   LnfluxDB:有性能问题
    单机:MySQL;RostgreSQL
    分布式:HIVE
    cloudera IMPARA
    文件型:mongeDB;MySQL
    内存型:redis(支持复杂的数据类型);memcached
    批处理:HIVE;
    交互式:cloudera IMPALA;HBASE;DynamoDB
AWS:有名的云平台。减免维护数据库

MySQL,python数据库使用
MySQL:属于ORACLE。
使用AWS工具打开MySql:打开AWS官网,登陆AWS控制管理台。蓝色数据库分组。服务器放在东京,会使服务器访问速度快一些。需要修改安全组的设置,改为我的IP。需要使用可视化的管理工具,如:phpMyAdmin;Navicat等等
MySQLpython客户端的使用:
官方客户端mysql-connector
第三方客户端MySQLdb
MySQLdb的二次封装torndb使用

十九、
二十、


二十一、web开发
web开发介绍
C/S(客户机、服务器);B/S(浏览器、服务器)
动态网站:请求、执行python、执行结果、HTML返回
采用MVC:Mmodel:存储数据的代码;view:格式化和现实web应用的用户界面的代码;controller:将web应用粘合在一起并提供业务逻辑代码
每一个用户都是user类,user存储在model中,用户界面的代码在视图里;controller将M与V粘合并提供各种业务操作
CGI:通用网关接口。可以让一个客户端,从网页浏览器向服务器请求数据。是描述客户端和服务器程序之间传输数据的一种标准。独立于语言而存在、
应用于web的编程语言:PHP;ASP;JSPL;PYTHON。
web应用结构
前端:HTML(骨架);超文本标记语言,渲染显示
      CSS(样式表):层叠样式表
      JS(实现简单功能)
后台:PYTHON;PHP;JSP..
数据库:Mysql(关系型);MongoDB(非关系型)
    
    实战html/js:计算器
     < html >
< head  lang= "en" >
     < meta  charset= "utf-8" >
     < title > caculator </ title >
     < script  src= "add.js" >

     </ script >
</ head >
< body >
     < div  align= "center"  style= " margin-top 50 px ; " >
         < img  src= "/pic/1.jpg" >

     </ div >
     < div  align= "center"  style= " margin-top 50 px ; " >
         < form  name= "form1" >
             < input  type= "text"  placeholder= " 加数 name= "a1" > +
             < input  type= "text"  placeholder= " 加数 2"  name= "a2" > =
             < input  type= "text"  readonly= "readonly"  placeholder= "result"  name= "a3" >
             < input  type= "button"  value= " 计算 onclick= " add () " >

         </ form >
     </ div >
</ body >
</ html >

/**
 * Created by tutelary on 2016/10/14.
 */
function  add () {
     var  add1 =Number( document . form1 . a1 . value );;
     var  add2 =Number( document . form1 . a2 . value );
     var  result = add1 + add2 ;
     //noinspection JSAnnotator
     document . form1 . a3 . value = result ;
}
二十二:Python进行CGI编程
CGI介绍
是运行在服务器上的程序,提供同客户端HTML页面的接口,全称:Commom Gateway Interface。可以是python脚本,Perl脚本,c或者c++程序等。CGI程序是不限定使用语言的。
1993年由NCSA开发,1997年制定了CGI1.1规范

工作原理:服务器接受请求-解析URL并查找访问文件是否在服务器上,存在就返回文件的内容,否则返回错误信息。浏览器从服务器上接受信息,并显示接收的文件或者错误信息
缺点:每次CGI请求都要生成一个程序的副本来运行
解决办法:FastCGI先编译;mod_perl将解释器作为模块集成在web服务器中;使用C语言
CGI中的环境变量:CONTENT_TYPE:指示传递来信息的类型
HTTP_COOKIE:客户机的cookie内容
REMOTE_ADDR:发送请求的客户机的IP地址
REQUEST_METHOD:脚本被调用的方法:get,post。。。
。浏览器客户端通过两种方法向服务器传递信息:get和post。
get方法发送用户信息到服务器,数据信息包含在请求URL上,以?分割。可被浏览器缓存;会保存在历史记录中,有长度限制,不应用于敏感场合,只用于取回数据
post:向服务器传递数据更可靠。包含在http头部中;不会显示在URL中;可使用SSL加密。


python中的web服务器
python自带web服务器。
BaseHTTPServer:提供基本的Web服务和处理类
SimpleHTTPServer:包含执行get请求的SimpleHTTPRequestHandler类
CGIHTTPServer:包含处理post请求和执行的CGIHTTPRequestHandler类
开启服务器:
使用Apache,
第一个CGI:创建目录
   编写CGI程序
   开启服务器
   使用浏览器访问

CGI编写加法器:使用Python,GET,POST请求,配合HTML,JS完成加法器,并开启服务器
二十三、python web开发框架

框架:为了实现某个业界标准或者完成特别基本任务的软件组件规范,也指为了实现某个软件组件规范时,提供规范所要求之基础功能的软件产品。
框架类似于基础设施,提供并实现最为基础的软件架构和体系。就是程序的骨架。
为什么使用框架:可重用;成熟,稳健;可扩展性良好(第三方扩展);提高开发速度。
什么是web框架:支持动态网站,网络应用程序的软件框架。
工作方式:接受HTTP请求并处理,分派代码,产生HTML,创建HTTP响应。
web框架通常包括URL路由,数据库管理,模板引擎等
web框架:着重业务逻辑;高度可重用;选对框架很重要。
MVC:大部分框架都做了MVC分离
ORM:对象,关系映射。将具体类映射为数据库的表
URL Route:不同URL访问映射为不同函数中,完成不同的操作
Tenplate:模板。将后台数据通过渲染传入前段。

    python常用web框架
Django
优点:完美文档;全套的解决方案;强大的URL路由配置;自助管理后台
缺点:系统紧耦合;自带ORM不够强大;Template比较弱
web.py和Tornado
Flask和Bottle(微框架)
优点:聚焦在业务逻辑上;学习成本低;灵活性,伸缩性强
缺点:很多逻辑需要开发者操刀;安装很多模块之后体积较大
Flask:核心简单,易于扩展。不包含数据库抽象层,表单验证等。可扩展框架。
安装:pip install flask
     验证安装:import flask

Flask实战——加法器
目标:使用Python,Flash,配合HTML,JS完成加法器,并开启服务器
static:静态文件存放文件夹。存放JS,图片等
          templates:模板文件夹,存放html文件
        index.py文件
         #coding:utf-8
from  flask  import  Flask
from  flask  import  render_template
from  flask  import  url_for
from  flask  import  request # 从前台拿数据
from  flask  import  redirect # 页面跳转
app=Flask(__name__) # 实例化一个 Flask 类,对象为 app

@ app.route ( '/' , methods =[ 'GET' , 'POST' ])
def  index():
     return  redirect(url_for( 'add' ))

@ app.route ( '/add' , methods =[ 'GET' , 'POST' ]) # 默认路径 , 用修饰器使函数接受两种方式
def  add(): #
    #message="Back message"
     if  request.method== 'POST' :

        a=request.form[ 'a1' ]
        b=request.form[ 'a2' ]
        a= int (a)
        b= int (b)
        c=a+b;
         return  render_template( 'asdf.html' , message = str (c)) # 返回渲染后的结果
         return  render_template( 'asdf.html' message =a)
     return   render_template( 'asdf.html' )
if  __name__== "__main__" : # 设定如果是独立运行,则 run 被调用
     app.run( port = 8080 )

asdf.html文件
< html >
< head  lang= "en" >
     < meta  charset= "utf-8" >
     < title > caculator </ title >
<!--    <script src="add.js">

    </script>-->
</ head >
< body >
     < div  align= "center"  style= " margin-top 50 px ; " >
         <!-- 后台的渲染引擎会将 url_for 中的内容渲染为 <img src="/static/1.jpg">-->
         < img  src= "{{url_for('static',filename='1.jpg')}}" >

     </ div >
     < div  align= "center"  style= " margin-top 50 px ; " >
         <!--{{message}}-->
         < form  name= "form1"  method= "POST" >
             <!--{{message}}-->
             < input  type= "text"  placeholder= " 加数 name= "a1" > +
             < input  type= "text"  placeholder= " 加数 2"  name= "a2" > =
             < input  type= "text"  readonly= "readonly"  placeholder= "result"  name= "a3"  value= "{{message}}" >
             < input  type= "submit"  value= " 计算 onclick= " add () " >

         </ form >
     </ div >
</ body >
</ html >
        
二十四、flask表单开发
表单:
html页面中负责数据采集功能的部件,可以采集到用户输入的内容。由表单标签,表单域,表单按钮组成。通过表单,将用户输入的数据提交给服务器,并交由服务端进行处理
表单标签:声明表单的范围,位于表单标签中的元素将被提交
<form></form>
属性:method(提交方式,get,post),enctype(编码),action(提交页面)
表单域:文本框,密码框等
<input..../>
属性:type(类型),name,value(值)
文本框:text;
密码框:possword
文本区域:textarea
文件上传框:file
单选框:radio
复选框:checkbox
表单按钮:提交按钮,复位按钮,一般按钮
     <!DOCTYPE  html >
     < html  lang= "en" >
< head >
     < meta  charset= "UTF-8" >
     < title > 表单 </ title >
     < script  type= "text/javascript"  src= "CheckValue.js" >

     </ script >
</ head >
< body >
     < div  align= "center" >
     < h1 > User Management </ h1 >
     < form  name= "form1" >
         < input  type= "text"  placeholder= "username"  name= "text1"  />
     < input  type= "password"  placeholder= "password"  name= "passwoed" />
         < textarea  placeholder= "textarea"  style= " resize none " ></ textarea >
         < input  type= "file"  name= "file" />
         < input  type= "radio"  name= "Option"  value= "Option1" /> Option1
         < input  type= "radio"  name= "Option"  value= "Option1" /> Option2
         < input  type= "checkbox"  name= "check"  value= "Option1" /> Option1
         < input  type= "checkbox"  name= "check"  value= "Option1" /> Option2
         < input  type= "submit"  value= "Submit" />
         < input  type= "reset"  value= "Reset" />
         < input  type= "button"  value= "button"  onclick= " getValue () " />

     </ form >
     </ div >
</ body >
</ html >
CheckValue.js
/**
 * Created by tutelary on 2016/10/24.
 */
function  getValue ()
{
     var  text = document . form1 .text1. value ;
     alert ( text );
     var  arr = document . form1 .check; //多选框的打印
     alert ( arr [ 0 ]. value )
}

表单的提交方式
    get:通过url,默认提交方式。数据在URL中可以看到
post:数据放置在HTML HEADER中提交
get:可以被浏览器缓存,因为是URL形式的。有长度限制,会有安全问题
post:请求的URL可以缓存,但数据不会被保存。不便于分享。没有长度限制
get适用场合:单纯请求数据,不进行其他操作;表单数据不超过1024个字符。对安全性要求一般的场合
post适用场合:数据不仅用于请求,需要插入数据库;表单数据过长时(论文);不是ASCIIS编码时

实战——用户管理
    使用flask框架,配合HTML和JS程序,编写一个页面,该页面判断用户提交的用户名和密码是否分别jikexueyuan和123456,如果是则跳转到极客学院的首页,否则返回错误信息。
main.py
#coding:utf-8
from  flask  import  Flask
from  flask  import  request
from  flask  import  render_template
from  flask  import  redirect #重定向

app=Flask(__name__)

from  wtforms  import  Form,TextField,PasswordField,validators
#分别是表单,文本框,密码框,验证器(帮助验证表单内容)

class  LoginForm(Form):
    username = TextField( "username" ,[validators.Required()]) #表明username是必须要填入的对象
     password=PasswordField( "password" ,[validators.Required()])
@ app.route ( "/user" , methods =[ 'GET' , 'POST' ])
def  login():
    myform=LoginForm(request.form)
     if  request.method== 'POST' :
         # username=request.form['username']
        # password=request.form['password']
        #if username=="jikexueyuan" and password=="123456":
         if  myform.username.data ==  "jikexueyuan"  and  myform.password.data ==  "123456"  and  myform.validate():
             return  redirect( "http://www.jikexueyuan.com" )
         else :
            message= "login failed"
             return  render_template ( 'index.html' , message =message, form =myform)
     return  render_template ( 'index.html' , form =myform)

if  __name__== "__main__" : #设定如果是独立运行,则run被调用
     app.run( port = 8080 )
index.html
<!DOCTYPE  html >
< html  lang= "en" >
< head >
     < meta  charset= "UTF-8" >
     < title > 表单 </ title >
     <!--<script type="text/javascript" src="CheckValue.js">-->

    <!--</script>-->
</ head >
< body >
     < div  align= "center" >
     < h1 > User Management </ h1 >
        {% if message %} {{message}} {% endif %}
     < form  method= "post" >
        {{form.username}}
         <!--<input type="text" placeholder="username" name="username" />-->
         < br >
        {{form.password}}
         <!--<input type="password" placeholder="password" name="password"/>-->
         < br >
         < input  type= "submit"  value= "Submit" />
         < input  type= "reset"  value= "Reset" />

     </ form >
     </ div >
</ body >
</ html >

二十五、数据库连接
数据库基础
何为数据库:电子化的文件柜,可增删改查。
数据库分类:关系型数据库:数据库中存放的数据是以关系存放的(MySQL。。。)
    非关系型数据库(BigTable/MongoDB(like doc)/LevelDB)
DBMS:为管理数据库而设计的电脑软件系统。一般会具有存储/截取/安全保障/备份等基础功能。
减少记录编档的时间
减少记录检索的时间
灵活的查找序列
灵活的输出格式
多个用户同时访问记录

安装mysql:
1.使用社区版(免费)www.mysql.com——>DOWNLOADS——>MySQL Community Downloads选择下载
MySQL Community Server和MySQL workbench两款软件
数据库查询语言SQL
SQL( structured Query Language)是一种用于数据库中的标准数据查询语言。不同数据库系统之间的SQL不能完全相互通用
SQL可以完成数据定义,数据操作,数据控制
查询:select 。。。from 表名 where 判断 order by (排序) id desc
插入:insert into 表名(字段)values()
删除:delete from 表名 where 
修改:update 表名 set 修改的值 where 
在python中进行SQL操作

实战使用falsk框架编写














猜你喜欢

转载自blog.csdn.net/cao_mary/article/details/79527339