更新了部分文档和代码

pull/25/head
jackfrued 2018-12-22 16:26:07 +08:00
parent 2d08d42fff
commit 321278297f
63 changed files with 1956 additions and 874 deletions

View File

@ -1,93 +1,101 @@
from turtle import*
"""
绘制小猪佩奇
"""
from turtle import *
def nose(x,y):#鼻子
penup()#提起笔
goto(x,y)#定位
pendown()#落笔,开始画
setheading(-30)#将乌龟的方向设置为to_angle/为数字0-东、90-北、180-西、270-南)
begin_fill()#准备开始填充图形
a=0.4
def nose(x,y):
"""画鼻子"""
penup()
# 将海龟移动到指定的坐标
goto(x,y)
pendown()
# 设置海龟的方向0-东、90-北、180-西、270-南)
setheading(-30)
begin_fill()
a = 0.4
for i in range(120):
if 0<=i<30 or 60<=i<90:
a=a+0.08
left(3) #向左转3度
forward(a) #向前走a的步长
if 0 <= i < 30 or 60 <= i <90:
a = a + 0.08
# 向左转3度
left(3)
# 向前走
forward(a)
else:
a=a-0.08
a = a - 0.08
left(3)
forward(a)
end_fill()#填充完成
end_fill()
penup()
setheading(90)
forward(25)
setheading(0)
forward(10)
pendown()
pencolor(255,155,192)#画笔颜色
# 设置画笔的颜色(红, 绿, 蓝)
pencolor(255, 155, 192)
setheading(10)
begin_fill()
circle(5)
color(160,82,45)#返回或设置pencolor和fillcolor
color(160, 82, 45)
end_fill()
penup()
setheading(0)
forward(20)
pendown()
pencolor(255,155,192)
pencolor(255, 155, 192)
setheading(10)
begin_fill()
circle(5)
color(160,82,45)
color(160, 82, 45)
end_fill()
def head(x,y):#头
color((255,155,192),"pink")
def head(x, y):
"""画头"""
color((255, 155, 192), "pink")
penup()
goto(x,y)
setheading(0)
pendown()
begin_fill()
setheading(180)
circle(300,-30)
circle(100,-60)
circle(80,-100)
circle(150,-20)
circle(60,-95)
circle(300, -30)
circle(100, -60)
circle(80, -100)
circle(150, -20)
circle(60, -95)
setheading(161)
circle(-300,15)
circle(-300, 15)
penup()
goto(-100,100)
goto(-100, 100)
pendown()
setheading(-30)
a=0.4
a = 0.4
for i in range(60):
if 0<=i<30 or 60<=i<90:
a=a+0.08
if 0<= i < 30 or 60 <= i < 90:
a = a + 0.08
lt(3) #向左转3度
fd(a) #向前走a的步长
else:
a=a-0.08
a = a - 0.08
lt(3)
fd(a)
end_fill()
def ears(x,y): #耳朵
color((255,155,192),"pink")
def ears(x,y):
"""画耳朵"""
color((255, 155, 192), "pink")
penup()
goto(x,y)
goto(x, y)
pendown()
begin_fill()
setheading(100)
circle(-50,50)
circle(-10,120)
circle(-50,54)
circle(-50, 50)
circle(-10, 120)
circle(-50, 54)
end_fill()
penup()
setheading(90)
forward(-12)
@ -96,14 +104,15 @@ def ears(x,y): #耳朵
pendown()
begin_fill()
setheading(100)
circle(-50,50)
circle(-10,120)
circle(-50,56)
circle(-50, 50)
circle(-10, 120)
circle(-50, 56)
end_fill()
def eyes(x,y):#眼睛
color((255,155,192),"white")
def eyes(x,y):
"""画眼睛"""
color((255, 155, 192), "white")
penup()
setheading(90)
forward(-20)
@ -113,7 +122,6 @@ def eyes(x,y):#眼睛
begin_fill()
circle(15)
end_fill()
color("black")
penup()
setheading(90)
@ -124,8 +132,7 @@ def eyes(x,y):#眼睛
begin_fill()
circle(3)
end_fill()
color((255,155,192),"white")
color((255, 155, 192), "white")
penup()
seth(90)
forward(-25)
@ -135,7 +142,6 @@ def eyes(x,y):#眼睛
begin_fill()
circle(15)
end_fill()
color("black")
penup()
setheading(90)
@ -148,8 +154,9 @@ def eyes(x,y):#眼睛
end_fill()
def cheek(x,y):#腮
color((255,155,192))
def cheek(x,y):
"""画脸颊"""
color((255, 155, 192))
penup()
goto(x,y)
pendown()
@ -159,35 +166,39 @@ def cheek(x,y):#腮
end_fill()
def mouth(x,y): #嘴
color(239,69,19)
def mouth(x,y):
"""画嘴巴"""
color(239, 69, 19)
penup()
goto(x,y)
goto(x, y)
pendown()
setheading(-80)
circle(30,40)
circle(40,80)
circle(30, 40)
circle(40, 80)
def setting(): #参数设置
def setting():
"""设置参数"""
pensize(4)
hideturtle() #使乌龟无形(隐藏)
colormode(255) #将其设置为1.0或255.随后 颜色三元组的rgb值必须在0 .. cmode范围内
color((255,155,192),"pink")
setup(840,500)
# 隐藏海龟
hideturtle()
colormode(255)
color((255, 155, 192), "pink")
setup(840, 500)
speed(10)
def main():
setting() #画布、画笔设置
nose(-100,100) #鼻子
head(-69,167) #头
ears(0,160) #耳朵
eyes(0,140) #眼睛
cheek(80,10) #腮
mouth(-20,30) #嘴
"""主函数"""
setting()
nose(-100, 100)
head(-69, 167)
ears(0, 160)
eyes(0, 140)
cheek(80, 10)
mouth(-20, 30)
done()
if __name__ == '__main__':
main()
main()

View File

