识python
python:面向对象(对象之间交互数据,各对象协同操作), 解释性语言。简单,功能强大
功能:
学习路线:
初级:初识—语法—运算符、表达式—控制流—函数—模块—数据结构—面向对象—文件、异常处理—标准库
进阶:正则表达式、多线程、网络编程、客户端编程、图形界面编程
高级:网络编程、wxpython
特点:严格区分大小写 简单,面向对象 开源 库非常丰富(标准库、) 跨平台使用 解释性语言(区别编译性语言c++,编译器编译为二进制,进入系统内存执行),通过解释器解释为字符码。 高级语言 目录:lib:放模块,自定义模块也在这里。
一、windows下环境配置 1.进入 https://www.python/ 点击downloads 3.。。的版本有新特性 2.。。的版本运行速度快。 现在多用其开发 安装都是next默认值
2.系统变量 用户变量:选择tmp(tmp和temp区别:tmp解决dos兼容性问题。两个一样,都可以选择 ) 系统变量:path:E:\python
3.集成开发环境 http://www.jetbrains/网站最下方(java语言开发)
用professional的版本 默认安装。快捷键(keymap)用eclipse的 4.java jdk环境(pycharm也是java开发)
二、osx系统下搭建python 1.下载集成开发环境pycharm http://www.jetbrains/。
三、linux系统下搭建python 1.测试linux是否安装python。打开终端:输入python查看版本 2.下载集成开发环境pycharm http://www.jetbrains/。 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 i in range ( 0 , 10 ): print (i) 输出:0123456789
for i in range ( 0 , 10 ): print ( "Item{0}" .format(i)) 输出:Item0 Item1 Item2 Item3 Item4 Item5 Item6 Item7 Item8 Item9
for i 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 i in [ 1 , 2 , 8 , 9 , 0 ]: print i 输出:12890
#range函数,生成一个集合的序列,个数为7-1,步长默认为1 for i in range ( 1 , 7 ): print "hello" 输出:hellohellohellohellohellohello
a= range ( 2 , 5 ) print a 输出:[2, 3, 4] #range中第三个参数代表步长,生成集合为1,3,5,7,9 for i in range ( 1 , 10 , 2 ): print i 输出:13579 #带嵌套的for语句,优先执行里面的语句,外层只做控制 for i 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 i in range ( 5 , 9 ): print i if i> 8 : break 输出:5678
#break在双层循环中 a= 10 while a<= 12 : a=a+ 1 for i in range ( 1 , 7 , 2 ): print i if i== 5 : break 输出:135135135
a= 10 while a<= 12 : a=a+ 1 for i 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= 9 func2(i) # i=9传递给a,函数内部i=7,所以输出7 print i #没有调用函数,输出函数外面的结果 输出:79 全局变量:作用域为全局,需要全局声明 def func3(): #定义函数 global i #声明全局变量,i的作用域在全局,函数外面也能用 i= 7 print i #局部变量 i= 9 func3() print i 输出:77
def func3(): #定义函数 global i #声明全局变量,i的作用域在全局,函数外面也能用 i= 7 print i #局部变量 func3() i= 9 #i的值改变 print i 输出:79
函数的使用与返回值 函数的调用:直接输入函数名,调用参数的时候,在括号里输入参数就行 def a(): i = 1 a() 函数的返回值:有的函数有,有的函数没有。返回可以一个值或多个值 #函数的返回值是通过return实现的 def test(): i= 7 return i #函数的整体值是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/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 i 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/welcome.html">huanying</a> <div class="list"> <ul> <li><a href="http://jikexueyuan/1.html">1 笨笨 </a></li> <li><a href="http://jikexueyuan/2.html">2 软软 </a></li> <li><a href="http://jikexueyuan/3.html">3 向冲 </a></li> </ul> </div> </div> </body> </html>
制作文本爬虫: 目标网站: http://jikexueyuan 目标内容:课程图片 实现原理: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/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/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/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/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/browse/deals/' # html=requests.get(url).text # print html url = 'https://www.crowdfunder/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/course/ 目标内容:课程名称,课程介绍,课程时间,课程等级,学习人数 设计知识:requests获取网页 re.sub换页 正则表达式匹配内容 分析网站:1.换页时URL发生变化:http://www.jikexueyuan/course/?pageNum=2 http://www.jikexueyuan/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 i 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/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/course/?pageNum=1 正在处理页面:http://www.jikexueyuan/course/?pageNum=2 正在处理页面:http://www.jikexueyuan/course/?pageNum=3 正在处理页面:http://www.jikexueyuan/course/?pageNum=4 正在处理页面:http://www.jikexueyuan/course/?pageNum=5 正在处理页面:http://www.jikexueyuan/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"> 极客学院 </a> <a href="http://jikexueyuan/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 i in range ( 1 , 21 ): newpage= 'http://tieba.baidu/p/35223957187?pn=' + str (i) urls.append(newpage)
time1=time.time() # 记录第一个时间 for i 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/p/4815845758 目标内容:跟帖用户名,跟帖内容,跟帖时间(前二十页的内容) 涉及知识:requests获取网页 xpath提取内容 map实现多线程爬虫 爬取前分析: 1.网站换页时,URL变为http://tieba.baidu/p/4815845758?pn=1 http://tieba.baidu/p/4815845758?pn=2 http://tieba.baidu/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 i in range ( 1 , 21 ): newpage = 'http://tieba.baidu/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= " 计算 " οnclick= " 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= " 计算 " οnclick= " 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" οnclick= " 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" ) 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——>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框架编写
特点:严格区分大小写 简单,面向对象 开源 库非常丰富(标准库、) 跨平台使用 解释性语言(区别编译性语言c++,编译器编译为二进制,进入系统内存执行),通过解释器解释为字符码。 高级语言 目录:lib:放模块,自定义模块也在这里。
一、windows下环境配置 1.进入 https://www.python/ 点击downloads 3.。。的版本有新特性 2.。。的版本运行速度快。 现在多用其开发 安装都是next默认值
2.系统变量 用户变量:选择tmp(tmp和temp区别:tmp解决dos兼容性问题。两个一样,都可以选择 ) 系统变量:path:E:\python
3.集成开发环境 http://www.jetbrains/网站最下方(java语言开发)
用professional的版本 默认安装。快捷键(keymap)用eclipse的 4.java jdk环境(pycharm也是java开发)
二、osx系统下搭建python 1.下载集成开发环境pycharm http://www.jetbrains/。
三、linux系统下搭建python 1.测试linux是否安装python。打开终端:输入python查看版本 2.下载集成开发环境pycharm http://www.jetbrains/。 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 i in range ( 0 , 10 ): print (i) 输出:0123456789
for i in range ( 0 , 10 ): print ( "Item{0}" .format(i)) 输出:Item0 Item1 Item2 Item3 Item4 Item5 Item6 Item7 Item8 Item9
for i 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 i in [ 1 , 2 , 8 , 9 , 0 ]: print i 输出:12890
#range函数,生成一个集合的序列,个数为7-1,步长默认为1 for i in range ( 1 , 7 ): print "hello" 输出:hellohellohellohellohellohello
a= range ( 2 , 5 ) print a 输出:[2, 3, 4] #range中第三个参数代表步长,生成集合为1,3,5,7,9 for i in range ( 1 , 10 , 2 ): print i 输出:13579 #带嵌套的for语句,优先执行里面的语句,外层只做控制 for i 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 i in range ( 5 , 9 ): print i if i> 8 : break 输出:5678
#break在双层循环中 a= 10 while a<= 12 : a=a+ 1 for i in range ( 1 , 7 , 2 ): print i if i== 5 : break 输出:135135135
a= 10 while a<= 12 : a=a+ 1 for i 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= 9 func2(i) # i=9传递给a,函数内部i=7,所以输出7 print i #没有调用函数,输出函数外面的结果 输出:79 全局变量:作用域为全局,需要全局声明 def func3(): #定义函数 global i #声明全局变量,i的作用域在全局,函数外面也能用 i= 7 print i #局部变量 i= 9 func3() print i 输出:77
def func3(): #定义函数 global i #声明全局变量,i的作用域在全局,函数外面也能用 i= 7 print i #局部变量 func3() i= 9 #i的值改变 print i 输出:79
函数的使用与返回值 函数的调用:直接输入函数名,调用参数的时候,在括号里输入参数就行 def a(): i = 1 a() 函数的返回值:有的函数有,有的函数没有。返回可以一个值或多个值 #函数的返回值是通过return实现的 def test(): i= 7 return i #函数的整体值是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/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 i 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/welcome.html">huanying</a> <div class="list"> <ul> <li><a href="http://jikexueyuan/1.html">1 笨笨 </a></li> <li><a href="http://jikexueyuan/2.html">2 软软 </a></li> <li><a href="http://jikexueyuan/3.html">3 向冲 </a></li> </ul> </div> </div> </body> </html>
制作文本爬虫: 目标网站: http://jikexueyuan 目标内容:课程图片 实现原理: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/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/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/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/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/browse/deals/' # html=requests.get(url).text # print html url = 'https://www.crowdfunder/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/course/ 目标内容:课程名称,课程介绍,课程时间,课程等级,学习人数 设计知识:requests获取网页 re.sub换页 正则表达式匹配内容 分析网站:1.换页时URL发生变化:http://www.jikexueyuan/course/?pageNum=2 http://www.jikexueyuan/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 i 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/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/course/?pageNum=1 正在处理页面:http://www.jikexueyuan/course/?pageNum=2 正在处理页面:http://www.jikexueyuan/course/?pageNum=3 正在处理页面:http://www.jikexueyuan/course/?pageNum=4 正在处理页面:http://www.jikexueyuan/course/?pageNum=5 正在处理页面:http://www.jikexueyuan/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"> 极客学院 </a> <a href="http://jikexueyuan/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 i in range ( 1 , 21 ): newpage= 'http://tieba.baidu/p/35223957187?pn=' + str (i) urls.append(newpage)
time1=time.time() # 记录第一个时间 for i 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/p/4815845758 目标内容:跟帖用户名,跟帖内容,跟帖时间(前二十页的内容) 涉及知识:requests获取网页 xpath提取内容 map实现多线程爬虫 爬取前分析: 1.网站换页时,URL变为http://tieba.baidu/p/4815845758?pn=1 http://tieba.baidu/p/4815845758?pn=2 http://tieba.baidu/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 i in range ( 1 , 21 ): newpage = 'http://tieba.baidu/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= " 计算 " οnclick= " 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= " 计算 " οnclick= " 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" οnclick= " 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" ) 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——>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框架编写
更多推荐
python——自学入门
发布评论