识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
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.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
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.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
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.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
i
in
range
(
1
,
21
):
newpage=
'http://tieba.baidu.com/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
实战——百度贴吧
目标内容:跟帖用户名,跟帖内容,跟帖时间(前二十页的内容)
涉及知识: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
i
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=
"
计算
"
ο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.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框架编写