@ -7,38 +7,38 @@
1. 1989年圣诞节Guido von Rossum开始写Python语言的编译器。
2. 1991年2月第一个Python编译器同时也是解释器诞生它是用C语言实现的后面又出现了Java和C#实现的版本Jython和IronPython以及PyPy、Brython、Pyston等其他实现可以调用C语言的库函数。在最早的版本中Python已经提供了对“类”“函数”“异常处理”等构造块的支持同时提供了“列表”和“字典”等核心数据类型同时支持以模块为基础的拓展系统。
3. 1994年1月Python 1.0正式发布。
4. 2000年10月16日Python 2.0发布,增加了实现完整的[垃圾回收](https://zh.wikipedia.org/wiki/%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6_(%E8%A8%88%E7%AE%97%E6%A9%9F%E7%A7%91%E5%AD%B8))并且支持[Unicode](https://zh.wikipedia.org/wiki/Unicode)。与此同时Python的整个开发过程更加透明社区对开发进度的影响逐渐扩大生态圈开始慢慢形成。
5. 2008年12月3日Python 3.0发布,此版不完全兼容之前的Python代码不过很多新特性后来也被移植到旧的Python 2.6/2.7版本因为目前还有公司在项目和运维中使用Python 2.x版本的代码
4. 2000年10月16日Python 2.0发布,增加了实现完整的[垃圾回收](https://zh.wikipedia.org/wiki/%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6_(%E8%A8%88%E7%AE%97%E6%A9%9F%E7%A7%91%E5%AD%B8))提供了对[Unicode](https://zh.wikipedia.org/wiki/Unicode)的支持。与此同时Python的整个开发过程更加透明社区对开发进度的影响逐渐扩大生态圈开始慢慢形成。
5. 2008年12月3日Python 3.0发布,它并不完全兼容之前的Python代码不过因为目前还有不少公司在项目和运维中使用Python 2.x版本所以Python 3.x的很多新特性后来也被移植到Python 2.6/2.7版本中
目前我们使用的Python 3.6.x的版本是在2016年的12月23日发布的Python的版本号分为三段形如A.B.C。其中A表示大版本号一般当整体重写或出现不向后兼容的改变时增加AB表示功能更新出现新功能时增加BC表示小的改动如修复了某个Bug只要有修改就增加C。如果对Python的历史感兴趣可以查看一篇名为[《Python简史》](http://www.cnblogs.com/vamei/archive/2013/02/06/2892628.html)的博文。
目前我们使用的Python 3.7.x的版本是在2018年发布的Python的版本号分为三段形如A.B.C。其中A表示大版本号一般当整体重写或出现不向后兼容的改变时增加AB表示功能更新出现新功能时增加BC表示小的改动如修复了某个Bug只要有修改就增加C。如果对Python的历史感兴趣可以查看一篇名为[《Python简史》](http://www.cnblogs.com/vamei/archive/2013/02/06/2892628.html)的博文。
#### Python的优缺点
Python的优点很多简单的可以总结为以下几点。
1. 简单和明确,做一件事只有一种方法。
2. 学习曲线低,与其他很多语言比上手更容易
2. 学习曲线低,跟其他很多语言相比Python更容易上手
3. 开放源代码,拥有强大的社区和生态圈。
4. 解释型语言,完美的平台可移植性。
5. 支持两种主流的编程范式,可以使用面向对象和函数式编程
6. 可扩展性和可嵌入性可以调用C/C++代码也可以在C/C++中调用。
4. 解释型语言,天生具有平台可移植性。
5. 支持两种主流的编程范式(面向对象编程和函数式编程)都提供了支持
6. 可扩展性和可嵌入性可以调用C/C++代码也可以在C/C++中调用Python
7. 代码规范程度高,可读性强,适合有代码洁癖和强迫症的人群。
Python的缺点主要集中在以下几点。
1. 执行效率低因此计算密集型任务可以由C/C++编写。
2. 代码无法加密,但是现在的公司很多都不是卖软件而是卖服务,这个问题慢慢会淡化。
3. 在开发时可以选择的框架太多,有选择的地方就有错误。
1. 执行效率因此计算密集型任务可以由C/C++编写。
2. 代码无法加密,但是现在的公司很多都不是卖软件而是卖服务,这个问题会淡化。
3. 在开发时可以选择的框架太多如Web框架就有100多个,有选择的地方就有错误。
#### Python的应用领域
目前Python在云基础设施、DevOps、网络爬虫开发、数据分析挖掘、机器学习等领域都有着广泛的应用因此也产生了服务器开发、数据接口开发、自动化运维、科学计算和数据可视化、聊天机器人开发、图像识别和处理等一系列的职位。
目前Python在云基础设施、DevOps、网络爬虫开发、数据分析挖掘、机器学习等领域都有着广泛的应用因此也产生了Web后端开发、数据接口开发、自动化运维、自动化测试、科学计算和可视化、数据分析、量化交易、机器人开发、图像识别和处理等一系列的职位。
### 搭建编程环境
#### Windows环境
可以在[Python官方网站](https://www.python.org)下载到Python的Windows安装程序exe文件需要注意的是如果在Windows 7环境下安装需要先安装Service Pack 1补丁包可以通过一些工具软件自动安装系统补丁的功能来安装安装过程建议勾选“Add Python 3.6 to PATH”将Python 3.6添加到PATH环境变量并选择自定义安装在设置“Optional Features”界面最好将“pip”、“tcl/tk”、“Python test suite”等项全部勾选上。强烈建议使用自定义的安装路径并保证路径中没有中文。安装完成会看到“Setup was successful”的提示但是在启动Python环境时可能会因为缺失一些动态链接库文件而导致Python解释器无法运行常见的问题主要是api-ms-win-crt\*.dll缺失以及更新DirectX之后导致某些动态链接库文件缺失前者可以参照[《api-ms-win-crt\*.dll缺失原因分析和解决方法》]()一文讲解的方法进行处理或者直接在[微软官网](https://www.microsoft.com/zh-cn/download/details.aspx?id=48145)下载Visual C++ Redistributable for Visual Studio 2015文件进行修复后者可以下载一个DirectX修复工具进行修复。
可以在[Python官方网站](https://www.python.org)下载到Python的Windows安装程序exe文件需要注意的是如果在Windows 7环境下安装需要先安装Service Pack 1补丁包可以通过一些工具软件自动安装系统补丁的功能来安装安装过程建议勾选“Add Python 3.6 to PATH”将Python 3.6添加到PATH环境变量并选择自定义安装在设置“Optional Features”界面最好将“pip”、“tcl/tk”、“Python test suite”等项全部勾选上。强烈建议使用自定义的安装路径并保证路径中没有中文。安装完成会看到“Setup was successful”的提示但是在启动Python环境时可能会因为缺失一些动态链接库文件而导致Python解释器无法运行常见的问题主要是api-ms-win-crt\*.dll缺失以及更新DirectX之后导致某些动态链接库文件缺失前者可以参照[《api-ms-win-crt\*.dll缺失原因分析和解决方法》]()一文讲解的方法进行处理或者直接在[微软官网](https://www.microsoft.com/zh-cn/download/details.aspx?id=48145)下载Visual C++ Redistributable for Visual Studio 2015文件进行修复后者可以下载一个DirectX修复工具进行修复。
#### Linux环境
@ -53,15 +53,15 @@ yum -y install wget gcc zlib-devel bzip2-devel openssl-devel ncurses-devel sqlit
下载Python源代码并解压缩到指定目录。
```Shell
wget https://www.python.org/ftp/python/3.7.0/Python-3.7.0.tar.xz
xz -d Python-3.7.0.tar.xz
tar -xvf Python-3.7.0.tar
wget https://www.python.org/ftp/python/3.7.0/Python-3.7.1.tar.xz
xz -d Python-3.7.1.tar.xz
tar -xvf Python-3.7.1.tar
```
切换至Python源代码目录并执行下面的命令进行配置和安装。
```Shell
cd Python-3.7.0
cd Python-3.7.1
./configure --prefix=/usr/local/python37 --enable-optimizations
make && make install
```
@ -87,7 +87,7 @@ source .bash_profile
#### MacOS环境
MacOS也是自带了Python 2.x版本的可以通过[Python的官方网站](https://www.python.org)提供的安装文件pkg文件安装3.x的版本。默认安装完成后可以通过在终端执行python命令来启动2.x版本的Python解释器可以通过执行python3命令来启动3.x版本的Python解释器当然也可以通过重新设置软链接来修改启动Python解释器的命令
MacOS也是自带了Python 2.x版本的可以通过[Python的官方网站](https://www.python.org)提供的安装文件pkg文件安装3.x的版本。默认安装完成后可以通过在终端执行python命令来启动2.x版本的Python解释器可以通过执行python3命令来启动3.x版本的Python解释器。
### 从终端运行Python程序
@ -137,7 +137,6 @@ python hello.py
Version: 0.1
Author: 骆昊
Date: 2018-02-26
"""
print('hello, world!')
@ -179,8 +178,6 @@ python -m pip install ipython jupyter
jupyter notebook
```
![](./res/python-jupyter-1.png)
![](./res/python-jupyter-2.png)
#### Sublime - 文本编辑神器
@ -203,13 +200,13 @@ jupyter notebook
import urllib2,os;pf='Package Control.sublime-package';ipp=sublime.installed_packages_path();os.makedirs(ipp)ifnotos.path.exists(ipp)elseNone;urllib2.install_opener(urllib2.build_opener(urllib2.ProxyHandler()));open(os.path.join(ipp,pf),'wb').write(urllib2.urlopen('http://sublime.wbond.net/'+pf.replace(' ','%20')).read());print('Please restart Sublime Text to finish installation')
```
- 安装插件。通过Preference菜单的Package Control或快捷键Ctrl+Shift+P打开命令面板在面板中输入Install Package就可以找到安装插件的工具然后再查找需要的插件。我们推荐大家安装以下几个插件
- 安装插件。通过Preference菜单的Package Control或快捷键Ctrl+Shift+P打开命令面板在面板中输入Install Package就可以找到安装插件的工具然后再查找需要的插件。我们推荐大家安装以下几个插件
- SublimeCodeIntel - 代码自动补全工具插件
- Emmet - 前端开发代码模板插件
- Git - 版本控制工具插件
- Python PEP8 Autoformat - PEP8规范自动格式化插件
- ConvertToUTF8 - 将本地编码转换为UTF-8
- SublimeCodeIntel - 代码自动补全工具插件
- Emmet - 前端开发代码模板插件
- Git - 版本控制工具插件
- Python PEP8 Autoformat - PEP8规范自动格式化插件
- ConvertToUTF8 - 将本地编码转换为UTF-8
#### PyCharm - Python开发神器

View File

@ -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 @@
- 浮点型:浮点数也就是小数,之所以称为浮点数,是因为按照科学记数法表示时,一个浮点数的小数点位置是可变的,浮点数除了数学写法(如`123.456`)之外还支持科学计数法(如`1.23456e2`)。
- 字符串型:字符串是以单引号或双引号括起来的任意文本,比如`'hello'`和`"hello"`,字符串还有原始字符串表示法、字节字符串表示法、Unicode字符串表示法而且可以书写成多行的形式用三个单引号或三个双引号开头三个单引号或三个双引号结尾
- 布尔型:布尔值只有`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 @@
- 受保护的实例属性用单个下划线开头(后面会讲到)。
- 私有的实例属性用两个下划线开头(后面会讲到)。
当然,作为一个专业的程序员,给变量(事实上应该是所有的标识符)命名做到见名知意也是非常重要的。
当然,作为一个专业的程序员,给变量(事实上应该是所有的标识符)命名做到见名知意也是非常重要的。
#### 变量的使用
@ -39,7 +39,6 @@
Version: 0.1
Author: 骆昊
Date: 2018-02-27
"""
a = 321
@ -62,7 +61,6 @@ print(a ** b)
Version: 0.1
Author: 骆昊
Date: 2018-02-27
"""
a = int(input('a = '))
@ -138,7 +136,6 @@ Python支持多种运算符下表大致按照优先级从高到低的顺序
Version: 0.1
Author: 骆昊
Date: 2018-02-27
"""
a = 5
@ -178,7 +175,6 @@ F = 1.8C + 32
Version: 0.1
Author: 骆昊
Date: 2018-02-27
"""
f = float(input('请输入华氏温度: '))
@ -195,7 +191,6 @@ print('%.1f华氏度 = %.1f摄氏度' % (f, c))
Version: 0.1
Author: 骆昊
Date: 2018-02-27
"""
import math
@ -216,7 +211,6 @@ print('面积: %.2f' % area)
Version: 0.1
Author: 骆昊
Date: 2018-02-27
"""
year = int(input('请输入年份: '))

View File

@ -14,7 +14,6 @@
Version: 0.1
Author: 骆昊
Date: 2018-02-28
"""
username = input('请输入用户名: ')
@ -44,7 +43,6 @@ f(x) = x + 2 (-1 <= x <= 1)
Version: 0.1
Author: 骆昊
Date: 2018-02-28
"""
x = float(input('x = '))
@ -68,7 +66,6 @@ f(x) = x + 2 (-1 <= x <= 1)
Version: 0.1
Author: 骆昊
Date: 2018-02-28
"""
x = float(input('x = '))
@ -94,7 +91,6 @@ print('f(%.2f) = %.2f' % (x, y))
Version: 0.1
Author: 骆昊
Date: 2018-02-28
"""
value = float(input('请输入长度: '))
@ -115,7 +111,6 @@ else:
Version: 0.1
Author: 骆昊
Date: 2018-02-28
"""
from random import randint
@ -150,7 +145,6 @@ print(result)
Version: 0.1
Author: 骆昊
Date: 2018-02-28
"""
score = float(input('请输入成绩: '))
@ -175,7 +169,6 @@ print('对应的等级是:', grade)
Version: 0.1
Author: 骆昊
Date: 2018-02-28
"""
import math
@ -193,7 +186,7 @@ else:
```
> **说明:**上面的代码中使用了`math`模块的`sqrt`函数来计算平方根。用边长计算三角形面积的公式叫做[海伦公式](https://zh.wikipedia.org/zh-hans/海伦公式)。
#### 练习5实现一个个人所得税计算器。
#### 练习5个人所得税计算器。
```Python
"""
@ -201,7 +194,6 @@ else:
Version: 0.1
Author: 骆昊
Date: 2018-02-28
"""
salary = float(input('本月收入: '))

View File

@ -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循环
@ -14,7 +14,6 @@
Version: 0.1
Author: 骆昊
Date: 2018-03-01
"""
sum = 0
@ -37,7 +36,6 @@ print(sum)
Version: 0.1
Author: 骆昊
Date: 2018-03-01
"""
sum = 0
@ -54,7 +52,6 @@ print(sum)
Version: 0.1
Author: 骆昊
Date: 2018-03-01
"""
sum = 0
@ -77,7 +74,6 @@ print(sum)
Version: 0.1
Author: 骆昊
Date: 2018-03-01
"""
import random
@ -109,8 +105,6 @@ if counter > 7:
Version: 0.1
Author: 骆昊
Date: 2018-03-01
"""
for i in range(1, 10):
@ -196,7 +190,6 @@ for factor in range(x, 0, -1):
Version: 0.1
Author: 骆昊
Date: 2018-03-01
"""
row = int(input('请输入行数: '))

View File

@ -27,7 +27,6 @@ fmn = 1
for num in range(1, m - n + 1):
fmn *= num
print(fm // fn // fmn)
```
### 函数的作用
@ -134,7 +133,8 @@ def foo():
print('goodbye, world!')
foo() # 输出goodbye, world!
# 下面的代码会输出什么呢?
foo()
```
当然上面的这种情况我们很容易就能避免,但是如果项目是由多人协作进行团队开发的时候,团队中可能有多个程序员都定义了名为`foo`的函数那么怎么解决这种命名冲突呢答案其实很简单Python中每个文件就代表了一个模块module我们在不同的模块中可以有同名的函数在使用函数的时候我们通过`import`关键字导入指定的模块就可以区分到底要使用的是哪个模块中的`foo`函数,代码如下所示。
@ -158,11 +158,13 @@ test.py
```Python
from module1 import foo
foo() # 输出hello, world!
# 输出hello, world!
foo()
from module2 import foo
foo() # 输出goodbye, world!
# 输出goodbye, world!
foo()
```
也可以按照如下所示的方式来区分到底要使用哪一个`foo`函数。
@ -185,7 +187,8 @@ test.py
from module1 import foo
from module2 import foo
foo() # 输出goodbye, world!
# 输出goodbye, world!
foo()
```
test.py
@ -194,7 +197,8 @@ test.py
from module2 import foo
from module1 import foo
foo() # 输出hello, world!
# 输出hello, world!
foo()
```
需要说明的是如果我们导入的模块除了定义函数之外还中有可以执行代码那么Python解释器在导入这个模块时就会执行这些代码事实上我们可能并不希望如此因此如果我们在模块中编写了执行代码最好是将这些执行代码放入如下所示的条件中这样的话除非直接运行该模块if条件下的这些代码是不会执行的因为只有直接执行的模块的名字才是“\_\_main\_\_”。

View File

@ -42,7 +42,6 @@ def main():
if __name__ == '__main__':
main()
```
下面是运行程序得到的一次运行结果。
@ -86,7 +85,6 @@ def main():
if __name__ == '__main__':
main()
```
在上面的代码中,我们通过`Process`类创建了进程对象,通过`target`参数我们传入一个函数来表示进程启动后要执行的代码,后面的`args`是一个元组,它代表了传递给函数的参数。`Process`对象的`start`方法用来启动进程,而`join`方法表示等待进程执行结束。运行上面的代码可以明显发现两个下载任务“同时”启动了,而且程序的执行时间将大大缩短,不再是两个任务的时间总和。下面是程序的一次执行结果。
@ -375,7 +373,6 @@ def main():
if __name__ == '__main__':
main()
```
如果使用多线程将耗时间的任务放到一个独立的线程中执行,这样就不会因为执行耗时间的任务而阻塞了主线程,修改后的代码如下所示。
@ -424,7 +421,6 @@ def main():
if __name__ == '__main__':
main()
```
#### 例子2使用多进程对复杂任务进行“分而治之”。
@ -448,7 +444,6 @@ def main():
if __name__ == '__main__':
main()
```
在上面的代码中我故意先去创建了一个列表容器然后填入了100000000个数这一步其实是比较耗时间的所以为了公平起见当我们将这个任务分解到8个进程中去执行的时候我们暂时也不考虑列表切片操作花费的时间只是把做运算和合并运算结果的时间统计出来代码如下所示。
@ -493,7 +488,6 @@ def main():
if __name__ == '__main__':
main()
```
比较两段代码的执行结果在我目前使用的MacBook上上面的代码需要大概6秒左右的时间而下面的代码只需要不到1秒的时间再强调一次我们只是比较了运算的时间不考虑列表创建及切片操作花费的时间使用多进程后由于获得了更多的CPU执行时间以及更好的利用了CPU的多核特性明显的减少了程序的执行时间而且计算量越大效果越明显。当然如果愿意还可以将多个进程部署在不同的计算机上做成分布式进程具体的做法就是通过multiprocessing.managers模块中提供的管理器将`Queue`对象通过网络共享出来(注册到网络上让其他计算机可以访问),这部分内容也留到爬虫的专题再进行讲解。

View File

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 59 KiB

View File

Before

Width:  |  Height:  |  Size: 110 KiB

After

Width:  |  Height:  |  Size: 110 KiB

View File

Before

Width:  |  Height:  |  Size: 182 KiB

After

Width:  |  Height:  |  Size: 182 KiB

View File

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 39 KiB

View File

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

View File

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

View File

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

Before

Width:  |  Height:  |  Size: 71 KiB

After

Width:  |  Height:  |  Size: 71 KiB

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

Before

Width:  |  Height:  |  Size: 120 KiB

After

Width:  |  Height:  |  Size: 120 KiB

View File

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 42 KiB

View File

Before

Width:  |  Height:  |  Size: 107 KiB

After

Width:  |  Height:  |  Size: 107 KiB

View File

@ -126,7 +126,6 @@ def main():
if __name__ == '__main__':
main()
```
### 基于传输层协议的套接字编程
@ -174,7 +173,6 @@ def main():
if __name__ == '__main__':
main()
```
运行服务器程序后我们可以通过Windows系统的telnet来访问该服务器结果如下图所示。
@ -203,7 +201,6 @@ def main():
if __name__ == '__main__':
main()
```
需要注意的是上面的服务器并没有使用多线程或者异步I/O的处理方式这也就意味着当服务器与一个客户端处于通信状态时其他的客户端只能排队等待。很显然这样的服务器并不能满足我们的需求我们需要的服务器是能够同时接纳和处理多个用户请求的。下面我们来设计一个使用多线程技术处理多个用户请求的服务器该服务器会向连接到服务器的客户端发送一张图片。
@ -256,7 +253,6 @@ def main():
if __name__ == '__main__':
main()
```
客户端代码:
@ -291,7 +287,6 @@ def main():
if __name__ == '__main__':
main()
```
在这个案例中我们使用了JSON作为数据传输的格式通过JSON格式对传输的数据进行了序列化和反序列化的操作但是JSON并不能携带二进制数据因此对图片的二进制数据进行了Base64编码的处理。Base64是一种用64个字符表示所有二进制数据的编码方式通过将二进制数据每6位一组的方式重新组织刚好可以使用0~9的数字、大小写字母以及“+”和“/”总共64个字符表示从`000000`到`111111`的64种状态。[维基百科](https://zh.wikipedia.org/wiki/Base64)上有关于Base64编码的详细讲解不熟悉Base64的读者可以自行阅读。

View File

@ -31,7 +31,6 @@ def main():
if __name__ == '__main__':
main()
```
如果要发送带有附件的邮件,那么可以按照下面的方式进行操作。
@ -88,7 +87,6 @@ def main():
if __name__ == '__main__':
main()
```
### 发送短信
@ -119,7 +117,5 @@ def main():
if __name__ == '__main__':
main()
```

View File

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 59 KiB

File diff suppressed because it is too large Load Diff

View File

@ -1249,7 +1249,3 @@ build environment:
3. HISTSIZE
4. RANDOM
5. PATH

View File

@ -115,7 +115,6 @@ HTTP响应响应行+响应头+空行+消息体):
3. HTTPie命令行HTTP客户端。
```Shell
$ http --header http://www.scu.edu.cn
HTTP/1.1 200 OK
Accept-Ranges: bytes
@ -138,8 +137,6 @@ HTTP响应响应行+响应头+空行+消息体):
4. BuiltWith识别网站所用技术的工具。
```Python
>>>
>>> import builtwith
>>> 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']}
@ -153,8 +150,6 @@ HTTP响应响应行+响应头+空行+消息体):
5. python-whois查询网站所有者的工具。
```Python
>>>
>>> import whois
>>> 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'}
@ -195,7 +190,6 @@ HTTP响应响应行+响应头+空行+消息体):
下面的例子给出了一个从“搜狐体育”上获取NBA新闻标题和链接的爬虫。
```Python
from urllib.error import URLError
from urllib.request import urlopen
@ -304,7 +298,6 @@ if __name__ == '__main__':
- 使用未经验证的上下文
```Python
import ssl
request = urllib.request.Request(url='...', headers={...})
@ -315,10 +308,8 @@ if __name__ == '__main__':
- 设置全局的取消证书验证
```Python
import ssl
ssl._create_default_https_context = ssl._create_unverified_context
```

View File

@ -12,7 +12,6 @@
### HTML页面分析
```HTML
<!DOCTYPE html>
<html lang="en">
<head>
@ -136,7 +135,6 @@ pyquery相当于jQuery的Python实现可以用于解析HTML网页。
### 实例 - 获取知乎发现上的问题链接
```Python
from urllib.parse import urljoin
import re
@ -168,6 +166,5 @@ def main():
if __name__ == '__main__':
main()
```

View File

@ -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)解压缩解归档之后进行构件安装。
```Shell
# wget http://download.redis.io/releases/redis-3.2.11.tar.gz
# gunzip redis-3.2.11.tar.gz
# tar -xvf redis-3.2.11.tar
# cd redis-3.2.11
# make && make install
wget http://download.redis.io/releases/redis-3.2.11.tar.gz
gunzip redis-3.2.11.tar.gz
tar -xvf redis-3.2.11.tar
cd redis-3.2.11
make && make install
```
接下来我们将redis-3.2.11目录下的redis.conf配置文件复制到用户主目录下并修改配置文件如果你对配置文件不是很有把握就不要直接修改而是先复制一份再修改这个副本
```Shell
# cd ..
# cp redis-3.2.11/redis.conf redis.conf
# vim redis.conf
cd ..
cp redis-3.2.11/redis.conf redis.conf
vim redis.conf
```
配置将Redis服务绑定到指定的IP地址和端口。
@ -76,8 +74,7 @@ Redis是REmote DIctionary Server的缩写它是一个用ANSI C编写的高性
接下来启动Redis服务器可以将服务器放在后台去运行。
```Shell
# redis-server redis.conf &
redis-server redis.conf &
_.-``__ ''-._
_.-`` `. `_. ''-._ Redis 3.2.11 (00000000/0) 64 bit
@ -100,8 +97,7 @@ Redis是REmote DIctionary Server的缩写它是一个用ANSI C编写的高性
接下来我们尝试用Redis客户端去连接服务器。
```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
OK
172.18.61.250:6379> ping
@ -112,7 +108,6 @@ PONG
Redis有着非常丰富的数据类型也有很多的命令来操作这些数据具体的内容可以查看[Redis命令参考](http://redisdoc.com/)在这个网站上除了Redis的命令参考还有Redis的详细文档其中包括了通知、事务、主从复制、持久化、哨兵、集群等内容。
```Shell
172.18.61.250:6379> set username admin
OK
172.18.61.250:6379> get username
@ -166,13 +161,11 @@ OK
可以使用pip安装redis模块。redis模块的核心是名为Redis的类该类的对象代表一个Redis客户端通过该客户端可以向Redis服务器发送命令并获取执行的结果。上面我们在Redis客户端中使用的命令基本上就是Redis对象可以接收的消息所以如果了解了Redis的命令就可以在Python中玩转Redis。
```Shell
$ pip3 install redis
$ python3
pip3 install redis
python3
```
```Python
>>> import redis
>>> client = redis.Redis(host='1.2.3.4', port=6379, password='1qaz2wsx')
>>> client.set('username', 'admin')
@ -202,14 +195,14 @@ MongoDB将数据存储为一个文档一个文档由一系列的“键值对
可以从MongoDB的[官方下载链接](https://www.mongodb.com/download-center#community)下载MongoDB官方为Windows系统提供了一个Installer程序而Linux和MacOS则提供了压缩文件。下面简单说一下Linux系统如何安装和配置MongoDB。
```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] db version v3.6.5
2018-06-03T18:03:28.232+0800 I CONTROL [initandlisten] git version: a20ecd3e3a174162052ff99913bc2ca9a839d618
@ -239,7 +232,8 @@ MongoDB将数据存储为一个文档一个文档由一系列的“键值对
启动服务器后可以使用交互式环境跟服务器通信,如下所示。
```shell
# mongo --host 172.18.61.250
mongo --host 172.18.61.250
MongoDB shell version v3.6.5
connecting to: mongodb://172.18.61.250:27017/
...
@ -249,7 +243,6 @@ connecting to: mongodb://172.18.61.250:27017/
1. 查看、创建和删除数据库。
```JavaScript
> // 显示所有数据库
> show dbs
admin 0.000GB
@ -267,7 +260,6 @@ connecting to: mongodb://172.18.61.250:27017/
2. 创建、删除和查看集合。
```JavaScript
> // 创建并切换到school数据库
> use school
switched to db school
@ -292,7 +284,6 @@ connecting to: mongodb://172.18.61.250:27017/
3. 文档的CRUD操作。
```JavaScript
> // 向students集合插入文档
> db.students.insert({stuid: 1001, name: '骆昊', age: 38})
WriteResult({ "nInserted" : 1 })
@ -394,13 +385,11 @@ connecting to: mongodb://172.18.61.250:27017/
可以通过pip安装pymongo来实现对MongoDB的操作。
```Shell
$ pip3 install pymongo
$ python3
pip3 install pymongo
python3
```
```Python
>>> from pymongo import MongoClient
>>> client = MongoClient('mongodb://120.77.222.217:27017')
>>> db = client.school
@ -451,7 +440,6 @@ $ python3
### 实例 - 缓存知乎发现上的链接和页面代码
```Python
from hashlib import sha1
from urllib.parse import urljoin
@ -501,7 +489,6 @@ def main():
if __name__ == '__main__':
main()
```

View File

@ -44,7 +44,6 @@ Python3.2带来了`concurrent.futures` 模块,这个模块包含了线程池
1. 生成器 - 数据的生产者。
```Python
from time import sleep
@ -70,7 +69,6 @@ Python3.2带来了`concurrent.futures` 模块,这个模块包含了线程池
生成器还可以叠加来组成生成器管道,代码如下所示。
```Python
# Fibonacci数生成器
def fib():
a, b = 0, 1
@ -94,13 +92,11 @@ Python3.2带来了`concurrent.futures` 模块,这个模块包含了线程池
if __name__ == '__main__':
main()
```
2. 协程 - 数据的消费者。
```Python
from time import sleep
@ -130,13 +126,11 @@ Python3.2带来了`concurrent.futures` 模块,这个模块包含了线程池
if __name__ == '__main__':
main()
```
> 说明上面代码中countdown_gen函数中的第1行consumer.send(None)是为了激活生成器通俗的说就是让生成器执行到有yield关键字的地方挂起当然也可以通过next(consumer)来达到同样的效果。如果不愿意每次都用这样的代码来“预激”生成器,可以写一个包装器来完成该操作,代码如下所示。
```Python
from functools import wraps
@ -156,7 +150,6 @@ Python3.2带来了`concurrent.futures` 模块,这个模块包含了线程池
3. 异步I/O - 非阻塞式I/O操作。
```Python
import asyncio
@ -179,13 +172,11 @@ Python3.2带来了`concurrent.futures` 模块,这个模块包含了线程池
if __name__ == '__main__':
main()
```
4. `async`和`await`。
4. `async`和`await`。
```Python
import asyncio
import aiohttp
@ -215,7 +206,6 @@ Python3.2带来了`concurrent.futures` 模块,这个模块包含了线程池
if __name__ == '__main__':
main()
```
上面的代码使用了[AIOHTTP](https://github.com/aio-libs/aiohttp)这个非常著名的第三方库它实现了HTTP客户端和HTTP服务器的功能对异步操作提供了非常好的支持有兴趣可以阅读它的[官方文档](https://aiohttp.readthedocs.io/en/stable/)。
@ -225,7 +215,6 @@ Python3.2带来了`concurrent.futures` 模块,这个模块包含了线程池
下面我们把之间讲的所有知识结合起来,用面向对象的方式实现一个爬取“手机搜狐网”的多线程爬虫。
```Python
import pickle
import zlib
from enum import Enum, unique
@ -382,6 +371,5 @@ def main():
if __name__ == '__main__':
main()
```

View File

@ -25,14 +25,12 @@ WebKit的代码始于1998年的KHTML项目当时它是Konqueror浏览器的
如果没有打算用上面所说的方式来渲染页面并获得动态内容其实还有一种替代方案就是使用自动化测试工具Selenium它提供了浏览器自动化的API接口这样就可以通过操控浏览器来获取动态内容。首先可以使用pip来安装Selenium。
```Shell
$ pip3 install selenium
pip3 install selenium
```
下面以“阿里V任务”的“直播服务”为例来演示如何使用Selenium获取到动态内容并抓取主播图片。
```Python
import requests
from bs4 import BeautifulSoup
@ -47,13 +45,11 @@ def main():
if __name__ == '__main__':
main()
```
运行上面的程序会发现没有任何的输出因为页面的HTML代码上根本找不到`<img>`标签。接下来我们使用Selenium来获取到页面上的动态内容再提取主播图片。
```Python
from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
@ -69,21 +65,18 @@ def main():
if __name__ == '__main__':
main()
```
在上面的程序中我们通过Selenium实现对Chrome浏览器的操控如果要操控其他的浏览器可以创对应的浏览器对象例如Firefox、IE等。运行上面的程序如果看到如下所示的错误提示那是说明我们还没有将Chrome浏览器的驱动添加到PATH环境变量中也没有在程序中指定Chrome浏览器驱动所在的位置。
```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的[官方网站]()找到浏览器驱动的下载链接并下载需要的驱动在Linux或macOS系统下可以通过下面的命令来设置PATH环境变量Windows下配置环境变量也非常简单不清楚的可以自行了解。
```Shell
$ export PATH=$PATH:/Users/Hao/Downloads/Tools/chromedriver/
export PATH=$PATH:/Users/Hao/Downloads/Tools/chromedriver/
```
其中`/Users/Hao/Downloads/Tools/chromedriver/ `就是chromedriver所在的路径。

View File

@ -43,13 +43,11 @@ Scrapy的整个数据处理流程由Scrapy引擎进行控制通常的运转
```Shell
$
```
项目的目录结构如下图所示。
```Shell
(venv) $ tree
.
|____ scrapy.cfg
@ -78,7 +76,6 @@ $
1. 在items.py文件中定义字段这些字段用来保存数据方便后续的操作。
```Python
# -*- coding: utf-8 -*-
# Define here the models for your scraped items
@ -102,12 +99,10 @@ $
2. 在spiders文件夹中编写自己的爬虫。
```Shell
(venv) $ scrapy genspider movie movie.douban.com --template=crawl
```
```Python
# -*- coding: utf-8 -*-
import scrapy
from scrapy.selector import Selector
@ -136,28 +131,24 @@ $
item['classification']= sel.xpath('//span[@property="v:genre"]/text()').extract()
item['actor']= sel.xpath('//*[@id="info"]/span[3]/a[1]/text()').extract()
return item
```
> 说明上面我们通过Scrapy提供的爬虫模板创建了Spider其中的rules中的LinkExtractor对象会自动完成对新的链接的解析该对象中有一个名为extract_link的回调方法。Scrapy支持用XPath语法和CSS选择器进行数据解析对应的方法分别是xpath和css上面我们使用了XPath语法对页面进行解析如果不熟悉XPath语法可以看看后面的补充说明。
到这里,我们已经可以通过下面的命令让爬虫运转起来。
```Shell
(venv)$ scrapy crawl movie
```
可以在控制台看到爬取到的数据,如果想将这些数据保存到文件中,可以通过`-o`参数来指定文件名Scrapy支持我们将爬取到的数据导出成JSON、CSV、XML、pickle、marshal等格式。
```Shell
(venv)$ scrapy crawl moive -o result.json
```
3. 在pipelines.py中完成对数据进行持久化的操作。
```Python
# -*- coding: utf-8 -*-
# Define your item pipelines here
@ -211,7 +202,6 @@ $
4. 修改settings.py文件对项目进行配置。
```Python
# -*- coding: utf-8 -*-
# Scrapy settings for douban project
@ -325,7 +315,6 @@ $
XML文件。
```XML
<?xml version="1.0" encoding="UTF-8"?>
<bookstore>

View File

@ -0,0 +1,764 @@
## 项目部署上线指南
### 准备上线
1. 上线前的检查工作。
```Shell
python manage.py check --deploy
```
2. 将DEBUG设置为False并配置ALLOWED_HOSTS。
```Python
DEBUG = False
ALLOWED_HOSTS = ['*']
```
3. 安全相关的配置。
```Python
# 保持HTTPS连接的时间
SECURE_HSTS_SECONDS = 3600
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True
# 自动重定向到安全连接
SECURE_SSL_REDIRECT = True
# 避免浏览器自作聪明推断内容类型
SECURE_CONTENT_TYPE_NOSNIFF = True
# 避免跨站脚本攻击
SECURE_BROWSER_XSS_FILTER = True
# COOKIE只能通过HTTPS进行传输
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
# 防止点击劫持攻击手段 - 修改HTTP协议响应头
# 当前网站是不允许使用<iframe>标签进行加载的
X_FRAME_OPTIONS = 'DENY'
```
4. 敏感信息放到环境变量或文件中。
```Python
SECRET_KEY = os.environ['SECRET_KEY']
DB_USER = os.environ['DB_USER']
DB_PASS = os.environ['DB_PASS']
REDIS_AUTH = os.environ['REDIS_AUTH']
```
### 更新服务器Python环境到3.x
> 说明:如果需要清除之前的安装,就删除对应的文件和文件夹即可
1. 安装底层依赖库。
```Shell
yum -y install wget gcc zlib-devel bzip2-devel openssl-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel libpcap-devel xz-devel libffi-devel
```
2. 下载Python源代码。
```Shell
wget https://www.python.org/ftp/python/3.7.1/Python-3.7.1.tar.xz
```
3. 解压缩和解归档。
```Shell
xz -d Python-3.7.1.tar.xz
tar -xvf Python-3.7.1.tar
```
4. 执行配置生成Makefile构建文件
```Shell
cd Python-3.7.1
./configure --prefix=/usr/local/python37 --enable-optimizations
```
5. 构建和安装。
```Shell
make && make install
```
6. 配置PATH环境变量并激活。
```Shell
cd ~
vim .bash_profile
```
```INI
... 此处省略上面的代码...
export PATH=$PATH:/usr/local/python37/bin
... 此处省略下面的代码...
```
```Shell
source .bash_profile
```
7. 注册软链接(符号链接)- 这一步不是必须的。
```Shell
ln -s /usr/local/python37/bin/python3 /usr/bin/python3
ln -s /usr/local/python37/bin/pip3 /usr/bin/pip3
```
8. 测试Python环境是否更新成功。
```Shell
python3 --version
python --version
```
### 项目目录结构
假设项目文件夹为`project`,下面的四个子目录分别是:`conf`、`logs`、`src`和`venv`分别用来保存项目的配置文件、日志文件、源代码和虚拟环境。其中,`conf`目录下的子目录`cert`中保存了配置HTTPS需要使用的证书和密钥`src`目录下的项目代码可以通过版本控制工具从代码仓库中检出虚拟环境可以通过venv或其他工具进行创建。
```
project
├── conf
│   ├── cert
│   │   ├── 214915882850706.key
│   │   └── 214915882850706.pem
│   ├── nginx.conf
│   └── uwsgi.ini
├── logs
│   ├── access.log
│   ├── error.log
│   └── uwsgi.log
├── code
│   └── fangall
│   ├── api
│   ├── common
│   ├── fang
│   ├── rent
│   ├── user
│   ├── manage.py
│   ├── README.md
│   ├── static
│   └── templates
└── venv
├── bin
│   ├── activate
│   ├── activate.csh
│   ├── activate.fish
│   ├── celery
│   ├── celerybeat
│   ├── celeryd
│   ├── celeryd-multi
│   ├── coverage
│   ├── coverage3
│   ├── coverage-3.7
│   ├── django-admin
│   ├── django-admin.py
│   ├── easy_install
│   ├── easy_install-3.7
│   ├── pip
│   ├── pip3
│   ├── pip3.7
│   ├── __pycache__
│   ├── pyrsa-decrypt
│   ├── pyrsa-decrypt-bigfile
│   ├── pyrsa-encrypt
│   ├── pyrsa-encrypt-bigfile
│   ├── pyrsa-keygen
│   ├── pyrsa-priv2pub
│   ├── pyrsa-sign
│   ├── pyrsa-verify
│   ├── python -> python3
│   ├── python3 -> /usr/bin/python3
│   └── uwsgi
├── include
├── lib
│   └── python3.7
├── lib64 -> lib
├── pip-selfcheck.json
└── pyvenv.cfg
```
下面以阿里云为例,简单说明如何为项目注册域名、解析域名以及购买权威机构颁发的证书。
1. [注册域名](https://wanwang.aliyun.com/domain/)。
![](./res/aliyun-domain.png)
2. [域名备案](https://beian.aliyun.com/)。
![](./res/aliyun-keeprecord.png)
3. [域名解析](https://dns.console.aliyun.com/#/dns/domainList)。
![](./res/aliyun-dnslist.png)
![](./res/aliyun-resolve-settings.png)
4. [购买证书](https://www.aliyun.com/product/cas)。
![](./res/aliyun-certificate.png)
### uWSGI的配置
1. 在`project`目录下创建并激活虚拟环境。
```Shell
python3 -m venv venv
source venv/bin/activate
```
2. 安装项目依赖项。
```Shell
pip install -r requirements.txt
```
3. 通过pip安装uWSGI。
```Shell
pip install uwsgi
```
4. 修改uWSGI的配置文件`/root/project/conf/uwsgi.ini`)。
```INI
[uwsgi]
# 配置前导路径
base=/root/project
# 配置项目名称
name=fangtx
# 守护进程
master=true
# 进程个数
processes=4
# 虚拟环境
pythonhome=%(base)/venv
# 项目地址
chdir=%(base)/code/%(name)
# 指定python解释器
pythonpath=%(pythonhome)/bin/python
# 指定uwsgi文件
module=%(name).wsgi
# 通信的地址和端口(自己服务器的IP地址和端口)
socket=172.18.61.250:8000
# 日志文件地址
logto=%(base)/logs/uwsgi.log
```
> 说明可以先将“通信的地址和端口”项等号前面改为http来进行测试如果没有问题再改回成socket然后通过Nginx来实现项目的“动静分离”静态资源交给Nginx处理动态内容交给 uWSGI处理。按照下面的方式可以启动uWSGI服务器。
5. 启动服务器。
```Shell
uwsgi --ini conf/uwsgi.ini
```
### Nginx的配置
1. 安装Nginx。
```Shell
yum -y install nginx
```
2. 修改全局配置文件(`/etc/nginx/nginx.conf`)。
```Nginx
# 配置用户
user root;
# 工作进程数(建议跟CPU的核数量一致)
worker_processes auto;
# 错误日志
error_log /var/log/nginx/error.log;
# 进程文件
pid /run/nginx.pid;
# 包含其他的配置
include /usr/share/nginx/modules/*.conf;
# 工作模式(多路IO复用方式)和连接上限
events {
use epoll;
worker_connections 1024;
}
# HTTP服务器相关配置
http {
# 日志格式
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
# 访问日志
access_log /var/log/nginx/access.log main;
# 开启高效文件传输模式
sendfile on;
# 用sendfile传输文件时有利于改善性能
tcp_nopush on;
# 禁用Nagle来解决交互性问题
tcp_nodelay on;
# 客户端保持连接时间
keepalive_timeout 30;
types_hash_max_size 2048;
# 包含MIME类型的配置
include /etc/nginx/mime.types;
# 默认使用二进制流格式
default_type application/octet-stream;
# 包含其他配置文件
include /etc/nginx/conf.d/*.conf;
# 包含项目的Nginx配置文件
include /root/project/conf/*.conf;
}
```
3. 编辑局部配置文件(`/root/project/conf/nginx.conf`)。
```Nginx
server {
listen 80;
server_name _;
access_log /root/project/logs/access.log;
error_log /root/project/logs/error.log;
location / {
include uwsgi_params;
uwsgi_pass 172.18.61.250:8000;
}
location /static/ {
alias /root/project/static/;
expires 30d;
}
}
server {
listen 443;
server_name _;
ssl on;
access_log /root/project/logs/access.log;
error_log /root/project/logs/error.log;
ssl_certificate /root/project/conf/cert/214915882850706.pem;
ssl_certificate_key /root/project/conf/cert/214915882850706.key;
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
location / {
include uwsgi_params;
uwsgi_pass 172.18.61.250:8000;
}
location /static/ {
alias /root/project/static/;
expires 30d;
}
}
```
到此为止我们可以启动Nginx来访问我们的应用程序HTTP和HTTPS都是没有问题的如果Nginx已经运行在修改配置文件后我们可以用下面的命令重新启动Nginx。
4. 重启Nginx服务器。
```Shell
nginx -s reload
```
```Shell
systemctl restart nginx
```
> 说明可以对Django项目使用`python manage.py collectstatic`命令将静态资源收集到指定目录下,要做到这点只需要在项目的配置文件`settings.py`中添加`STATIC_ROOT`配置即可。
#### 负载均衡配置
下面的配置中我们使用Nginx实现负载均衡为另外的三个Nginx服务器通过Docker创建提供反向代理服务。
```Shell
docker run -d -p 801:80 --name nginx1 nginx:latest
docker run -d -p 802:80 --name nginx2 nginx:latest
docker run -d -p 803:80 --name nginx3 nginx:latest
```
```Nginx
user root;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
# 为HTTP服务配置负载均衡
http {
upstream fangtx {
server 172.18.61.250:801 weight=4;
server 172.18.61.250:802 weight=2;
server 172.18.61.250:803 weight=2;
}
server {
listen 80 default_server;
listen [::]:80 default_server;
listen 443 ssl;
listen [::]:443 ssl;
ssl on;
access_log /root/project/logs/access.log;
error_log /root/project/logs/error.log;
ssl_certificate /root/project/conf/cert/214915882850706.pem;
ssl_certificate_key /root/project/conf/cert/214915882850706.key;
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_buffering off;
proxy_pass http://fangtx;
}
}
}
```
> 说明Nginx在配置负载均衡时默认使用WRR加权轮询算法除此之外还支持ip_hash、fair需要安装upstream_fair模块和url_hash算法。此外在配置upstream模块时可以指定服务器的状态值包括backup备份机器其他服务器不可用时才将请求分配到该机器、down、fail_timeout请求失败达到max_fails后的暂停服务时间、max_fails允许请求失败的次数和weight轮询的权重
### Keepalived
当使用Nginx进行负载均衡配置时要考虑负载均衡服务器宕机的情况。为此可以使用Keepalived来实现负载均衡主机和备机的热切换从而保证系统的高可用性。Keepalived的配置还是比较复杂通常由专门做运维的人进行配置一个基本的配置可以参照[《Keepalived的配置和使用》](https://www.jianshu.com/p/dd93bc6d45f5)。
### MySQL主从复制
下面还是基于Docker来演示如何配置MySQL主从复制。我们事先准备好MySQL的配置文件以及保存MySQL数据和运行日志的目录然后通过Docker的数据卷映射来指定容器的配置、数据和日志文件的位置。
```Shell
root
└── mysql
├── conf
│   ├── master
│   │   └── mysqld.cnf
│   ├── slave1
│   │   └── mysqld.cnf
│   ├── slave2
│   │   └── mysqld.cnf
│   └── slave3
│   └── mysqld.cnf
└── data
├── master
├── slave1
├── slave2
└── slave3
```
1. MySQL的配置文件master和slave的配置文件需要不同的server-id
```
[mysqld]
pid-file=/var/run/mysqld/mysqld.pid
socket=/var/run/mysqld/mysqld.sock
datadir=/var/lib/mysql
log-error=/var/log/mysql/error.log
server-id=1
log_bin=/var/log/mysql/mysql-bin.log
expire_logs_days=30
max_binlog_size=256M
symbolic-links=0
```
2. 创建和配置master。
```Shell
docker run -d -p 3306:3306 --name mysql57 \
-v /root/mysql/conf/master:/etc/mysql/mysql.conf.d \
-v /root/mysql/data/master:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
docker exec -it mysql57 /bin/bash
```
```Shell
mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.7.23-log MySQL Community Server (GPL)
Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> grant replication slave on *.* to 'slave'@'%' identified by 'iamslave';
Query OK, 0 rows affected, 1 warning (0.00 sec)
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 | 590 | | | |
+------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
mysql> quit
Bye
exit
```
上面创建Docker容器时使用的`-v`参数(`--volume`)表示映射数据卷,冒号前是宿主机的目录,冒号后是容器中的目录,这样相当于将宿主机中的目录挂载到了容器中。
3. 创建和配置slave。
```Shell
docker run -d -p 3307:3306 --name mysql57-slave-1 \
-v /root/mysql/conf/slave1:/etc/mysql/mysql.conf.d \
-v /root/mysql/data/slave1:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=123456 \
--link mysql57:mysql57 mysql:5.7
docker exec -it mysql57-slave-1 /bin/bash
```
```Shell
mysql -u root -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.23-log MySQL Community Server (GPL)
Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> reset slave;
Query OK, 0 rows affected (0.02 sec)
mysql> change master to master_host='mysql57', master_user='slave', master_password='iamslave', master_log_file='mysql-bin.000003', master_log_pos=590;
Query OK, 0 rows affected, 2 warnings (0.03 sec)
mysql> start slave;
Query OK, 0 rows affected (0.01 sec)
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: mysql57
Master_User: slave
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 590
Relay_Log_File: f352f05eb9d0-relay-bin.000002
Relay_Log_Pos: 320
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 590
Relay_Log_Space: 534
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 1
Master_UUID: 30c38043-ada1-11e8-8fa1-0242ac110002
Master_Info_File: /var/lib/mysql/master.info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set:
Executed_Gtid_Set:
Auto_Position: 0
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
1 row in set (0.00 sec)
mysql> quit
Bye
exit
```
接下来可以如法炮制配置出slave2和slave3这样就可以搭建起一个“一主带三从”的主从复制环境。上面创建创建容器时使用的`--link`参数用来配置容器在网络上的主机名(网络地址别名),下一节有这个知识点的介绍。
### Docker
事实上项目上线中最为麻烦的事情就是配置软件运行环境环境的差异会给软件的安装和部署带来诸多的麻烦而Docker正好可以解决这个问题。关于Docker在之前的文档中我们已经介绍过了接下来我们对Docker的知识做一些必要的补充。
1. 创建镜像文件。
将容器保存成镜像:
```Shell
docker commit -m "..." -a "..." <container-name> jackfrued/<image-name>
```
使用Dockerfile构建镜像
```Dockerfile
# 指定基础镜像文件
FROM centos:latest
# 指定维护者信息
MAINTAINER jackfrued
# 执行命令
RUN yum -y install gcc
RUN cd ~
RUN mkdir -p project/code
RUN mkdir -p project/logs
# 拷贝文件
COPY ...
# 暴露端口
EXPOSE ...
# 在容器启动时执行命令
CMD ~/init.sh
```
```Shell
docker build -t jackfrued/<image-name> .
```
2. 镜像的导入和导出。
```Shell
docker save -o <file-name>.tar <image-name>:<version>
docker load -i <file-name>.tar
```
3. 推送到DockerHub服务器。
```Shell
docker tag <image-name>:<version> jackfrued/<name>
docker login
docker push jackfrued/<name>
```
4. 容器之间的通信。
```Shell
docker run --link <container-name>:<alias-name>
```
如果我们能够在Docker中完成项目的部署并且将整个部署好的容器打包成镜像文件进行分发和安装这样就可以解决项目在多个节点上进行部署时可能遇到的麻烦而且整个部署可以在很短的时间内完成。
### Supervisor
[Supervisor](https://github.com/Supervisor/supervisor)是一个用Python写的进程管理工具可以很方便的用来在类Unix系统下启动、重启自动重启程序和关闭进程。
1. 安装Supervisor。
```Shell
yum -y install supervisor
```
2. 查看Supervisor的配置文件。
```Shell
vim /etc/supervisord.conf
```
```INI
; 此处省略上面的代码
; The [include] section can just contain the "files" setting. This
; setting can list multiple files (separated by whitespace or
; newlines). It can also contain wildcards. The filenames are
; interpreted as relative to this file. Included files *cannot*
; include files themselves.
[include]
files = supervisord.d/*.ini
```
可以看出自定义的管理配置代码可以放在`/etc/supervisord.d`目录中,并且文件名以`ini`作为后缀即可。
3. 编写管理配置代码。
```Shell
cd /etc/supervisord.d
vim fangtx.ini
```
```INI
```
4. 启动Supervisor服务和查看状态。
```Shell
systemctl start supervisord
supervisorctl status
```
### 其他服务
1. 常用开源软件。
| 功能 | 开源方案 |
| ------------------- | ------------------------- |
| 版本控制工具 | Git、Mercurial、SVN |
| 缺陷管理 | Redmine、Mantis |
| 负载均衡 | Nginx、LVS、HAProxy |
| 邮件服务 | Postfix、Sendmail |
| HTTP服务 | Nginx、Apache |
| 消息队列 | RabbitMQ、ZeroMQ、Redis |
| 文件系统 | FastDFS |
| 基于位置服务LBS | MongoDB、Redis |
| 监控服务 | Nagios、Zabbix |
| 关系型数据库 | MySQL、PostgreSQL |
| 非关系型数据库 | MongoDB、Redis、Cassandra |
| 搜索引擎 | ElasticSearch、Solr |
| 缓存服务 | Mamcached、Redis |
2. 常用云服务。
| 功能 | 可用的云服务 |
| -------------- | --------------------------------------- |
| 团队协作工具 | Teambition、钉钉 |
| 代码托管平台 | Github、Gitee、CODING |
| 邮件服务 | SendCloud |
| 云存储CDN | 七牛、OSS、LeanCloud、Bmob、又拍云、AWS |
| 移动端推送 | 极光、友盟、百度 |
| 即时通信 | 环信、融云 |
| 短信服务 | 云片、极光、Luosimao、又拍云 |
| 第三方登录 | 友盟、ShareSDK |
| 网站监控和统计 | 阿里云监控、监控宝、百度云观测、小鸟云 |

View File

@ -145,19 +145,26 @@
- 使用进程 - fork函数 / multiprocessing模块 / 进程池 / 进程间通信
- 使用线程 - thread模块 / threading模块 / Thread类 / Lock类
#### Day14 - [网络编程入门](./Day01-15/Day14/网络编程入门.md)
#### Day14-A - [网络编程入门](./Day01-15/Day14/网络编程入门.md)
- 计算机网络基础 - 计算机网络发展史 / “TCP-IP”模型 / IP地址 / 端口 / 协议 / 其他相关概念
- 网络应用架构 - “客户端-服务器”架构 / “浏览器-服务器”架构
- Python网络编程 - 套接字的概念 / socket模块 / socket函数 / 创建TCP服务器 / 创建TCP客户端 / 创建UDP服务器 / 创建UDP客户端 / SocketServer模块
#### Day15 - [网络应用开发](./Day01-15/Day15/网络应用开发.md)
#### Day14-B - [网络应用开发](./Day01-15/Day15/网络应用开发.md)
- 访问网络API - 网络API概述 / 访问URL / requests模块 / 解析JSON格式数据
- 文件传输 - FTP协议 / ftplib模块 / 交互式FTP应用
- 电子邮件 - SMTP协议 / POP3协议 / IMAP协议 / smtplib模块 / poplib模块 / imaplib模块
- 短信服务 - twilio模块 / 国内的短信服务
#### Day15 - 图像和文档处理
- 用Pillow处理图片
- 读写Word文档
- 读写Excel文件
- 生成PDF文件
### Day16~Day20 - [Python语言进阶 ](./Day16-20/Python语言进阶.md)
- 常用数据结构

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 158 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 MiB

View File

@ -1,4 +1,4 @@
## 玩转PyCharm(上)
## 玩转PyCharm
PyCharm是由JetBrains公司开发的提供给Python专业的开发者的一个集成开发环境它最大的优点是能够大大提升Python开发者的工作效率为开发者集成了很多用起来非常顺手的功能包括代码调试、高亮语法、代码跳转、智能提示、自动补全、单元测试、版本控制等等。此外PyCharm还提供了对一些高级功能的支持包括支持基于Django框架的Web开发、。