Commit 32127829 authored by jackfrued's avatar jackfrued

更新了部分文档和代码

parent 2d08d42f
from turtle import* """
绘制小猪佩奇
"""
from turtle import *
def nose(x,y):#鼻子 def nose(x,y):
penup()#提起笔 """画鼻子"""
goto(x,y)#定位 penup()
pendown()#落笔,开始画 # 将海龟移动到指定的坐标
setheading(-30)#将乌龟的方向设置为to_angle/为数字(0-东、90-北、180-西、270-南) goto(x,y)
begin_fill()#准备开始填充图形 pendown()
a=0.4 # 设置海龟的方向(0-东、90-北、180-西、270-南)
setheading(-30)
begin_fill()
a = 0.4
for i in range(120): for i in range(120):
if 0<=i<30 or 60<=i<90: if 0 <= i < 30 or 60 <= i <90:
a=a+0.08 a = a + 0.08
left(3) #向左转3度 # 向左转3度
forward(a) #向前走a的步长 left(3)
# 向前走
forward(a)
else: else:
a=a-0.08 a = a - 0.08
left(3) left(3)
forward(a) forward(a)
end_fill()#填充完成 end_fill()
penup() penup()
setheading(90) setheading(90)
forward(25) forward(25)
setheading(0) setheading(0)
forward(10) forward(10)
pendown() pendown()
pencolor(255,155,192)#画笔颜色 # 设置画笔的颜色(红, 绿, 蓝)
pencolor(255, 155, 192)
setheading(10) setheading(10)
begin_fill() begin_fill()
circle(5) circle(5)
color(160,82,45)#返回或设置pencolor和fillcolor color(160, 82, 45)
end_fill() end_fill()
penup() penup()
setheading(0) setheading(0)
forward(20) forward(20)
pendown() pendown()
pencolor(255,155,192) pencolor(255, 155, 192)
setheading(10) setheading(10)
begin_fill() begin_fill()
circle(5) circle(5)
color(160,82,45) color(160, 82, 45)
end_fill() end_fill()
def head(x,y):#头 def head(x, y):
color((255,155,192),"pink") """画头"""
color((255, 155, 192), "pink")
penup() penup()
goto(x,y) goto(x,y)
setheading(0) setheading(0)
pendown() pendown()
begin_fill() begin_fill()
setheading(180) setheading(180)
circle(300,-30) circle(300, -30)
circle(100,-60) circle(100, -60)
circle(80,-100) circle(80, -100)
circle(150,-20) circle(150, -20)
circle(60,-95) circle(60, -95)
setheading(161) setheading(161)
circle(-300,15) circle(-300, 15)
penup() penup()
goto(-100,100) goto(-100, 100)
pendown() pendown()
setheading(-30) setheading(-30)
a=0.4 a = 0.4
for i in range(60): for i in range(60):
if 0<=i<30 or 60<=i<90: if 0<= i < 30 or 60 <= i < 90:
a=a+0.08 a = a + 0.08
lt(3) #向左转3度 lt(3) #向左转3度
fd(a) #向前走a的步长 fd(a) #向前走a的步长
else: else:
a=a-0.08 a = a - 0.08
lt(3) lt(3)
fd(a) fd(a)
end_fill() end_fill()
def ears(x,y): #耳朵 def ears(x,y):
color((255,155,192),"pink") """画耳朵"""
color((255, 155, 192), "pink")
penup() penup()
goto(x,y) goto(x, y)
pendown() pendown()
begin_fill() begin_fill()
setheading(100) setheading(100)
circle(-50,50) circle(-50, 50)
circle(-10,120) circle(-10, 120)
circle(-50,54) circle(-50, 54)
end_fill() end_fill()
penup() penup()
setheading(90) setheading(90)
forward(-12) forward(-12)
...@@ -96,14 +104,15 @@ def ears(x,y): #耳朵 ...@@ -96,14 +104,15 @@ def ears(x,y): #耳朵
pendown() pendown()
begin_fill() begin_fill()
setheading(100) setheading(100)
circle(-50,50) circle(-50, 50)
circle(-10,120) circle(-10, 120)
circle(-50,56) circle(-50, 56)
end_fill() end_fill()
def eyes(x,y):#眼睛 def eyes(x,y):
color((255,155,192),"white") """画眼睛"""
color((255, 155, 192), "white")
penup() penup()
setheading(90) setheading(90)
forward(-20) forward(-20)
...@@ -113,7 +122,6 @@ def eyes(x,y):#眼睛 ...@@ -113,7 +122,6 @@ def eyes(x,y):#眼睛
begin_fill() begin_fill()
circle(15) circle(15)
end_fill() end_fill()
color("black") color("black")
penup() penup()
setheading(90) setheading(90)
...@@ -124,8 +132,7 @@ def eyes(x,y):#眼睛 ...@@ -124,8 +132,7 @@ def eyes(x,y):#眼睛
begin_fill() begin_fill()
circle(3) circle(3)
end_fill() end_fill()
color((255, 155, 192), "white")
color((255,155,192),"white")
penup() penup()
seth(90) seth(90)
forward(-25) forward(-25)
...@@ -135,7 +142,6 @@ def eyes(x,y):#眼睛 ...@@ -135,7 +142,6 @@ def eyes(x,y):#眼睛
begin_fill() begin_fill()
circle(15) circle(15)
end_fill() end_fill()
color("black") color("black")
penup() penup()
setheading(90) setheading(90)
...@@ -148,8 +154,9 @@ def eyes(x,y):#眼睛 ...@@ -148,8 +154,9 @@ def eyes(x,y):#眼睛
end_fill() end_fill()
def cheek(x,y):#腮 def cheek(x,y):
color((255,155,192)) """画脸颊"""
color((255, 155, 192))
penup() penup()
goto(x,y) goto(x,y)
pendown() pendown()
...@@ -159,33 +166,37 @@ def cheek(x,y):#腮 ...@@ -159,33 +166,37 @@ def cheek(x,y):#腮
end_fill() end_fill()
def mouth(x,y): #嘴 def mouth(x,y):
color(239,69,19) """画嘴巴"""
color(239, 69, 19)
penup() penup()
goto(x,y) goto(x, y)
pendown() pendown()
setheading(-80) setheading(-80)
circle(30,40) circle(30, 40)
circle(40,80) circle(40, 80)
def setting(): #参数设置 def setting():
"""设置参数"""
pensize(4) pensize(4)
hideturtle() #使乌龟无形(隐藏) # 隐藏海龟
colormode(255) #将其设置为1.0或255.随后 颜色三元组的r,g,b值必须在0 .. cmode范围内 hideturtle()
color((255,155,192),"pink") colormode(255)
setup(840,500) color((255, 155, 192), "pink")
setup(840, 500)
speed(10) speed(10)
def main(): def main():
setting() #画布、画笔设置 """主函数"""
nose(-100,100) #鼻子 setting()
head(-69,167) #头 nose(-100, 100)
ears(0,160) #耳朵 head(-69, 167)
eyes(0,140) #眼睛 ears(0, 160)
cheek(80,10) #腮 eyes(0, 140)
mouth(-20,30) #嘴 cheek(80, 10)
mouth(-20, 30)
done() done()
......
This diff is collapsed.
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
#### 指令和程序 #### 指令和程序
计算机的硬件系统通常由五大部件构成,包括:运算器、控制器、存储器、输入设备和输出设备。其中,运算器和控制器放在一起就是我们通常所说的中央处理器,它的功能是执行各种运算和控制指令以及处理计算机软件中的数据。我们通常所说的程序实际上就是指令的集合,我们程序就是将一系列的指令按照某种方式组织到一起,然后通过这些指令去控制计算机做我们想让它做的事情。今天我们使用的计算机虽然器件做工越来越精密,处理能力越来越强大,但究其本质来说仍然属于[“冯·诺依曼结构”](https://zh.wikipedia.org/wiki/%E5%86%AF%C2%B7%E8%AF%BA%E4%BC%8A%E6%9B%BC%E7%BB%93%E6%9E%84)的计算机。“冯·诺依曼结构”有两个关键点,一是提出了将存储设备与中央处理器分开,二是提出了将数据以二进制方式编码。二进制是一种“逢二进一”的计数法,跟我们人类使用的“逢十进一”的计数法没有实质性的区别,人类因为有十根手指所以使用了十进制(因为在数数时十根手指用完之后就只能进位了,当然凡事都有例外,玛雅人可能是因为长年光着脚的原因把脚趾头也算上了,于是他们使用了二十进制的计数法,在这种计数法的指导下玛雅人的历法就与我们的不太一致,而按照玛雅人的历法,2012年是上一个所谓的“太阳纪”的最后一年,而2013年则是新的“太阳纪”的开始,后来这件事情被以讹传讹的方式误传为2012年就是玛雅人预言的世界末日这种荒诞的说法,今天我们可以大胆的猜测,玛雅文明之所以发展缓慢估计也与使用了二十进制有关),对于计算机来说,二进制在物理器件上来说是最容易实现的(高电压表示1,低电压表示0),于是在“冯·诺依曼结构”的计算机都使用了二进制。虽然我们并不需要每个程序员都能够使用二进制的思维方式来工作,但是了解二进制以及它与我们生活中的十进制之间的转换关系,以及二进制与八进制和十六进制的转换关系还是有必要的。如果你对这一点不熟悉,可以自行使用[维基百科](https://zh.wikipedia.org/wiki/%E4%BA%8C%E8%BF%9B%E5%88%B6)或者[百度百科](https://baike.baidu.com)科普一下。 计算机的硬件系统通常由五大部件构成,包括:运算器、控制器、存储器、输入设备和输出设备。其中,运算器和控制器放在一起就是我们通常所说的中央处理器,它的功能是执行各种运算和控制指令以及处理计算机软件中的数据。我们通常所说的程序实际上就是指令的集合,我们程序就是将一系列的指令按照某种方式组织到一起,然后通过这些指令去控制计算机做我们想让它做的事情。今天我们使用的计算机虽然器件做工越来越精密,处理能力越来越强大,但究其本质来说仍然属于[“冯·诺依曼结构”](https://zh.wikipedia.org/wiki/%E5%86%AF%C2%B7%E8%AF%BA%E4%BC%8A%E6%9B%BC%E7%BB%93%E6%9E%84)的计算机。“冯·诺依曼结构”有两个关键点,一是指出要将存储设备与中央处理器分开,二是提出了将数据以二进制方式编码。二进制是一种“逢二进一”的计数法,跟我们人类使用的“逢十进一”的计数法没有实质性的区别,人类因为有十根手指所以使用了十进制(因为在数数时十根手指用完之后就只能进位了,当然凡事都有例外,玛雅人可能是因为长年光着脚的原因把脚趾头也算上了,于是他们使用了二十进制的计数法,在这种计数法的指导下玛雅人的历法就与我们平常使用的历法不一样,而按照玛雅人的历法,2012年是上一个所谓的“太阳纪”的最后一年,而2013年则是新的“太阳纪”的开始,后来这件事情被以讹传讹的方式误传为”2012年是玛雅人预言的世界末日“这种荒诞的说法,今天我们可以大胆的猜测,玛雅文明之所以发展缓慢估计也与使用了二十进制有关)。对于计算机来说,二进制在物理器件上来说是最容易实现的(高电压表示1,低电压表示0),于是在“冯·诺依曼结构”的计算机都使用了二进制。虽然我们并不需要每个程序员都能够使用二进制的思维方式来工作,但是了解二进制以及它与我们生活中的十进制之间的转换关系,以及二进制与八进制和十六进制的转换关系还是有必要的。如果你对这一点不熟悉,可以自行使用[维基百科](https://zh.wikipedia.org/wiki/%E4%BA%8C%E8%BF%9B%E5%88%B6)或者[百度百科](https://baike.baidu.com)科普一下。
### 变量和类型 ### 变量和类型
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
- 浮点型:浮点数也就是小数,之所以称为浮点数,是因为按照科学记数法表示时,一个浮点数的小数点位置是可变的,浮点数除了数学写法(如`123.456`)之外还支持科学计数法(如`1.23456e2`)。 - 浮点型:浮点数也就是小数,之所以称为浮点数,是因为按照科学记数法表示时,一个浮点数的小数点位置是可变的,浮点数除了数学写法(如`123.456`)之外还支持科学计数法(如`1.23456e2`)。
- 字符串型:字符串是以单引号或双引号括起来的任意文本,比如`'hello'``"hello"`,字符串还有原始字符串表示法、字节字符串表示法、Unicode字符串表示法,而且可以书写成多行的形式(用三个单引号或三个双引号开头,三个单引号或三个双引号结尾)。 - 字符串型:字符串是以单引号或双引号括起来的任意文本,比如`'hello'``"hello"`,字符串还有原始字符串表示法、字节字符串表示法、Unicode字符串表示法,而且可以书写成多行的形式(用三个单引号或三个双引号开头,三个单引号或三个双引号结尾)。
- 布尔型:布尔值只有`True``False`两种值,要么是`True`,要么是`False`,在Python中,可以直接用`True``False`表示布尔值(请注意大小写),也可以通过布尔运算计算出来(例如`3 < 5`会产生布尔值`True`,而`2 == 1`会产生布尔值`False`)。 - 布尔型:布尔值只有`True``False`两种值,要么是`True`,要么是`False`,在Python中,可以直接用`True``False`表示布尔值(请注意大小写),也可以通过布尔运算计算出来(例如`3 < 5`会产生布尔值`True`,而`2 == 1`会产生布尔值`False`)。
- 复数型:形如`3+5j`,跟数学上的复数表示一样,唯一不同的是虚部的i换成了j - 复数型:形如`3+5j`,跟数学上的复数表示一样,唯一不同的是虚部的`i`换成了`j`
#### 变量命名 #### 变量命名
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
- 受保护的实例属性用单个下划线开头(后面会讲到)。 - 受保护的实例属性用单个下划线开头(后面会讲到)。
- 私有的实例属性用两个下划线开头(后面会讲到)。 - 私有的实例属性用两个下划线开头(后面会讲到)。
当然,作为一个专业的程序员,给变量(事实上应该是所有的标识符)命名做到见名知意也是非常重要的。 当然,作为一个专业的程序员,给变量(事实上应该是所有的标识符)命名做到见名知意也是非常重要的。
#### 变量的使用 #### 变量的使用
...@@ -39,7 +39,6 @@ ...@@ -39,7 +39,6 @@
Version: 0.1 Version: 0.1
Author: 骆昊 Author: 骆昊
Date: 2018-02-27
""" """
a = 321 a = 321
...@@ -62,7 +61,6 @@ print(a ** b) ...@@ -62,7 +61,6 @@ print(a ** b)
Version: 0.1 Version: 0.1
Author: 骆昊 Author: 骆昊
Date: 2018-02-27
""" """
a = int(input('a = ')) a = int(input('a = '))
...@@ -138,7 +136,6 @@ Python支持多种运算符,下表大致按照优先级从高到低的顺序 ...@@ -138,7 +136,6 @@ Python支持多种运算符,下表大致按照优先级从高到低的顺序
Version: 0.1 Version: 0.1
Author: 骆昊 Author: 骆昊
Date: 2018-02-27
""" """
a = 5 a = 5
...@@ -178,7 +175,6 @@ F = 1.8C + 32 ...@@ -178,7 +175,6 @@ F = 1.8C + 32
Version: 0.1 Version: 0.1
Author: 骆昊 Author: 骆昊
Date: 2018-02-27
""" """
f = float(input('请输入华氏温度: ')) f = float(input('请输入华氏温度: '))
...@@ -195,7 +191,6 @@ print('%.1f华氏度 = %.1f摄氏度' % (f, c)) ...@@ -195,7 +191,6 @@ print('%.1f华氏度 = %.1f摄氏度' % (f, c))
Version: 0.1 Version: 0.1
Author: 骆昊 Author: 骆昊
Date: 2018-02-27
""" """
import math import math
...@@ -216,7 +211,6 @@ print('面积: %.2f' % area) ...@@ -216,7 +211,6 @@ print('面积: %.2f' % area)
Version: 0.1 Version: 0.1
Author: 骆昊 Author: 骆昊
Date: 2018-02-27
""" """
year = int(input('请输入年份: ')) year = int(input('请输入年份: '))
......
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
Version: 0.1 Version: 0.1
Author: 骆昊 Author: 骆昊
Date: 2018-02-28
""" """
username = input('请输入用户名: ') username = input('请输入用户名: ')
...@@ -44,7 +43,6 @@ f(x) = x + 2 (-1 <= x <= 1) ...@@ -44,7 +43,6 @@ f(x) = x + 2 (-1 <= x <= 1)
Version: 0.1 Version: 0.1
Author: 骆昊 Author: 骆昊
Date: 2018-02-28
""" """
x = float(input('x = ')) x = float(input('x = '))
...@@ -68,7 +66,6 @@ f(x) = x + 2 (-1 <= x <= 1) ...@@ -68,7 +66,6 @@ f(x) = x + 2 (-1 <= x <= 1)
Version: 0.1 Version: 0.1
Author: 骆昊 Author: 骆昊
Date: 2018-02-28
""" """
x = float(input('x = ')) x = float(input('x = '))
...@@ -94,7 +91,6 @@ print('f(%.2f) = %.2f' % (x, y)) ...@@ -94,7 +91,6 @@ print('f(%.2f) = %.2f' % (x, y))
Version: 0.1 Version: 0.1
Author: 骆昊 Author: 骆昊
Date: 2018-02-28
""" """
value = float(input('请输入长度: ')) value = float(input('请输入长度: '))
...@@ -115,7 +111,6 @@ else: ...@@ -115,7 +111,6 @@ else:
Version: 0.1 Version: 0.1
Author: 骆昊 Author: 骆昊
Date: 2018-02-28
""" """
from random import randint from random import randint
...@@ -150,7 +145,6 @@ print(result) ...@@ -150,7 +145,6 @@ print(result)
Version: 0.1 Version: 0.1
Author: 骆昊 Author: 骆昊
Date: 2018-02-28
""" """
score = float(input('请输入成绩: ')) score = float(input('请输入成绩: '))
...@@ -175,7 +169,6 @@ print('对应的等级是:', grade) ...@@ -175,7 +169,6 @@ print('对应的等级是:', grade)
Version: 0.1 Version: 0.1
Author: 骆昊 Author: 骆昊
Date: 2018-02-28
""" """
import math import math
...@@ -193,7 +186,7 @@ else: ...@@ -193,7 +186,7 @@ else:
``` ```
> **说明:**上面的代码中使用了`math`模块的`sqrt`函数来计算平方根。用边长计算三角形面积的公式叫做[海伦公式](https://zh.wikipedia.org/zh-hans/海伦公式)。 > **说明:**上面的代码中使用了`math`模块的`sqrt`函数来计算平方根。用边长计算三角形面积的公式叫做[海伦公式](https://zh.wikipedia.org/zh-hans/海伦公式)。
#### 练习5:实现一个个人所得税计算器。 #### 练习5:个人所得税计算器。
```Python ```Python
""" """
...@@ -201,7 +194,6 @@ else: ...@@ -201,7 +194,6 @@ else:
Version: 0.1 Version: 0.1
Author: 骆昊 Author: 骆昊
Date: 2018-02-28
""" """
salary = float(input('本月收入: ')) salary = float(input('本月收入: '))
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
### 循环结构的应用场景 ### 循环结构的应用场景
如果在程序中我们需要重复的执行某条或某些指令,例如用程序控制机器人踢足球,如果机器人持球而且还没有进入射门范围,那么我们就要一直发出让机器人向球门方向奔跑的指令。当然你可能已经注意到了,刚才的描述中其实不仅仅有需要重复的动作,还有我们上一个章节讲到的分支结构。再举一个简单的例子,比如在我们的程序中要实现每隔1秒中在屏幕上打印一个&quot;hello, world&quot;这样的字符串并持续一个小时,我们肯定不能够将`print('hello, world')`这句代码写上3600遍,如果真的需要这样做那么我们的工作就太无聊了。因此,我们需要循环结构,使用循环结构我们就可以轻松的控制某件事或者某些事重复、重复、再重复的发生。在Python中构造循环结构有两种做法,一种是`for-in`循环,一种是`while`循环。 如果在程序中我们需要重复的执行某条或某些指令,例如用程序控制机器人踢足球,如果机器人持球而且还没有进入射门范围,那么我们就要一直发出让机器人向球门方向奔跑的指令。当然你可能已经注意到了,刚才的描述中其实不仅仅有需要重复的动作,还有我们上一个章节讲到的分支结构。再举一个简单的例子,比如在我们的程序中要实现每隔1秒中在屏幕上打印一个&quot;hello, world&quot;这样的字符串并持续一个小时,我们肯定不能够将`print('hello, world')`这句代码写上3600遍,如果真的需要这样做那么编程的工作就太无聊了。因此,我们需要了解一下循环结构,有了循环结构我们就可以轻松的控制某件事或者某些事重复、重复、再重复的发生。在Python中构造循环结构有两种做法,一种是`for-in`循环,一种是`while`循环。
### for-in循环 ### for-in循环
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
Version: 0.1 Version: 0.1
Author: 骆昊 Author: 骆昊
Date: 2018-03-01
""" """
sum = 0 sum = 0
...@@ -37,7 +36,6 @@ print(sum) ...@@ -37,7 +36,6 @@ print(sum)
Version: 0.1 Version: 0.1
Author: 骆昊 Author: 骆昊
Date: 2018-03-01
""" """
sum = 0 sum = 0
...@@ -54,7 +52,6 @@ print(sum) ...@@ -54,7 +52,6 @@ print(sum)
Version: 0.1 Version: 0.1
Author: 骆昊 Author: 骆昊
Date: 2018-03-01
""" """
sum = 0 sum = 0
...@@ -77,7 +74,6 @@ print(sum) ...@@ -77,7 +74,6 @@ print(sum)
Version: 0.1 Version: 0.1
Author: 骆昊 Author: 骆昊
Date: 2018-03-01
""" """
import random import random
...@@ -109,8 +105,6 @@ if counter > 7: ...@@ -109,8 +105,6 @@ if counter > 7:
Version: 0.1 Version: 0.1
Author: 骆昊 Author: 骆昊
Date: 2018-03-01
""" """
for i in range(1, 10): for i in range(1, 10):
...@@ -196,7 +190,6 @@ for factor in range(x, 0, -1): ...@@ -196,7 +190,6 @@ for factor in range(x, 0, -1):
Version: 0.1 Version: 0.1
Author: 骆昊 Author: 骆昊
Date: 2018-03-01
""" """
row = int(input('请输入行数: ')) row = int(input('请输入行数: '))
......
...@@ -27,7 +27,6 @@ fmn = 1 ...@@ -27,7 +27,6 @@ fmn = 1
for num in range(1, m - n + 1): for num in range(1, m - n + 1):
fmn *= num fmn *= num
print(fm // fn // fmn) print(fm // fn // fmn)
``` ```
### 函数的作用 ### 函数的作用
...@@ -134,7 +133,8 @@ def foo(): ...@@ -134,7 +133,8 @@ def foo():
print('goodbye, world!') print('goodbye, world!')
foo() # 输出goodbye, world! # 下面的代码会输出什么呢?
foo()
``` ```
当然上面的这种情况我们很容易就能避免,但是如果项目是由多人协作进行团队开发的时候,团队中可能有多个程序员都定义了名为`foo`的函数,那么怎么解决这种命名冲突呢?答案其实很简单,Python中每个文件就代表了一个模块(module),我们在不同的模块中可以有同名的函数,在使用函数的时候我们通过`import`关键字导入指定的模块就可以区分到底要使用的是哪个模块中的`foo`函数,代码如下所示。 当然上面的这种情况我们很容易就能避免,但是如果项目是由多人协作进行团队开发的时候,团队中可能有多个程序员都定义了名为`foo`的函数,那么怎么解决这种命名冲突呢?答案其实很简单,Python中每个文件就代表了一个模块(module),我们在不同的模块中可以有同名的函数,在使用函数的时候我们通过`import`关键字导入指定的模块就可以区分到底要使用的是哪个模块中的`foo`函数,代码如下所示。
...@@ -158,11 +158,13 @@ test.py ...@@ -158,11 +158,13 @@ test.py
```Python ```Python
from module1 import foo from module1 import foo
foo() # 输出hello, world! # 输出hello, world!
foo()
from module2 import foo from module2 import foo
foo() # 输出goodbye, world! # 输出goodbye, world!
foo()
``` ```
也可以按照如下所示的方式来区分到底要使用哪一个`foo`函数。 也可以按照如下所示的方式来区分到底要使用哪一个`foo`函数。
...@@ -185,7 +187,8 @@ test.py ...@@ -185,7 +187,8 @@ test.py
from module1 import foo from module1 import foo
from module2 import foo from module2 import foo
foo() # 输出goodbye, world! # 输出goodbye, world!
foo()
``` ```
test.py test.py
...@@ -194,7 +197,8 @@ test.py ...@@ -194,7 +197,8 @@ test.py
from module2 import foo from module2 import foo
from module1 import foo from module1 import foo
foo() # 输出hello, world! # 输出hello, world!
foo()
``` ```
需要说明的是,如果我们导入的模块除了定义函数之外还中有可以执行代码,那么Python解释器在导入这个模块时就会执行这些代码,事实上我们可能并不希望如此,因此如果我们在模块中编写了执行代码,最好是将这些执行代码放入如下所示的条件中,这样的话除非直接运行该模块,if条件下的这些代码是不会执行的,因为只有直接执行的模块的名字才是“\_\_main\_\_”。 需要说明的是,如果我们导入的模块除了定义函数之外还中有可以执行代码,那么Python解释器在导入这个模块时就会执行这些代码,事实上我们可能并不希望如此,因此如果我们在模块中编写了执行代码,最好是将这些执行代码放入如下所示的条件中,这样的话除非直接运行该模块,if条件下的这些代码是不会执行的,因为只有直接执行的模块的名字才是“\_\_main\_\_”。
......
...@@ -42,7 +42,6 @@ def main(): ...@@ -42,7 +42,6 @@ def main():
if __name__ == '__main__': if __name__ == '__main__':
main() main()
``` ```
下面是运行程序得到的一次运行结果。 下面是运行程序得到的一次运行结果。
...@@ -86,7 +85,6 @@ def main(): ...@@ -86,7 +85,6 @@ def main():
if __name__ == '__main__': if __name__ == '__main__':
main() main()
``` ```
在上面的代码中,我们通过`Process`类创建了进程对象,通过`target`参数我们传入一个函数来表示进程启动后要执行的代码,后面的`args`是一个元组,它代表了传递给函数的参数。`Process`对象的`start`方法用来启动进程,而`join`方法表示等待进程执行结束。运行上面的代码可以明显发现两个下载任务“同时”启动了,而且程序的执行时间将大大缩短,不再是两个任务的时间总和。下面是程序的一次执行结果。 在上面的代码中,我们通过`Process`类创建了进程对象,通过`target`参数我们传入一个函数来表示进程启动后要执行的代码,后面的`args`是一个元组,它代表了传递给函数的参数。`Process`对象的`start`方法用来启动进程,而`join`方法表示等待进程执行结束。运行上面的代码可以明显发现两个下载任务“同时”启动了,而且程序的执行时间将大大缩短,不再是两个任务的时间总和。下面是程序的一次执行结果。
...@@ -375,7 +373,6 @@ def main(): ...@@ -375,7 +373,6 @@ def main():
if __name__ == '__main__': if __name__ == '__main__':
main() main()
``` ```
如果使用多线程将耗时间的任务放到一个独立的线程中执行,这样就不会因为执行耗时间的任务而阻塞了主线程,修改后的代码如下所示。 如果使用多线程将耗时间的任务放到一个独立的线程中执行,这样就不会因为执行耗时间的任务而阻塞了主线程,修改后的代码如下所示。
...@@ -424,7 +421,6 @@ def main(): ...@@ -424,7 +421,6 @@ def main():
if __name__ == '__main__': if __name__ == '__main__':
main() main()
``` ```
#### 例子2:使用多进程对复杂任务进行“分而治之”。 #### 例子2:使用多进程对复杂任务进行“分而治之”。
...@@ -448,7 +444,6 @@ def main(): ...@@ -448,7 +444,6 @@ def main():
if __name__ == '__main__': if __name__ == '__main__':
main() main()
``` ```
在上面的代码中,我故意先去创建了一个列表容器然后填入了100000000个数,这一步其实是比较耗时间的,所以为了公平起见,当我们将这个任务分解到8个进程中去执行的时候,我们暂时也不考虑列表切片操作花费的时间,只是把做运算和合并运算结果的时间统计出来,代码如下所示。 在上面的代码中,我故意先去创建了一个列表容器然后填入了100000000个数,这一步其实是比较耗时间的,所以为了公平起见,当我们将这个任务分解到8个进程中去执行的时候,我们暂时也不考虑列表切片操作花费的时间,只是把做运算和合并运算结果的时间统计出来,代码如下所示。
...@@ -493,7 +488,6 @@ def main(): ...@@ -493,7 +488,6 @@ def main():
if __name__ == '__main__': if __name__ == '__main__':
main() main()
``` ```
比较两段代码的执行结果(在我目前使用的MacBook上,上面的代码需要大概6秒左右的时间,而下面的代码只需要不到1秒的时间,再强调一次我们只是比较了运算的时间,不考虑列表创建及切片操作花费的时间),使用多进程后由于获得了更多的CPU执行时间以及更好的利用了CPU的多核特性,明显的减少了程序的执行时间,而且计算量越大效果越明显。当然,如果愿意还可以将多个进程部署在不同的计算机上,做成分布式进程,具体的做法就是通过multiprocessing.managers模块中提供的管理器将`Queue`对象通过网络共享出来(注册到网络上让其他计算机可以访问),这部分内容也留到爬虫的专题再进行讲解。 比较两段代码的执行结果(在我目前使用的MacBook上,上面的代码需要大概6秒左右的时间,而下面的代码只需要不到1秒的时间,再强调一次我们只是比较了运算的时间,不考虑列表创建及切片操作花费的时间),使用多进程后由于获得了更多的CPU执行时间以及更好的利用了CPU的多核特性,明显的减少了程序的执行时间,而且计算量越大效果越明显。当然,如果愿意还可以将多个进程部署在不同的计算机上,做成分布式进程,具体的做法就是通过multiprocessing.managers模块中提供的管理器将`Queue`对象通过网络共享出来(注册到网络上让其他计算机可以访问),这部分内容也留到爬虫的专题再进行讲解。
\ No newline at end of file
...@@ -126,7 +126,6 @@ def main(): ...@@ -126,7 +126,6 @@ def main():
if __name__ == '__main__': if __name__ == '__main__':
main() main()
``` ```
### 基于传输层协议的套接字编程 ### 基于传输层协议的套接字编程
...@@ -174,7 +173,6 @@ def main(): ...@@ -174,7 +173,6 @@ def main():
if __name__ == '__main__': if __name__ == '__main__':
main() main()
``` ```
运行服务器程序后我们可以通过Windows系统的telnet来访问该服务器,结果如下图所示。 运行服务器程序后我们可以通过Windows系统的telnet来访问该服务器,结果如下图所示。
...@@ -203,7 +201,6 @@ def main(): ...@@ -203,7 +201,6 @@ def main():
if __name__ == '__main__': if __name__ == '__main__':
main() main()
``` ```
需要注意的是,上面的服务器并没有使用多线程或者异步I/O的处理方式,这也就意味着当服务器与一个客户端处于通信状态时,其他的客户端只能排队等待。很显然,这样的服务器并不能满足我们的需求,我们需要的服务器是能够同时接纳和处理多个用户请求的。下面我们来设计一个使用多线程技术处理多个用户请求的服务器,该服务器会向连接到服务器的客户端发送一张图片。 需要注意的是,上面的服务器并没有使用多线程或者异步I/O的处理方式,这也就意味着当服务器与一个客户端处于通信状态时,其他的客户端只能排队等待。很显然,这样的服务器并不能满足我们的需求,我们需要的服务器是能够同时接纳和处理多个用户请求的。下面我们来设计一个使用多线程技术处理多个用户请求的服务器,该服务器会向连接到服务器的客户端发送一张图片。
...@@ -256,7 +253,6 @@ def main(): ...@@ -256,7 +253,6 @@ def main():
if __name__ == '__main__': if __name__ == '__main__':
main() main()
``` ```
客户端代码: 客户端代码:
...@@ -291,7 +287,6 @@ def main(): ...@@ -291,7 +287,6 @@ def main():
if __name__ == '__main__': if __name__ == '__main__':
main() main()
``` ```
在这个案例中,我们使用了JSON作为数据传输的格式(通过JSON格式对传输的数据进行了序列化和反序列化的操作),但是JSON并不能携带二进制数据,因此对图片的二进制数据进行了Base64编码的处理。Base64是一种用64个字符表示所有二进制数据的编码方式,通过将二进制数据每6位一组的方式重新组织,刚好可以使用0~9的数字、大小写字母以及“+”和“/”总共64个字符表示从`000000``111111`的64种状态。[维基百科](https://zh.wikipedia.org/wiki/Base64)上有关于Base64编码的详细讲解,不熟悉Base64的读者可以自行阅读。 在这个案例中,我们使用了JSON作为数据传输的格式(通过JSON格式对传输的数据进行了序列化和反序列化的操作),但是JSON并不能携带二进制数据,因此对图片的二进制数据进行了Base64编码的处理。Base64是一种用64个字符表示所有二进制数据的编码方式,通过将二进制数据每6位一组的方式重新组织,刚好可以使用0~9的数字、大小写字母以及“+”和“/”总共64个字符表示从`000000``111111`的64种状态。[维基百科](https://zh.wikipedia.org/wiki/Base64)上有关于Base64编码的详细讲解,不熟悉Base64的读者可以自行阅读。
......
...@@ -31,7 +31,6 @@ def main(): ...@@ -31,7 +31,6 @@ def main():
if __name__ == '__main__': if __name__ == '__main__':
main() main()
``` ```
如果要发送带有附件的邮件,那么可以按照下面的方式进行操作。 如果要发送带有附件的邮件,那么可以按照下面的方式进行操作。
...@@ -88,7 +87,6 @@ def main(): ...@@ -88,7 +87,6 @@ def main():
if __name__ == '__main__': if __name__ == '__main__':
main() main()
``` ```
### 发送短信 ### 发送短信
...@@ -119,7 +117,5 @@ def main(): ...@@ -119,7 +117,5 @@ def main():
if __name__ == '__main__': if __name__ == '__main__':
main() main()
``` ```
This diff is collapsed.
...@@ -1249,7 +1249,3 @@ build environment: ...@@ -1249,7 +1249,3 @@ build environment:
3. HISTSIZE 3. HISTSIZE
4. RANDOM 4. RANDOM
5. PATH 5. PATH
...@@ -115,7 +115,6 @@ HTTP响应(响应行+响应头+空行+消息体): ...@@ -115,7 +115,6 @@ HTTP响应(响应行+响应头+空行+消息体):
3. HTTPie:命令行HTTP客户端。 3. HTTPie:命令行HTTP客户端。
```Shell ```Shell
$ http --header http://www.scu.edu.cn $ http --header http://www.scu.edu.cn
HTTP/1.1 200 OK HTTP/1.1 200 OK
Accept-Ranges: bytes Accept-Ranges: bytes
...@@ -138,8 +137,6 @@ HTTP响应(响应行+响应头+空行+消息体): ...@@ -138,8 +137,6 @@ HTTP响应(响应行+响应头+空行+消息体):
4. BuiltWith:识别网站所用技术的工具。 4. BuiltWith:识别网站所用技术的工具。
```Python ```Python
>>>
>>> import builtwith >>> import builtwith
>>> builtwith.parse('http://www.bootcss.com/') >>> builtwith.parse('http://www.bootcss.com/')
{'web-servers': ['Nginx'], 'font-scripts': ['Font Awesome'], 'javascript-frameworks': ['Lo-dash', 'Underscore.js', 'Vue.js', 'Zepto', 'jQuery'], 'web-frameworks': ['Twitter Bootstrap']} {'web-servers': ['Nginx'], 'font-scripts': ['Font Awesome'], 'javascript-frameworks': ['Lo-dash', 'Underscore.js', 'Vue.js', 'Zepto', 'jQuery'], 'web-frameworks': ['Twitter Bootstrap']}
...@@ -153,8 +150,6 @@ HTTP响应(响应行+响应头+空行+消息体): ...@@ -153,8 +150,6 @@ HTTP响应(响应行+响应头+空行+消息体):
5. python-whois:查询网站所有者的工具。 5. python-whois:查询网站所有者的工具。
```Python ```Python
>>>
>>> import whois >>> import whois
>>> whois.whois('baidu.com') >>> whois.whois('baidu.com')
{'domain_name': ['BAIDU.COM', 'baidu.com'], 'registrar': 'MarkMonitor, Inc.', 'whois_server': 'whois.markmonitor.com', 'referral_url': None, 'updated_date': [datetime.datetime(2017, 7, 28, 2, 36, 28), datetime.datetime(2017, 7, 27, 19, 36, 28)], 'creation_date': [datetime.datetime(1999, 10, 11, 11, 5, 17), datetime.datetime(1999, 10, 11, 4, 5, 17)], 'expiration_date': [datetime.datetime(2026, 10, 11, 11, 5, 17), datetime.datetime(2026, 10, 11, 0, 0)], 'name_servers': ['DNS.BAIDU.COM', 'NS2.BAIDU.COM', 'NS3.BAIDU.COM', 'NS4.BAIDU.COM', 'NS7.BAIDU.COM', 'dns.baidu.com', 'ns4.baidu.com', 'ns3.baidu.com', 'ns7.baidu.com', 'ns2.baidu.com'], 'status': ['clientDeleteProhibited https://icann.org/epp#clientDeleteProhibited', 'clientTransferProhibited https://icann.org/epp#clientTransferProhibited', 'clientUpdateProhibited https://icann.org/epp#clientUpdateProhibited', 'serverDeleteProhibited https://icann.org/epp#serverDeleteProhibited', 'serverTransferProhibited https://icann.org/epp#serverTransferProhibited', 'serverUpdateProhibited https://icann.org/epp#serverUpdateProhibited', 'clientUpdateProhibited (https://www.icann.org/epp#clientUpdateProhibited)', 'clientTransferProhibited (https://www.icann.org/epp#clientTransferProhibited)', 'clientDeleteProhibited (https://www.icann.org/epp#clientDeleteProhibited)', 'serverUpdateProhibited (https://www.icann.org/epp#serverUpdateProhibited)', 'serverTransferProhibited (https://www.icann.org/epp#serverTransferProhibited)', 'serverDeleteProhibited (https://www.icann.org/epp#serverDeleteProhibited)'], 'emails': ['abusecomplaints@markmonitor.com', 'whoisrelay@markmonitor.com'], 'dnssec': 'unsigned', 'name': None, 'org': 'Beijing Baidu Netcom Science Technology Co., Ltd.', 'address': None, 'city': None, 'state': 'Beijing', 'zipcode': None, 'country': 'CN'} {'domain_name': ['BAIDU.COM', 'baidu.com'], 'registrar': 'MarkMonitor, Inc.', 'whois_server': 'whois.markmonitor.com', 'referral_url': None, 'updated_date': [datetime.datetime(2017, 7, 28, 2, 36, 28), datetime.datetime(2017, 7, 27, 19, 36, 28)], 'creation_date': [datetime.datetime(1999, 10, 11, 11, 5, 17), datetime.datetime(1999, 10, 11, 4, 5, 17)], 'expiration_date': [datetime.datetime(2026, 10, 11, 11, 5, 17), datetime.datetime(2026, 10, 11, 0, 0)], 'name_servers': ['DNS.BAIDU.COM', 'NS2.BAIDU.COM', 'NS3.BAIDU.COM', 'NS4.BAIDU.COM', 'NS7.BAIDU.COM', 'dns.baidu.com', 'ns4.baidu.com', 'ns3.baidu.com', 'ns7.baidu.com', 'ns2.baidu.com'], 'status': ['clientDeleteProhibited https://icann.org/epp#clientDeleteProhibited', 'clientTransferProhibited https://icann.org/epp#clientTransferProhibited', 'clientUpdateProhibited https://icann.org/epp#clientUpdateProhibited', 'serverDeleteProhibited https://icann.org/epp#serverDeleteProhibited', 'serverTransferProhibited https://icann.org/epp#serverTransferProhibited', 'serverUpdateProhibited https://icann.org/epp#serverUpdateProhibited', 'clientUpdateProhibited (https://www.icann.org/epp#clientUpdateProhibited)', 'clientTransferProhibited (https://www.icann.org/epp#clientTransferProhibited)', 'clientDeleteProhibited (https://www.icann.org/epp#clientDeleteProhibited)', 'serverUpdateProhibited (https://www.icann.org/epp#serverUpdateProhibited)', 'serverTransferProhibited (https://www.icann.org/epp#serverTransferProhibited)', 'serverDeleteProhibited (https://www.icann.org/epp#serverDeleteProhibited)'], 'emails': ['abusecomplaints@markmonitor.com', 'whoisrelay@markmonitor.com'], 'dnssec': 'unsigned', 'name': None, 'org': 'Beijing Baidu Netcom Science Technology Co., Ltd.', 'address': None, 'city': None, 'state': 'Beijing', 'zipcode': None, 'country': 'CN'}
...@@ -195,7 +190,6 @@ HTTP响应(响应行+响应头+空行+消息体): ...@@ -195,7 +190,6 @@ HTTP响应(响应行+响应头+空行+消息体):
下面的例子给出了一个从“搜狐体育”上获取NBA新闻标题和链接的爬虫。 下面的例子给出了一个从“搜狐体育”上获取NBA新闻标题和链接的爬虫。
```Python ```Python
from urllib.error import URLError from urllib.error import URLError
from urllib.request import urlopen from urllib.request import urlopen
...@@ -304,7 +298,6 @@ if __name__ == '__main__': ...@@ -304,7 +298,6 @@ if __name__ == '__main__':
- 使用未经验证的上下文 - 使用未经验证的上下文
```Python ```Python
import ssl import ssl
request = urllib.request.Request(url='...', headers={...}) request = urllib.request.Request(url='...', headers={...})
...@@ -315,10 +308,8 @@ if __name__ == '__main__': ...@@ -315,10 +308,8 @@ if __name__ == '__main__':
- 设置全局的取消证书验证 - 设置全局的取消证书验证
```Python ```Python
import ssl import ssl
ssl._create_default_https_context = ssl._create_unverified_context ssl._create_default_https_context = ssl._create_unverified_context
``` ```
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
### HTML页面分析 ### HTML页面分析
```HTML ```HTML
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
...@@ -136,7 +135,6 @@ pyquery相当于jQuery的Python实现,可以用于解析HTML网页。 ...@@ -136,7 +135,6 @@ pyquery相当于jQuery的Python实现,可以用于解析HTML网页。
### 实例 - 获取知乎发现上的问题链接 ### 实例 - 获取知乎发现上的问题链接
```Python ```Python
from urllib.parse import urljoin from urllib.parse import urljoin
import re import re
...@@ -168,6 +166,5 @@ def main(): ...@@ -168,6 +166,5 @@ def main():
if __name__ == '__main__': if __name__ == '__main__':
main() main()
``` ```
...@@ -20,21 +20,19 @@ Redis是REmote DIctionary Server的缩写,它是一个用ANSI C编写的高性 ...@@ -20,21 +20,19 @@ Redis是REmote DIctionary Server的缩写,它是一个用ANSI C编写的高性
可以使用Linux系统的包管理工具(如yum)来安装Redis,也可以通过在Redis的[官方网站](https://redis.io/)下载Redis的[源代码](http://download.redis.io/releases/redis-3.2.11.tar.gz)解压缩解归档之后进行构件安装。 可以使用Linux系统的包管理工具(如yum)来安装Redis,也可以通过在Redis的[官方网站](https://redis.io/)下载Redis的[源代码](http://download.redis.io/releases/redis-3.2.11.tar.gz)解压缩解归档之后进行构件安装。
```Shell ```Shell
wget http://download.redis.io/releases/redis-3.2.11.tar.gz
# wget http://download.redis.io/releases/redis-3.2.11.tar.gz gunzip redis-3.2.11.tar.gz
# gunzip redis-3.2.11.tar.gz tar -xvf redis-3.2.11.tar
# tar -xvf redis-3.2.11.tar cd redis-3.2.11
# cd redis-3.2.11 make && make install
# make && make install
``` ```
接下来我们将redis-3.2.11目录下的redis.conf配置文件复制到用户主目录下并修改配置文件(如果你对配置文件不是很有把握就不要直接修改而是先复制一份再修改这个副本)。 接下来我们将redis-3.2.11目录下的redis.conf配置文件复制到用户主目录下并修改配置文件(如果你对配置文件不是很有把握就不要直接修改而是先复制一份再修改这个副本)。
```Shell ```Shell
cd ..
# cd .. cp redis-3.2.11/redis.conf redis.conf
# cp redis-3.2.11/redis.conf redis.conf vim redis.conf
# vim redis.conf
``` ```
配置将Redis服务绑定到指定的IP地址和端口。 配置将Redis服务绑定到指定的IP地址和端口。
...@@ -76,8 +74,7 @@ Redis是REmote DIctionary Server的缩写,它是一个用ANSI C编写的高性 ...@@ -76,8 +74,7 @@ Redis是REmote DIctionary Server的缩写,它是一个用ANSI C编写的高性
接下来启动Redis服务器,可以将服务器放在后台去运行。 接下来启动Redis服务器,可以将服务器放在后台去运行。
```Shell ```Shell
redis-server redis.conf &
# redis-server redis.conf &
_.-``__ ''-._ _.-``__ ''-._
_.-`` `. `_. ''-._ Redis 3.2.11 (00000000/0) 64 bit _.-`` `. `_. ''-._ Redis 3.2.11 (00000000/0) 64 bit
...@@ -100,8 +97,7 @@ Redis是REmote DIctionary Server的缩写,它是一个用ANSI C编写的高性 ...@@ -100,8 +97,7 @@ Redis是REmote DIctionary Server的缩写,它是一个用ANSI C编写的高性
接下来,我们尝试用Redis客户端去连接服务器。 接下来,我们尝试用Redis客户端去连接服务器。
```Shell ```Shell
redis-cli -h 172.18.61.250 -p 6379
# redis-cli -h 172.18.61.250 -p 6379
172.18.61.250:6379> auth 1qaz2wsx 172.18.61.250:6379> auth 1qaz2wsx
OK OK
172.18.61.250:6379> ping 172.18.61.250:6379> ping
...@@ -112,7 +108,6 @@ PONG ...@@ -112,7 +108,6 @@ PONG
Redis有着非常丰富的数据类型,也有很多的命令来操作这些数据,具体的内容可以查看[Redis命令参考](http://redisdoc.com/),在这个网站上,除了Redis的命令参考,还有Redis的详细文档,其中包括了通知、事务、主从复制、持久化、哨兵、集群等内容。 Redis有着非常丰富的数据类型,也有很多的命令来操作这些数据,具体的内容可以查看[Redis命令参考](http://redisdoc.com/),在这个网站上,除了Redis的命令参考,还有Redis的详细文档,其中包括了通知、事务、主从复制、持久化、哨兵、集群等内容。
```Shell ```Shell
172.18.61.250:6379> set username admin 172.18.61.250:6379> set username admin
OK OK
172.18.61.250:6379> get username 172.18.61.250:6379> get username
...@@ -166,13 +161,11 @@ OK ...@@ -166,13 +161,11 @@ OK
可以使用pip安装redis模块。redis模块的核心是名为Redis的类,该类的对象代表一个Redis客户端,通过该客户端可以向Redis服务器发送命令并获取执行的结果。上面我们在Redis客户端中使用的命令基本上就是Redis对象可以接收的消息,所以如果了解了Redis的命令就可以在Python中玩转Redis。 可以使用pip安装redis模块。redis模块的核心是名为Redis的类,该类的对象代表一个Redis客户端,通过该客户端可以向Redis服务器发送命令并获取执行的结果。上面我们在Redis客户端中使用的命令基本上就是Redis对象可以接收的消息,所以如果了解了Redis的命令就可以在Python中玩转Redis。
```Shell ```Shell
pip3 install redis
$ pip3 install redis python3
$ python3
``` ```
```Python ```Python
>>> import redis >>> import redis
>>> client = redis.Redis(host='1.2.3.4', port=6379, password='1qaz2wsx') >>> client = redis.Redis(host='1.2.3.4', port=6379, password='1qaz2wsx')
>>> client.set('username', 'admin') >>> client.set('username', 'admin')
...@@ -202,14 +195,14 @@ MongoDB将数据存储为一个文档,一个文档由一系列的“键值对 ...@@ -202,14 +195,14 @@ MongoDB将数据存储为一个文档,一个文档由一系列的“键值对
可以从MongoDB的[官方下载链接](https://www.mongodb.com/download-center#community)下载MongoDB,官方为Windows系统提供了一个Installer程序,而Linux和MacOS则提供了压缩文件。下面简单说一下Linux系统如何安装和配置MongoDB。 可以从MongoDB的[官方下载链接](https://www.mongodb.com/download-center#community)下载MongoDB,官方为Windows系统提供了一个Installer程序,而Linux和MacOS则提供了压缩文件。下面简单说一下Linux系统如何安装和配置MongoDB。
```Shell ```Shell
wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-amazon-3.6.5.tgz
gunzip mongodb-linux-x86_64-amazon-3.6.5.tgz
mkdir mongodb-3.6.5
tar -xvf mongodb-linux-x86_64-amazon-3.6.5.tar --strip-components 1 -C mongodb-3.6.5/
export PATH=$PATH:~/mongodb-3.6.5/bin
mkdir -p /data/db
mongod --bind_ip 172.18.61.250
# wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-amazon-3.6.5.tgz
# gunzip mongodb-linux-x86_64-amazon-3.6.5.tgz
# mkdir mongodb-3.6.5
# tar -xvf mongodb-linux-x86_64-amazon-3.6.5.tar --strip-components 1 -C mongodb-3.6.5/
# export PATH=$PATH:~/mongodb-3.6.5/bin
# mkdir -p /data/db
# mongod --bind_ip 172.18.61.250
2018-06-03T18:03:28.232+0800 I CONTROL [initandlisten] MongoDB starting : pid=1163 port=27017 dbpath=/data/db 64-bit host=iZwz97tbgo9lkabnat2lo8Z 2018-06-03T18:03:28.232+0800 I CONTROL [initandlisten] MongoDB starting : pid=1163 port=27017 dbpath=/data/db 64-bit host=iZwz97tbgo9lkabnat2lo8Z
2018-06-03T18:03:28.232+0800 I CONTROL [initandlisten] db version v3.6.5 2018-06-03T18:03:28.232+0800 I CONTROL [initandlisten] db version v3.6.5
2018-06-03T18:03:28.232+0800 I CONTROL [initandlisten] git version: a20ecd3e3a174162052ff99913bc2ca9a839d618 2018-06-03T18:03:28.232+0800 I CONTROL [initandlisten] git version: a20ecd3e3a174162052ff99913bc2ca9a839d618
...@@ -239,7 +232,8 @@ MongoDB将数据存储为一个文档,一个文档由一系列的“键值对 ...@@ -239,7 +232,8 @@ MongoDB将数据存储为一个文档,一个文档由一系列的“键值对
启动服务器后可以使用交互式环境跟服务器通信,如下所示。 启动服务器后可以使用交互式环境跟服务器通信,如下所示。
```shell ```shell
# mongo --host 172.18.61.250 mongo --host 172.18.61.250
MongoDB shell version v3.6.5 MongoDB shell version v3.6.5
connecting to: mongodb://172.18.61.250:27017/ connecting to: mongodb://172.18.61.250:27017/
... ...
...@@ -249,7 +243,6 @@ connecting to: mongodb://172.18.61.250:27017/ ...@@ -249,7 +243,6 @@ connecting to: mongodb://172.18.61.250:27017/
1. 查看、创建和删除数据库。 1. 查看、创建和删除数据库。
```JavaScript ```JavaScript
> // 显示所有数据库 > // 显示所有数据库
> show dbs > show dbs
admin 0.000GB admin 0.000GB
...@@ -267,7 +260,6 @@ connecting to: mongodb://172.18.61.250:27017/ ...@@ -267,7 +260,6 @@ connecting to: mongodb://172.18.61.250:27017/
2. 创建、删除和查看集合。 2. 创建、删除和查看集合。
```JavaScript ```JavaScript
> // 创建并切换到school数据库 > // 创建并切换到school数据库
> use school > use school
switched to db school switched to db school
...@@ -292,7 +284,6 @@ connecting to: mongodb://172.18.61.250:27017/ ...@@ -292,7 +284,6 @@ connecting to: mongodb://172.18.61.250:27017/
3. 文档的CRUD操作。 3. 文档的CRUD操作。
```JavaScript ```JavaScript
> // 向students集合插入文档 > // 向students集合插入文档
> db.students.insert({stuid: 1001, name: '骆昊', age: 38}) > db.students.insert({stuid: 1001, name: '骆昊', age: 38})
WriteResult({ "nInserted" : 1 }) WriteResult({ "nInserted" : 1 })
...@@ -394,13 +385,11 @@ connecting to: mongodb://172.18.61.250:27017/ ...@@ -394,13 +385,11 @@ connecting to: mongodb://172.18.61.250:27017/
可以通过pip安装pymongo来实现对MongoDB的操作。 可以通过pip安装pymongo来实现对MongoDB的操作。
```Shell ```Shell
pip3 install pymongo
$ pip3 install pymongo python3
$ python3
``` ```
```Python ```Python
>>> from pymongo import MongoClient >>> from pymongo import MongoClient
>>> client = MongoClient('mongodb://120.77.222.217:27017') >>> client = MongoClient('mongodb://120.77.222.217:27017')
>>> db = client.school >>> db = client.school
...@@ -451,7 +440,6 @@ $ python3 ...@@ -451,7 +440,6 @@ $ python3
### 实例 - 缓存知乎发现上的链接和页面代码 ### 实例 - 缓存知乎发现上的链接和页面代码
```Python ```Python
from hashlib import sha1 from hashlib import sha1
from urllib.parse import urljoin from urllib.parse import urljoin
...@@ -501,7 +489,6 @@ def main(): ...@@ -501,7 +489,6 @@ def main():
if __name__ == '__main__': if __name__ == '__main__':
main() main()
``` ```
......
...@@ -44,7 +44,6 @@ Python3.2带来了`concurrent.futures` 模块,这个模块包含了线程池 ...@@ -44,7 +44,6 @@ Python3.2带来了`concurrent.futures` 模块,这个模块包含了线程池
1. 生成器 - 数据的生产者。 1. 生成器 - 数据的生产者。
```Python ```Python
from time import sleep from time import sleep
...@@ -70,7 +69,6 @@ Python3.2带来了`concurrent.futures` 模块,这个模块包含了线程池 ...@@ -70,7 +69,6 @@ Python3.2带来了`concurrent.futures` 模块,这个模块包含了线程池
生成器还可以叠加来组成生成器管道,代码如下所示。 生成器还可以叠加来组成生成器管道,代码如下所示。
```Python ```Python
# Fibonacci数生成器 # Fibonacci数生成器
def fib(): def fib():
a, b = 0, 1 a, b = 0, 1
...@@ -94,13 +92,11 @@ Python3.2带来了`concurrent.futures` 模块,这个模块包含了线程池 ...@@ -94,13 +92,11 @@ Python3.2带来了`concurrent.futures` 模块,这个模块包含了线程池
if __name__ == '__main__': if __name__ == '__main__':
main() main()
``` ```
2. 协程 - 数据的消费者。 2. 协程 - 数据的消费者。
```Python ```Python
from time import sleep from time import sleep
...@@ -130,13 +126,11 @@ Python3.2带来了`concurrent.futures` 模块,这个模块包含了线程池 ...@@ -130,13 +126,11 @@ Python3.2带来了`concurrent.futures` 模块,这个模块包含了线程池
if __name__ == '__main__': if __name__ == '__main__':
main() main()
``` ```
> 说明:上面代码中countdown_gen函数中的第1行consumer.send(None)是为了激活生成器,通俗的说就是让生成器执行到有yield关键字的地方挂起,当然也可以通过next(consumer)来达到同样的效果。如果不愿意每次都用这样的代码来“预激”生成器,可以写一个包装器来完成该操作,代码如下所示。 > 说明:上面代码中countdown_gen函数中的第1行consumer.send(None)是为了激活生成器,通俗的说就是让生成器执行到有yield关键字的地方挂起,当然也可以通过next(consumer)来达到同样的效果。如果不愿意每次都用这样的代码来“预激”生成器,可以写一个包装器来完成该操作,代码如下所示。
```Python ```Python
from functools import wraps from functools import wraps
...@@ -156,7 +150,6 @@ Python3.2带来了`concurrent.futures` 模块,这个模块包含了线程池 ...@@ -156,7 +150,6 @@ Python3.2带来了`concurrent.futures` 模块,这个模块包含了线程池
3. 异步I/O - 非阻塞式I/O操作。 3. 异步I/O - 非阻塞式I/O操作。
```Python ```Python
import asyncio import asyncio
...@@ -179,13 +172,11 @@ Python3.2带来了`concurrent.futures` 模块,这个模块包含了线程池 ...@@ -179,13 +172,11 @@ Python3.2带来了`concurrent.futures` 模块,这个模块包含了线程池
if __name__ == '__main__': if __name__ == '__main__':
main() main()
``` ```
4. `async`和`await`。 4. `async`和`await`。
```Python ```Python
import asyncio import asyncio
import aiohttp import aiohttp
...@@ -215,7 +206,6 @@ Python3.2带来了`concurrent.futures` 模块,这个模块包含了线程池 ...@@ -215,7 +206,6 @@ Python3.2带来了`concurrent.futures` 模块,这个模块包含了线程池
if __name__ == '__main__': if __name__ == '__main__':
main() main()
``` ```
上面的代码使用了[AIOHTTP](https://github.com/aio-libs/aiohttp)这个非常著名的第三方库,它实现了HTTP客户端和HTTP服务器的功能,对异步操作提供了非常好的支持,有兴趣可以阅读它的[官方文档](https://aiohttp.readthedocs.io/en/stable/)。 上面的代码使用了[AIOHTTP](https://github.com/aio-libs/aiohttp)这个非常著名的第三方库,它实现了HTTP客户端和HTTP服务器的功能,对异步操作提供了非常好的支持,有兴趣可以阅读它的[官方文档](https://aiohttp.readthedocs.io/en/stable/)。
...@@ -225,7 +215,6 @@ Python3.2带来了`concurrent.futures` 模块,这个模块包含了线程池 ...@@ -225,7 +215,6 @@ Python3.2带来了`concurrent.futures` 模块,这个模块包含了线程池
下面我们把之间讲的所有知识结合起来,用面向对象的方式实现一个爬取“手机搜狐网”的多线程爬虫。 下面我们把之间讲的所有知识结合起来,用面向对象的方式实现一个爬取“手机搜狐网”的多线程爬虫。
```Python ```Python
import pickle import pickle
import zlib import zlib
from enum import Enum, unique from enum import Enum, unique
...@@ -382,6 +371,5 @@ def main(): ...@@ -382,6 +371,5 @@ def main():
if __name__ == '__main__': if __name__ == '__main__':
main() main()
``` ```
...@@ -25,14 +25,12 @@ WebKit的代码始于1998年的KHTML项目,当时它是Konqueror浏览器的 ...@@ -25,14 +25,12 @@ WebKit的代码始于1998年的KHTML项目,当时它是Konqueror浏览器的
如果没有打算用上面所说的方式来渲染页面并获得动态内容,其实还有一种替代方案就是使用自动化测试工具Selenium,它提供了浏览器自动化的API接口,这样就可以通过操控浏览器来获取动态内容。首先可以使用pip来安装Selenium。 如果没有打算用上面所说的方式来渲染页面并获得动态内容,其实还有一种替代方案就是使用自动化测试工具Selenium,它提供了浏览器自动化的API接口,这样就可以通过操控浏览器来获取动态内容。首先可以使用pip来安装Selenium。
```Shell ```Shell
pip3 install selenium
$ pip3 install selenium
``` ```
下面以“阿里V任务”的“直播服务”为例,来演示如何使用Selenium获取到动态内容并抓取主播图片。 下面以“阿里V任务”的“直播服务”为例,来演示如何使用Selenium获取到动态内容并抓取主播图片。
```Python ```Python
import requests import requests
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
...@@ -47,13 +45,11 @@ def main(): ...@@ -47,13 +45,11 @@ def main():
if __name__ == '__main__': if __name__ == '__main__':
main() main()
``` ```
运行上面的程序会发现没有任何的输出,因为页面的HTML代码上根本找不到`<img>`标签。接下来我们使用Selenium来获取到页面上的动态内容,再提取主播图片。 运行上面的程序会发现没有任何的输出,因为页面的HTML代码上根本找不到`<img>`标签。接下来我们使用Selenium来获取到页面上的动态内容,再提取主播图片。
```Python ```Python
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
from selenium import webdriver from selenium import webdriver
from selenium.webdriver.common.keys import Keys from selenium.webdriver.common.keys import Keys
...@@ -69,21 +65,18 @@ def main(): ...@@ -69,21 +65,18 @@ def main():
if __name__ == '__main__': if __name__ == '__main__':
main() main()
``` ```
在上面的程序中,我们通过Selenium实现对Chrome浏览器的操控,如果要操控其他的浏览器,可以创对应的浏览器对象,例如Firefox、IE等。运行上面的程序,如果看到如下所示的错误提示,那是说明我们还没有将Chrome浏览器的驱动添加到PATH环境变量中,也没有在程序中指定Chrome浏览器驱动所在的位置。 在上面的程序中,我们通过Selenium实现对Chrome浏览器的操控,如果要操控其他的浏览器,可以创对应的浏览器对象,例如Firefox、IE等。运行上面的程序,如果看到如下所示的错误提示,那是说明我们还没有将Chrome浏览器的驱动添加到PATH环境变量中,也没有在程序中指定Chrome浏览器驱动所在的位置。
```Shell ```Shell
selenium.common.exceptions.WebDriverException: Message: 'chromedriver' executable needs to be in PATH. Please see https://sites.google.com/a/chromium.org/chromedriver/home selenium.common.exceptions.WebDriverException: Message: 'chromedriver' executable needs to be in PATH. Please see https://sites.google.com/a/chromium.org/chromedriver/home
``` ```
为了解决上面的问题,可以到Selenium的[官方网站]()找到浏览器驱动的下载链接并下载需要的驱动,在Linux或macOS系统下可以通过下面的命令来设置PATH环境变量,Windows下配置环境变量也非常简单,不清楚的可以自行了解。 为了解决上面的问题,可以到Selenium的[官方网站]()找到浏览器驱动的下载链接并下载需要的驱动,在Linux或macOS系统下可以通过下面的命令来设置PATH环境变量,Windows下配置环境变量也非常简单,不清楚的可以自行了解。
```Shell ```Shell
export PATH=$PATH:/Users/Hao/Downloads/Tools/chromedriver/
$ export PATH=$PATH:/Users/Hao/Downloads/Tools/chromedriver/
``` ```
其中`/Users/Hao/Downloads/Tools/chromedriver/ `就是chromedriver所在的路径。 其中`/Users/Hao/Downloads/Tools/chromedriver/ `就是chromedriver所在的路径。
\ No newline at end of file
...@@ -43,13 +43,11 @@ Scrapy的整个数据处理流程由Scrapy引擎进行控制,通常的运转 ...@@ -43,13 +43,11 @@ Scrapy的整个数据处理流程由Scrapy引擎进行控制,通常的运转
```Shell ```Shell
$
``` ```
项目的目录结构如下图所示。 项目的目录结构如下图所示。
```Shell ```Shell
(venv) $ tree (venv) $ tree
. .
|____ scrapy.cfg |____ scrapy.cfg
...@@ -78,7 +76,6 @@ $ ...@@ -78,7 +76,6 @@ $
1. 在items.py文件中定义字段,这些字段用来保存数据,方便后续的操作。 1. 在items.py文件中定义字段,这些字段用来保存数据,方便后续的操作。
```Python ```Python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Define here the models for your scraped items # Define here the models for your scraped items
...@@ -102,12 +99,10 @@ $ ...@@ -102,12 +99,10 @@ $
2. 在spiders文件夹中编写自己的爬虫。 2. 在spiders文件夹中编写自己的爬虫。
```Shell ```Shell
(venv) $ scrapy genspider movie movie.douban.com --template=crawl (venv) $ scrapy genspider movie movie.douban.com --template=crawl
``` ```
```Python ```Python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import scrapy import scrapy
from scrapy.selector import Selector from scrapy.selector import Selector
...@@ -136,28 +131,24 @@ $ ...@@ -136,28 +131,24 @@ $
item['classification']= sel.xpath('//span[@property="v:genre"]/text()').extract() item['classification']= sel.xpath('//span[@property="v:genre"]/text()').extract()
item['actor']= sel.xpath('//*[@id="info"]/span[3]/a[1]/text()').extract() item['actor']= sel.xpath('//*[@id="info"]/span[3]/a[1]/text()').extract()
return item return item
``` ```
> 说明:上面我们通过Scrapy提供的爬虫模板创建了Spider,其中的rules中的LinkExtractor对象会自动完成对新的链接的解析,该对象中有一个名为extract_link的回调方法。Scrapy支持用XPath语法和CSS选择器进行数据解析,对应的方法分别是xpath和css,上面我们使用了XPath语法对页面进行解析,如果不熟悉XPath语法可以看看后面的补充说明。 > 说明:上面我们通过Scrapy提供的爬虫模板创建了Spider,其中的rules中的LinkExtractor对象会自动完成对新的链接的解析,该对象中有一个名为extract_link的回调方法。Scrapy支持用XPath语法和CSS选择器进行数据解析,对应的方法分别是xpath和css,上面我们使用了XPath语法对页面进行解析,如果不熟悉XPath语法可以看看后面的补充说明。
到这里,我们已经可以通过下面的命令让爬虫运转起来。 到这里,我们已经可以通过下面的命令让爬虫运转起来。
```Shell ```Shell
(venv)$ scrapy crawl movie (venv)$ scrapy crawl movie
``` ```
可以在控制台看到爬取到的数据,如果想将这些数据保存到文件中,可以通过`-o`参数来指定文件名,Scrapy支持我们将爬取到的数据导出成JSON、CSV、XML、pickle、marshal等格式。 可以在控制台看到爬取到的数据,如果想将这些数据保存到文件中,可以通过`-o`参数来指定文件名,Scrapy支持我们将爬取到的数据导出成JSON、CSV、XML、pickle、marshal等格式。
```Shell ```Shell
(venv)$ scrapy crawl moive -o result.json (venv)$ scrapy crawl moive -o result.json
``` ```
3. 在pipelines.py中完成对数据进行持久化的操作。 3. 在pipelines.py中完成对数据进行持久化的操作。
```Python ```Python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Define your item pipelines here # Define your item pipelines here
...@@ -211,7 +202,6 @@ $ ...@@ -211,7 +202,6 @@ $
4. 修改settings.py文件对项目进行配置。 4. 修改settings.py文件对项目进行配置。
```Python ```Python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Scrapy settings for douban project # Scrapy settings for douban project
...@@ -325,7 +315,6 @@ $ ...@@ -325,7 +315,6 @@ $
XML文件。 XML文件。
```XML ```XML
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<bookstore> <bookstore>
......
This diff is collapsed.
...@@ -145,19 +145,26 @@ ...@@ -145,19 +145,26 @@
- 使用进程 - fork函数 / multiprocessing模块 / 进程池 / 进程间通信 - 使用进程 - fork函数 / multiprocessing模块 / 进程池 / 进程间通信
- 使用线程 - thread模块 / threading模块 / Thread类 / Lock类 - 使用线程 - thread模块 / threading模块 / Thread类 / Lock类
#### Day14 - [网络编程入门](./Day01-15/Day14/网络编程入门.md) #### Day14-A - [网络编程入门](./Day01-15/Day14/网络编程入门.md)
- 计算机网络基础 - 计算机网络发展史 / “TCP-IP”模型 / IP地址 / 端口 / 协议 / 其他相关概念 - 计算机网络基础 - 计算机网络发展史 / “TCP-IP”模型 / IP地址 / 端口 / 协议 / 其他相关概念
- 网络应用架构 - “客户端-服务器”架构 / “浏览器-服务器”架构 - 网络应用架构 - “客户端-服务器”架构 / “浏览器-服务器”架构
- Python网络编程 - 套接字的概念 / socket模块 / socket函数 / 创建TCP服务器 / 创建TCP客户端 / 创建UDP服务器 / 创建UDP客户端 / SocketServer模块 - Python网络编程 - 套接字的概念 / socket模块 / socket函数 / 创建TCP服务器 / 创建TCP客户端 / 创建UDP服务器 / 创建UDP客户端 / SocketServer模块
#### Day15 - [网络应用开发](./Day01-15/Day15/网络应用开发.md) #### Day14-B - [网络应用开发](./Day01-15/Day15/网络应用开发.md)
- 访问网络API - 网络API概述 / 访问URL / requests模块 / 解析JSON格式数据 - 访问网络API - 网络API概述 / 访问URL / requests模块 / 解析JSON格式数据
- 文件传输 - FTP协议 / ftplib模块 / 交互式FTP应用 - 文件传输 - FTP协议 / ftplib模块 / 交互式FTP应用
- 电子邮件 - SMTP协议 / POP3协议 / IMAP协议 / smtplib模块 / poplib模块 / imaplib模块 - 电子邮件 - SMTP协议 / POP3协议 / IMAP协议 / smtplib模块 / poplib模块 / imaplib模块
- 短信服务 - twilio模块 / 国内的短信服务 - 短信服务 - twilio模块 / 国内的短信服务
#### Day15 - 图像和文档处理
- 用Pillow处理图片
- 读写Word文档
- 读写Excel文件
- 生成PDF文件
### Day16~Day20 - [Python语言进阶 ](./Day16-20/Python语言进阶.md) ### Day16~Day20 - [Python语言进阶 ](./Day16-20/Python语言进阶.md)
- 常用数据结构 - 常用数据结构
......
This diff is collapsed.
## 玩转PyCharm(上) ## 玩转PyCharm
PyCharm是由JetBrains公司开发的提供给Python专业的开发者的一个集成开发环境,它最大的优点是能够大大提升Python开发者的工作效率,为开发者集成了很多用起来非常顺手的功能,包括代码调试、高亮语法、代码跳转、智能提示、自动补全、单元测试、版本控制等等。此外,PyCharm还提供了对一些高级功能的支持,包括支持基于Django框架的Web开发、。 PyCharm是由JetBrains公司开发的提供给Python专业的开发者的一个集成开发环境,它最大的优点是能够大大提升Python开发者的工作效率,为开发者集成了很多用起来非常顺手的功能,包括代码调试、高亮语法、代码跳转、智能提示、自动补全、单元测试、版本控制等等。此外,PyCharm还提供了对一些高级功能的支持,包括支持基于Django框架的Web开发、。
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment