赞
踩
web就是基于B/S模式的应用程序 - 网页
WEB的典型的应用:
B/S : Browser / Server 浏览器与服务器交互模式
C/S : Client / Server 客户端与服务器交互模式
服务器 : 处理用户的请求(request)和响应(response)->提供数据支持
# 服务器的组成: 服务器,浏览器 和 通信协议组成
浏览器 : 代替用户向服务器发请求,解析数据->代替用户向服务器发送请求(User Agent)
通信协议 : 规范数据传输及打包的方式. - http
http : Hyper Text transfer protocal 超文本传输协议
1. 提供数据支持
2. 接收请求并响应
3. 提供数据安全功能
4. 产品 :
5. Apache
6. Tomcat
7. IIS - Internet Information Service
8. Nginx ...
9. 开发语言:
10. Java
11. PHP
12. ASP.net
13. Python (Django, flask...)
1. 代替用户向服务器发送请求 接收响应数据并解析,以图形化界面展示给用户
2. 产品(主流) :
1. Chrome - Google产品
2. Safari - Apple产品
3. IE - 微软产品
4. Firefox - Mozilla 产品
5. Opera - Opera产品 划分依据 :
6. 市场份额(决定每年排名)
7. 浏览器引擎(内核)不同
渲染引擎:解析页面,控制渲染结果
JS引擎:解析脚本
1. 技术 : 前端开发 - 制作网页
HTML : 写页面结构
CSS : 写样式
JS : 写逻辑,实现用户交互
框架 : VUE Angular Node.js
1. HyperText Markup Language
超文本 标记 语言
作用 : 通过标签的形式书写页面结构并且填充内容
1. 超文本:具备特殊功能的文本就是超文本
普通文本 a :普通字符a
超文本 a :表示的是超链接功能
普通文本 b :普通字符b
超文本 b :表示文字加粗功能
2. 标记:超文本的组成形式
普通文本 a : a
超文本 a : <a></a>
3. 语言:语言有自己的语法规范
2. W3C:World Wide Web Consortium 万维网联盟
也叫标签或元素,标记页面结构和内容,配合CSS实现页面整体布局和美化
以<>为标志
在计算机中以.html 或 .htm 后缀标识
网页文件的打开工具 - 浏览器
开发工具 : 记事本, sublime,VSCode,editPlus,WebStorm,Hbuilder...
调试工具 : 浏览器自带开发者工具,使用右键-'检查'打开,或者F12打开
1. 所有的标签都以<>为标志,区分普通文本
2. 标签分类:
1. 双标签 : 成对出现,有开始,有结束 语法 : <标签名> 标签内容(文本或其他标签) </标签名>
2. 单标签 : 只有开始,没有结束,本身代表一定的意义或功能
语法 :
<标签名>
或
<标签名/>
3. 标签嵌套
在双标签中嵌套添加其他标签
4. 文档结构
1. 网页文件以.html / .htm为后缀
2. 添加双标签<html></html>
3. 在<html>标签中嵌套一对<head></head>,嵌套<body></body>标签
5. 标签属性
主要用来修饰当前你标签的显示效果,或者为元素及网页本身添加额外补充信息
语法 :
<开始标签 属性名=属性值 属性名=值>
注意 :
1. 标签属性必须写在开始标签中
2. 属性值必须使用引号引起来,单双引号都可以
3. 多组属性之间使用空格隔开
6. HTML语法规范
1. 标签名不区分大小写,建议统一使用小写
2. 标签名不报错,如果缺少闭合标签,浏览器会自动添加闭合;
标签名书写错误,不报错,只是丧失原有标签的效果及功能
<meta>
<label>
<table>
3. 注释 :
<!-- 注释内容 -->
注意 :
注释不能嵌套
<body <!-- -->> 错误
<!-- <!-- --> --> 错误
4. 代码中适当添加注释与缩进,提高可阅读性
1. HTML5 提供的文档类型声明,以便浏览器能正确解析网页中的标签,并且采用标准方式渲染页面
2. <html></html>
表示网页文档的开始和结束
3. <head></head>嵌套在html标签中,表示网页的头部,可以书写网页标题,字符集,外部资源的引入,网页相关介绍,网
页选项卡图标
4. <body></body>表示网页的主体,也是浏览器窗口显示区域
一切有关页面的内容都写在body中
网页头部:<head></head>中可以嵌套其它标签,设置标题,选项卡图标,字符集等信息
1. 标题
<title>百度一下,你就知道</title>
2. 字符集
<meta charset="utf-8">
3. 选项卡小图标
<link rel="shortcut icon" href="图片路径" type="image/x-icon">
图片后缀 .ico
<link>标签用于引入外部资源
标签属性 :
rel 设置资源类型
href 设置资源路径
type 声明文件类型和后缀
1. 文本标签
1. 标题标签 n表示数字,取值1~6,总共六级标题.标题中的文本自带加粗效果,并且一级到六级,字号逐级
减小
2. 段落标签
2. 普通文本标签
给一段文本中的某一部分额外添加样式或者动态操作使用的标签
1. 行分区
<span></span>
常与段落或者标题结合使用,为内容设置额外样式
2. <label></label>
在表单中使用,优化用户操作
3. 格式标签
加粗 : <b></b>或<strong></strong> H5推荐使用更有语义的标签
斜体 : <i></i>
删除线 : <s></s>
下划线 : <u></u>
上标 : <sup></sup>
下标 : <sub></sub>
4. 空格与换行
开发过程中出于代码整理造成的空格和换行.在浏览器解析时,统统理解为一个空格
换行标签 : 可以使用<br/>或<br>实现换行
5. 水平线标签 : <hr/>
6. 字符实体
由于HTML是标签语法,所以在某些情况下,特殊字符无法正常显示
例:
<day01> 标签语法
如果内容为<day01>,浏览器会认为是HTML标签
3. < : <
4. > : >
5. 空格 :
6. 版权符号 : ©
7. 人民币符号 : &
1. 列表是一种结构化标签,按照从上到下依次显示数据,每一条数据称为一个列表项,不同类型的列表,项目符
号不同
2. 分类 :
1. 有序列表(ordered list) 默认按照阿拉伯数字从1开始排列
语法 :
1. List Item
2. 列表项
2. 无序列表(unordered list)
语法 :
列表项
默认以实心原点标识列表项
练习 :
新建文件,在body中添加列表
无序列表显示四大名著
有序列表列出四种编程语言
1. 有序列表 - ol
1. type 设置项目符号的类型,默认以阿拉伯数字标识
可取 :
1 默认项目符号
a 按照小写字母排序
A 按照大写字母排列
i 按照希腊数字排列
I 大写希腊数字排列
2. start 设置项目符号使用第几个字符开始标识
取值 : 无单位的数值,跟项目符号类型无关
2. 无序列表 - ul type :
设置项目符号的类型
取值 :
disc 默认实心原点
circle 空心圆
square 实心方块
none 取消项目符号
在列表中嵌套使用另外一个列表实现多级结构
语法 :
<ul>
<li>
Desktop
<ul>
<li>Python-web</li>
</ul>
</li>
<li>C盘</li>
</ul>
<ul>
<li>Desktop</li>
<ul>
<li>Python-web</li>
</ul>
<li>C盘</li>
</ul>
练习 :
使用列表显示四大名著,
每本名著下显示三个主要人物
建议 :
下拉菜单使用嵌套列表实现,建议采用父子关系嵌套
1.出现标签嵌套时,外层标签称为父元素,内层标签称为子元素
2.多级嵌套时,外层标签称为祖先元素,内层所有标签都可以称为后代元素
3.平级的子元素之间称为兄弟关系,元素称为兄弟元素
例 :
<html>
undefined
<head>
<title></title>
</head>
<body>
<h1>
<span></span>
</h1>
</body>
</html>
1. 路径 (URL)
1. URL :
统一资源定位符 Uniform Resource Locator 表示资源文件所在的位置
2. 组成 :
协议 域名 文件目录 文件名
例 :
http://www.baidu.com
https://ss0.bdstatic.com/community/010cf65652fd876ac7251c94c524cf.jpg
file:///C:/Users/Python/Desktop/Web/day1/03-list.html
3. 分类 :
1. 绝对路径
从根目录开始查找文件
Windows操作系统上,根目录以盘符为标志
其他操作系统,根目录使用/表示
2. 相对路径
从当前所在目录(文件夹)开始查找资源文件
可以使用../表示回退上一级目录
./表示当前目录文件夹
et :
03-list.html
注意 :
1. 网络URL中不能出现中文
文件及文件夹名称中禁止出现中文
2. URL严格区分大小写
2. 图片标签(img)
作用: 在网页中插入一张图片
语法 :
<img src="资源路径">
标签属性 :
1. src : 设置图片URL(必填)
作用 : 在网页中插入一张图片
语法 : <img src="">
属性 :
1. src : 设置图片URL,必填属性
2. width : 设置图片宽度,取像素值
3. height : 设置图片高度,取像素值
注 : 默认情况下,图片会按照原始尺寸显示在网页中,宽高属性可以只写一个,另外一个方向会自动等比缩放
4. title : 设置图片标题,鼠标悬停于图片时显示标题文本
5. alt : 设置图片加载失败时的提示文本
1. 作用 : 实现资源文件的跳转
2. 语法 :
<a href="链接地址"></a>
3. 属性 :
1. href : 设置资源文件的地址,必填
如果省略,超链接文本跟普通文本无差别
2. target : 设置目标文件是否在当前窗口打开,默认值为 _self 表示在当前窗口打开新文件.可取 _blank 表示
新建窗口打开文件
4. 默认样式
超链接自带两种状态:
访问前 蓝色文本色,自带下划线
访问后 紫色文本色,自带下划线
5. 锚点链接
作用 : 链接到指定文件的指定位置
语法 :
1. 定义锚点
<a name="1"></a>
空标签添加name属性定义锚点名称
2. 指定超链接的链接地址
<a href="#1">1. 人物介绍</a>
链接地址中使用#代表当前页面,后面跟上锚点名称,指定位置
6. 链接地址为空时的语法:
1. href="" 跳转至当前页,包含刷新
2. href="#" 跳转到当前页,没有刷新,会在当前url末尾添加上#
3. href="javascript:void(0);"
跳转至当前页,类似于href="",但是不会刷新页面
作用 : 在网页中插入一张图片
语法 : <img src="">
属性 :
1. src : 设置图片URL,必填属性
2. width : 设置图片宽度,取像素值
3. height : 设置图片高度,取像素值
注 : 默认情况下,图片会按照原始尺寸显示在网页中,宽高属性可以只写一个,另外一个方向会自动等比缩放
4. title : 设置图片标题,鼠标悬停于图片时显示标题文本
5. alt : 设置图片加载失败时的提示文本
1. 表格标签
2. 表格中嵌套行标签
tr : table row
3. 行中嵌套单元格标签<td></td>
td : table data
1. table 属性
1. border : 为表格添加边框,取像素值
2. bgcolor : 设置表格背景颜色,取颜色的英文单词
3. align : 设置表格在父元素中的水平位置,取值 : left/center/right
4. width : 设置表格宽度,取像素值
5. height : 设置表格高度,取像素值 注 : 表格的默认尺寸由内容决定,手动设置宽高之后,会根据单元格
内容的多少自动分配行和列的尺寸
6. cellspacing : 设置表格边框与边框之间的距离,取像素值
7. cellpadding : 设置单元格内容与边框之间的距离
8. tr 属性
9. bgcolor : 设置当前行的背景颜色
10. align : 设置当前行内容的水平对齐方式,默认居左,可取值left/center/right
11. valign : 设置当前行内容 的垂直对齐方式,默认垂直居中,可取值 top/middle/bottom
12. td 属性
13. bgcolor : 为单元格设置背景颜色
14. align : 设置当前单元格内容的水平对齐方式
15. valign : 设置单元格内容的垂直对齐方式
16. width/height : 设置单元格的宽高尺寸
1. 合并属性是单元格td独有的属性
2. 属性 :
colspan : collum-span 跨列合并
横向合并单元格,取值为无单位的数值,表示包含当前单元格在内,合并几个单元格
例:
colspan="3"
rowspan : 跨行合并,取无单位的数值,表示合并几个单元格
3. 注意 :
不管是跨行还是跨列,都涉及表格结构调整,需要手动删除多余的单元格
跨列合并 : 删除当前行中多余的单元格
跨行合并 : 删除后面行中对应的单元格
1.表头行分组
2. <tfoot></tfoot>
表尾行分组
3. <tbody></tbody>
表格主体,行分组标签可以省略不写,默认情况下,所有的行都自动加入tbody中
用法与td一致,表示单元格,自带文本加粗和居中效果,常用于表头
表单用于收集用户信息,并将数据发送给服务器
1. form 表单元素
2. 表单控件(输入框,按钮,文件选择...)
<form>
表单控件
</form>
1. action : 指定数据的提交地址
2. method : 指定数据的提交方式
默认为get,可取get/post
1. get 请求 :
1. 将数据以参数形式拼接在URL后面,明文传输
例 :
baidu.com?name=zhangsan&passwd=123456
2. 安全性较低
3. 数据大小有限制,不超过2Kb
2. post请求
1. 数据会被打包,以请求体的方式传输,外界不可见
2. 隐式传输,安全性较高
3. 没有大小限制
3. enctype : encode-type
指定数据发往服务器时的编码类型
取值 :
1. application/x-www-form-urlencoded
默认的编码方式,会将表单中的数据转换成一个字符串,附加到URL后面(get方式提交数据),请求新的URL
2. multipart/form-data
专门用来上传特殊数据类型,比如图片,文件等,通过二进制形式将数据发送至服务器,要求必须指定数据以post
方式提交
1. 提供与用户交互的可视化组件
2. 分类
1. 文本框和密码框
语法 :
<input type="text">
<input type="password">
属性 :
1. name : 定义控件名称,必填,缺少的话无法提交数据
2. value : 设置控件的值,文本框与密码框的值更常见使用JS动态操作
3. maxlength : 设置输入框最大字符数,取无单位数值
4. placeholder : 用户输入之前显示的提示文本
5. autocomplete : 文本框的自动提示功能,取值on/off
2. 单选钮和复选框
单选:<input type="radio">
复选:<input type="checkbox">
属性 :
1. name : 控件名称,必填
2. value: 控件的值,必填,代表按钮的含义,最终将发送给服务器
3. checked : 设置按钮的选中状态,直接使用属性名,省略属性值
注意 :一组按钮的name属性值必须保持一致
特殊用法 : label for id
将文本与按钮绑定在一起,点文本与点按钮一致
语法 :
<label for="male">
<input id="male">
3. 隐藏域和文件选择框
1. 隐藏域 : 对用户不可见,某些服务器需要,但是不需要告知用户的数据,例如用户id,都可以使用隐藏域设置
<input type="hidden" name="uid" value="001">
2. 文件选择框 :
<input type="file" name="uImg">
注 :二进制数据传输时, 必须使用post提交,必须指定enctype
4. 下拉菜单
语法 :
<select name="address">
<option value="beijing"></option>
</select>
5. 多行文本域
语法 :
<textarea name='uinfo'></textarea>
特点 : 支持多行输入,支持用户手动调整尺寸
6. 按钮控件
1. 提交按钮 : 当用户点击时,会将表单中的数据按照指定的方式发送给后台
<input type="submit" value="">
属性value用于设置按钮的显示文本
2. 重置按钮 : 将表单中的数据恢复到初始化状态
<input type="reset" value="">
3. 普通按钮 : 需要自行绑定JS事件
<input type="button" value="">
注 : 提交和重置按钮自带显示文本,普通按钮没有默认显示文本,需要单独指定
4. <button></button>标签
也可以表示按钮,标签内容就是按钮显示文本
注意 :
1. form表单外使用button标签,就是普通按钮
2. form表单内部使用<button>标签,等价于<input type="submit">,具有提交功能
Cascading Style Sheet 层叠样式表,修饰和美化页面元素,实现页面的排版和布局.
1. CSS使用方式
2. 行内样式/内联样式
语法 : 通过标签属性style,为元素设置CSS样式
注 : CSS样式声明是由CSS的属性和值组成的
例 :
<h1 style="CSS属性名:值;"></h1>
常用CSS属性 :
1. 文本颜色 color 取颜色值(英文单词)
2. 背景颜色 background-color 取颜色值
3. 字体大小 font-size 取像素值
语法 : 使用<style></style>标签引入CSS代码,实现样式与结构的分离
例 :
<style>
CSS选择器{
属性:值;
属性:值;
}
</style>
<h1></h1>
<p></p>
注 :
1. CSS选择器主要用来匹配页面中的元素为其设置样式
2. <style></style>标签可以书写在文档的任意位置,书写任意次,一般遵循"样式优先"的原则
1. 在HTML文件中使用外部的样式表文件,CSS文件以.css为后缀,文件中直接使用选择器书写样式,在HTML中使用标签引入
2. 外链方式真正实现结构与样式的分离,实现样式的复用
不同的样式在同一个元素上共同起作用
CSS某些样式可以被子元素或后代元素继承
例 : 大部分的文本样式;
块元素默认与父元素宽度保持一致
元素发生样式冲突时最终选用哪一种样式,由样式表的优先级决定
1. 行内样式优先级最高 (style属性定义的样式)
2. 文档内嵌和外链样式优先级低于行内样式,发生样式冲突时,考虑代码的书写顺序,后来者居上.
3. 浏览器默认样式优先级最低 (user agent style)
选择页面中哪些元素应用样式
1. 标签选择器/元素选择器
1. 作用 : 根据指定的标签名匹配文档中所有的该元素
2. 语法 : 标签名 { 属性:值; 属性:值; }
练习 :
创建文件,添加超链接标签
设置超链接文本色为红色,取消下划线 text-decoration:none;
2. id 选择器
1. 作用 : 根据标签的id属性值选择元素
2. id属性具有唯一性,不能重复
3. id属性值命名规范 : 自定义,尽量见名知意; 可以由数字,字母,下划线 ,-组成,禁止以数字开头
4. 语法 :
id选择器以#开头,后跟id属性值,用于匹配文档中唯一的元素
例 :
#id属性值 { 样式声明 } <标签 id="">
练习
创建文件 id-selector.html
添加div标签,文本内容不限
设置div 200*200 尺寸,背景色自选
width:200px; height:200px;
3. class选择器/类选择器
1. 作用 : 根据标签的class属性值匹配元素
2. 特点 : 类选择器定义的样式可以实现复用,类名可在多个元素中重复使用,命名规范参照id属性值
3. 语法 : 类选择器以英文.开头,后跟class属性值
例 :
.c1{
color:red;
font-size:32px;
}
练习
创建class-selector.html
添加标签 p span div
通过类选择器为元素统一设置样式 200*200 文
本色 背景色 字体大小
4. 特殊用法
5. 标签选择器与类选择器组合使用,注意标签名在前,类名在后
例 :
div.c1{
}
匹配类名为c1的div元素 或 : .c1.c2 类选择器的组合使用
4. 群组选择器
1. 作用 : 为一组元素统一设置样式
2. 语法 :
选择器1,选择器2,选择器3...{
}
3. 练习 :
创建div h1 p标签
通过群组选择器,统一设置字体大小,文本颜色,自定义尺寸
div,h1,p{
font-size:32px;
color:red;
width:200px;
height:200px;
}
5. 后代选择器
1. 语法 :
选择器1 选择器2{
}
2. 作用 : 在选择器1对应的元素下,查找所有满足选择器2的后代元素
6. 子代选择器
1. 语法 :
选择器1>选择器2{
}
2. 查找直接子元素
7. 伪类选择器
1. 作用 :针对元素的不同状态设置样式
2. 分类 :
1. 超链接伪类选择器
针对超链接访问前和访问后两种状态分别设置样式 访问前 :link 访问后 :visited
2. 动态伪类选择器
:hover 表示鼠标滑过/悬停时的状态
:active 表示激活(鼠标点按不抬起)状态
:focus 文本输入框获取焦点时的状态(编辑状态)
3. 使用 : 伪类选择器必须与其他选择器结合使用,表示某种状态
例 :
a:link{
}
#d1:hover{
}
4. 如果需要为超链接添加四种状态的样式, 需要固定书写顺序: LoVe/HAte
爱恨原则 :link :visited :hover :active
在使用选择器为元素设置样式,发生冲突时,最终选用哪一个选择器的样式,取决于选择器的权重
权重:权值,使用数字来标明选择器的优先级,数字越大,优先级越高
权重:
选择器 | 权重 |
---|---|
标签选择器 | 1 |
类选择器 | 10 |
id选择器 | 100 |
行内 | 1000 |
注 :
1. 组合选择器(后代,子代,伪类),权重为各个选择器权值之和
2. 群组选择器权重不累加,单独看每个选择器的权重
练习 :
创建div id为nav,表示导航栏
div中嵌套若干a标签,表示导航项
div : 宽高,背景色
a : 取消下划线,修改默认颜色
鼠标悬停修改a标签的文本色和背景色
独占一行,不与其他元素共行;可以设置宽高
例 : div p h1 table ul ol form li
注 : 除table外,所有块元素默认宽度与父元素保持一致,高度由内容决定
可以与其他元素共行显示,不能手动调整宽高
例 : a span label i b strong u s sub sup
既可以共行显示,又可以设置宽高
例 : img input button
注 :
行内块元素是特殊的行内元素,默认垂直方向上,以文本底部对齐显示(基线对齐).
可以通过属性 vertical-align 调整行内元素的垂直对齐方式,常用于调整行内块元素垂直对齐问题
取值 : top / middle / bottom / baseline(默认值)
复习:
引入方式
style属性书写行内样式
使用 <style></style>
标签书写样式
外链文件,使用 <link rel="stylesheet" href="">
引入方式之间的优先级
行内 > 外链/内嵌(代码书写顺序)
1. 标签选择器 div{}
2. id选择器 #id{}
3. class选择器 .className{}
4. 伪类选择器 a:link{}
5. 群组选择器 div,h1{}
6. 后代选择器 div span{}
7. 子代选择器 div>span{} div中的直接子元素span
选择器 | 权重 |
---|---|
标签选择器 | 1 |
类选择器 | 10 |
id选择器 | 100 |
行内 | 1000 |
组合选择器 | 后代或子代选择器,权重为各个选择器权值之和 |
例 :
span{
color:red;
}
#box span{}
.c1 span{}
HTML 标签类型
块元素
块元素: 独占一行,手动设置宽高块元素默认与父元素宽度保持一致
例 :
<body>
<div style="width:200px;">
<h1></h1>
</div>
</body>
元素 : body div h1 p ul ol table form li
行内元素 :可以共行显示,不能手动调整宽高
常见 : a b strong span label i s u sub sup
行内块 : 既可以共行,也可以设置宽高
常见: img button input
属性: vertical-align
取值: top/middle/bottom
作用: 调整行内块元素的垂直对齐方式
color
background-color
font-size
text-decoration
width
height
vertical-align
px : 浏览器默认单位,表示像素
% : 百分比单位参照父元素对应尺寸计算
em : 默认1em等于字体大小 16px
rem :参照文档根元素的字体大小进行尺寸设置
1. 英文单词
2. rgb(r,g,b) 采用三原色设置颜色,取值范围 0 ~ 255
特殊值 :
rgb(255,0,0) red
rgb(0,255,0) green
rgb(0,0,255) blue
rgb(0,0,0) black
rgb(255,255,255) white
3. rgba(r,g,b,a) a表示alpha透明度,取值0-1
0表示透明,1表示不透明,小数为半透明
例 :
rgba(255,0,0,.55)
4. 十六进制表示颜色
1. 语法 : 以#开头表示十六进制,可以使用6位字符或三位字符表示颜色,每位字符取值0-9,a-f
2. 六位十六进制: 每两位为一组,代表一种三原色
特殊值 :
rgb(255,0,0) red #ff0000
rgb(0,255,0) green #00ff00
rgb(0,0,255) blue #0000ff
rgb(0,0,0) black
rgb(255,255,255) white
计算 :
ff :
15 * 16 (0) + 15 * 16 (1)
2. 短十六进制 三位字符表示
浏览器会自动对每一位重复扩充,最终完成6位十六进制
#000 -> #000000
#fff -> #ffffff
1. 尺寸属性 :
width/height : 取像素值或%
2. 内容溢出 :
元素内容超过元素自身的尺寸,称为溢出,默认溢出部分可见
属性 : overflow
取值 :
visible (默认溢出部分可见)
hidden 隐藏溢出部分
scroll 强制在水平和垂直方向添加滚动条
auto 自动在出现溢出的方向上添加可用的滚动条
1. 边框实现
属性 : border
作用 : 为元素统一设置上右下左四条边框
取值 :
border-width border-style border-color
1. border-width : 设置边框宽度,取像素值
2. border-style : 设置边框样式,可取
solid 实线边框
dashed 虚线边框
dotted 点线边框
double 双线边框
3. border-color : 设置边框颜色
注意 :
1. 边框宽度默认为3px,border-width可以省略
2. 边框颜色默认为黑色,border-color可以省略
3. 边框样式必须写,没有默认值
2. 单边框的设置
1. 属性 :
border-top 上边框
border-right 右
border-bottom 下
border-left 左
2. 取值 : width style color;
3. 网页三角标制作 :
1. 块元素设置宽高为0
2. 统一设置四条边框宽度样式,透明色(transparent)
3. 想要哪个方向的三角标就设置某个方向边框颜色,显示 注意 :
4. 三角标是通过边框拼接而成,所以不能省略其他的边框
5. 行内元素不能设置宽高,自带高度(文本大小决定),空标签只能拼接上下三角标,所以一般使用块元素做三角标
类似于边框,常见于输入框获取焦点时自带的样式
区别 : 元素添加边框,在文档中是实际占位的,而轮廓线在文档中不占位
属性 : outline
取值 : color style width
使用 :
取消文本输入框自带的轮廓线
outline:none;
1. 作用 :
调整元素四个角的显示形状,也可以改变元素形状
2. 属性 :
border-radius
3. 取值 :
像素值或百分比,表示半径,以当前半径在元素的四个角做圆或者椭圆,取一段弧,形成圆角效果
4. 取值情况
1. 像素值
border-radius : 20px; 四个角都以20px为半径做圆角效果
border-radius : 5px 10px 15px 20px; 分别代表上右下左四个角的圆角半径
border-radius : 10px 20px; 上下保持一致,左右保持一致
border:radisu : 10px 20px 30px; 上下分别为10px 30px,左右保持一致为20px
2. 百分比
百分比参照自身宽高尺寸计算圆角半径
根据宽高计算出两条半径,确定圆心,取弧,取值情况参照像素值
border-radius:20%;
border-radius:20% 30%;
border-radius:20% 30% 40%;
border-radius:10% 20% 30% 40%;
5. 取值范围
不超过元素尺寸
注意 :
1. 取100%等价于50%的效果
2. 单个角的取值范围 0 ~ 100%
3. 多个角统一设置,最大取50%
4. 四个角统一50%,改变元素形状(圆/椭圆,与元素尺寸有关)
1. 属性 : box-shadow
2. 取值 :
offsetX : 阴影的水平偏移距离,取像素值
offsetY : 阴影的垂直偏移距离,取像素值
blur : 阴影的模糊程度,取像素值,越大越模糊
spread : (选填)阴影的延伸距离,取像素值
color : 阴影颜色
3. 浏览器或者元素自身都具备坐标系.默认以左上角为(0,0)点,向右向下分别为X轴和Y轴的正方向
盒模型组成 :
元素尺寸(width/height)
内边距 (padding)
边框 (border)
外边距 (margin)
作用 : 各个属性互相叠加,影响元素在文档中的最终占据尺寸
计算 : 默认情况下,元素最终占据尺寸为
最终宽度 = width + 左右内边距 + 左右边框宽度 + 左右外边距
最终高度 = height + 上下内边距 +上下边框宽度 + 上下外边距
1. 作用 : 设置元素与元素之间的距离
2. 属性 : margin
3. 取值 :
像素值/百分比
1. margin : v1;
设置上右下左四个方向的外边距
2. margin : v1 v2;
设置上下外边距为v1,左右外边距为v2
3. margin : v1 v2 v3;
左右外边距一致为v2
4. margin : v1 v2 v3 v4;
分别设置上右下左四个方向的外边距
4. 特殊取值 :
1. margin:0; 取消默认外边距
2. margin:0 auto;
设置左右外边距自动,实现元素居中效果;auto只对左右边距有效
3. 可以使用负值,实现元素位置的微调
5. 单方向外边距的设置
1. 属性
margin-top
margin-right
margin-bottom
margin-left
2. 取值:
只写一个值
6. 外边距合并
1. 垂直方向
1. 子元素(块元素)添加的margin-top,作用于父元素上
解决办法 :
1. 父元素添加顶部边框
2. 父元素添加顶部内边距0.1px
padding-top:0.1px;
3. 父元素添加overflow:hidden;
2. 垂直方向上的块元素,同时添加上下外边距,取较大的值
2. 水平方向
行内元素默认情况下,对盒模型的属性部分支持,水平方向的外边距会叠加显示
7. 具有默认外边距的元素
body h1~h6 p ul ol
取消默认外边距 margin:0;
1. 元素内容与边框之间的距离
2. 语法 :
1. padding:10px; 设置上右下左四个方向的内边距
2. padding:10px 20px; 上下内边距一致,左右内边距一致
3. padding:10px 20px 30px; 左右保持一致
4. padding:10px 20px 30px 40px; 分别设置四个方向的内边距
5. 单方向内边距的设置
6. 属性 : padding-top padding-right padding-bottom padding-left
7. 取值 : 只取一个值
8. 具有内边距的元素
ul ol 表单控件 button
1. 作用 : 指定盒模型的计算方式
2. 取值 :
1. content-box 默认值 大部分元素遵照content-box计算在文档中的实际尺寸,计算方法 : 盒模型
各项属性值依次累加
2. border-box 表单控件默认都是按照border-box计算最终尺寸的 计算方法 : CSS属性
width/height定义的尺寸,是border-box的尺寸,包含边框,内边距,内容.
最终占据尺寸 width/height + margin
属性 : background-color
取值 : 颜色值
注意 :
1. 所有的元素默认背景颜色为透明rgba(0,0,0,0),窗口显示的白色是浏览器自动渲染的,与元素本身无关
2. 背景颜色从边框位置渲染,包含内边距和元素尺寸区域
1. 背景图片设置
属性 : background-image
取值 : url('路径')
注意 :
1. 路径加不加引号都可以,如果出现空格或者中文,必须加引号
2. 图片尺寸小于元素尺寸,浏览器会自动将背景图片重复平铺,填满元素
3. 图片尺寸大于元素尺寸,图片按照原始尺寸从边框位置显示,超出部分不可见
2. 背景图片重复方式
默认水平和垂直两个方向重复平铺,填满元素
属性 : background-repeat
取值 :
1. repeat 默认值
2. repeat-x 沿水平方向重复平铺
3. repeat-y 沿垂直方向重复平铺
4. no-repeat 不重复平铺
3. 背景图片的尺寸设置
属性 : background-size
取值 :
1. width height(px)
2. % %
百分比单位参照当前元素尺寸计算并调整背景图片大小
注意 : 如果只给一个值,默认表示宽度,高度会等比拉伸
3. cover 图片等比拉伸至足够大,完全覆盖元素,超出部分裁剪不可见
4. contain 图片等比拉伸至刚好被元素容纳,不改变图片宽高比,不会超出元素尺寸,会出现填不满元素的情况
4. 背景图片的位置设置
默认情况下,元素的内容或者背景图片都是从左上角显示的
属性 : background-position
取值 :
1. x y(px)
分别表示水平和垂直偏移距离
正值表示向右向下移动
负值表示向左向上移动,一旦超出元素区域,超出部分不显示
2. % %
参照元素自身的宽高尺寸,计算偏移距离
1. 0% 0%
显示在元素的左上角
2. 100% 100%
显示在元素的右下角
3. 50% 50%
显示在元素的中间
3. 方位值
x y 代表水平和垂直方向
取值 :
x : left/center/right
y : top/center/bottom
如果只设置一个方向的值,另外一个方向默认为center
精灵图技术 :
为了减少网络请求,节省资源,通常会将一组按钮不同状态下的小图片拼在一张图片上,通过一次网络请求得到,页面中借助background-position调整图标的显示
属性 : background
取值 : color url() repeat position;
注意 :
1. 使用简写属性统一设置背景相关的样式时,遵照以上顺序书写
2. 属性值根据需要添加,没有必填项
3. background-size是CSS3提供的属性,根据需要单独设置
1. 设置字体大小
属性 : font-size
取值 : 像素值 /em
2. 指定字体名称
属性 : font-family
取值 : 字体名称,多个名称之间使用逗号隔开;
如果字体名称中出现中文或者空格,必须加引号
例 :
font-family : Arial;
font-family : Arial,"黑体","Microsoft YaHei";
3. 指定字体粗细
属性 : font-weight
取值 :
normal (默认)
bold (加粗)
使用100~900之间的整百数值表示粗细程度
400 -> normal
700 -> bold
4. 指定字体样式(是否斜体或倾斜)
属性 : font-style
取值 :
1. normal (默认正常显示)
2. italic (斜体显示)
3. oblique (字体倾斜显示)
注意 : oblique 默认情况下显示效果与 italic一致,没有区别.一般将oblique作为italic的备用样式
5. 简写属性
属性 : font
取值 : style weight size family;
注意 :
1. 严格按照顺序书写
2. size family 是必填项,不能省略
1. 文本颜色
属性 : color
取值 : 颜色值
2. 文本的水平对齐方式
属性 : text-align
取值 : left/center/right/justify(两端对齐)
注意 :
1.用于块元素,在元素尺 寸范围内设置文本内容的水平对齐;
2. 两端对齐,浏览器会自动调整每一行字符之间的间距
3. 文本的垂直显示位置
属性 : line-height
取值 : 像素值
使用 :
1. 一行文本的垂直居中:
将行高设置与高度保持一致,元素尺寸范围内,只能显示一行.
文本内容在当前行中,永远是垂直居中的,浏览器会自动分配上下空隙
2. 如果行高小于高度,文本显示在元素靠上的位置
3. 如果行高大于高度,文本显示在元素靠下的位置,可以通过行高对文本位置微调
特殊 :
line-height可取无单位的数值,表示字体大小的倍数,依此计算行高
p{
font-size:16px;
line-height:2;
/*表示行高为字体大小的两倍,32px*/
}
4. 文本装饰线
属性 : text-decoration
取值 :
1. underline 下划线
2. overline 上划线
3. line-through 删除线
4. none 取消装饰线
5. 标签嵌套
1. 块元素中可以嵌套一切标签
注意 :
1. 标题中只能嵌套段落或者行内元素
2. 段落中只能嵌套行内元素
2. 行内元素中只能嵌套行内元素
1. 边框合并
属性 : border-collapse
取值 :
1. separate (默认表格边框与单元格边框是分离状态)
2. collapse 边框合并
2. 设置边框之间的距离
属性 : border-spacing
取值 : h v;
两个值分别设置水平方向边框之间的距离
垂直方向边框之间的距离,取像素值
注意 : 必须在边框分离状态下才能使用该属性
3. 表格尺寸
1. table设置宽高,单元格会自动分配空间
2. table固定宽高,指定某个单元格的尺寸,会影响单元格所在的行高和列宽
3. 如果需要统一设置所有单元格的尺寸,table就不能再指定宽高了,让表格的尺寸由内容决定
不同状态下元素样式的改变,不再是瞬时完成,而是增加平滑过渡的效果
1. 指定过渡时长
transition-duration
取值 : 以秒(s)或者毫秒(ms)为单位的数值 1s = 1000ms
2. 指定过渡属性
transition-property
取值 :
1. all (代表所有CSS属性)
2. CSS属性名,属性名,属性名
3. 指定过渡效果的速度变化
transition-timing-function
取值 :
1. ease 默认值,慢速开始,中间快速变快,慢速结束
2. linear 匀速变化
3. ease-in 慢速开始,加速结束
4. ease-out 快速开始,减速结束
5. ease-in-out 慢速开始和结束,中间过程先加速后减速
4. 指定过渡效果延迟执行
transition-delay
取值 : 时间值(s/ms)
5. 属性简写
语法 :
transition : property duration timing-function delay;
注意 : duration 是必填项,不写过渡时长,就没有过渡效果
练习 :
1. 块元素200*200,背景颜色自定义
2. 鼠标悬停时,尺寸改为300*300,改成圆形,背景颜色自定义
3. 所有样式改变,添加过渡效果,在3s内完成
1. 普通流布局/文档流布局/静态布局
特点 : 按照元素类型和书写顺序,从上至下,从左到右,依次显示元素,是默认的布局方式
2. 浮动布局
属性 : float
取值 : left/right/none(默认)
特点 :
1. 元素设置浮动,会停靠在其他元素的边缘,left/right指定元素的浮动方向
2. 浮动元素会脱离文档流,在文档中不再占位,后面正常元素会向前占位,影响整体布局
3. 元素一旦脱离文档流,尺寸就由内容多少决定,可以手动调整宽高
4. 浮动会造成文字环绕效果,浮动元素不占位,悬浮在文档上方,有可能遮挡正常元素,正常元素中的内容会围绕在浮动元素周围显示
问题 : 浮动元素不占位,导致父元素高度为0,影响布局,影响父元素背景图片,背景色的展示
作业 :
1. 自定义导航栏,内容样式不限,要求导航项均匀分布,导航项之间有间隔
2. 登录页面
3. 表格练习
CSS页面布局样式
特点 : 根据标签类型和书写顺序从上到下,从左到右依次排列显示
属性 : float
取值 : left/right/none
特点 :
1. 元素设置浮动,会从它在文档中的原始位置,脱离文档流,向左或向右移动,停靠在其它元素的边缘,多个浮动元素会按照顺序依次停靠
2. 浮动元素在文档中不占位,元素设置浮动之后都可以设置宽高尺寸,并且水平方向没有缝隙
问题 :
子元素全部浮动不占位,导致父元素高度为0,自身的背景色背景图无法显示,后面正常文档中的元素会向前占位,影响布局
解决 :
1. 给父元素固定高度(导航栏)
2. 给父元素添加overflow:hidden;
3. 清除浮动带来的影响 :
在父元素末尾添加空的块元素,
为新添加的块元素设置clear:both;
清除浮动 :
属性 : clear
取值 : left/right/both
作用 : 使文档中正常元素不受前面浮动元素的影响
属性 : position
取值 : static(默认)/relative/absolute/fixed
已定位元素 : 只有元素设置position属性值为relative/absolute/fixed,才称为已定位元素
分类 :
1. relative 相对定位
特点 : 元素设置相对定位,会参照它在文档中的原始位置进行偏移
偏移属性 :
top : 正值,元素下移;负值,元素上移
left :正值,元素右移;负值,元素左移
right:
bottom :
2. absolute 绝对定位
特点 :
1. 绝对定位的元素会参照一个离它最近的已经定位的祖先元素进行偏移,
如果没有已定位的祖先元素,就参照浏览器窗口的左上角进行偏移.
2. 绝对定位的元素会脱离文档流,所有脱流元素在文档中都不占位
使用 :
1. 偏移属性,根据元素参照物的边缘进行偏移
2. 父相子绝 : 父元素相对定位,子元素通过绝对定位调整显示位置
3. 堆叠次序调整
属性 : z-index
取值 : 无单位的数值,数值越大,越靠上,默认值为0
使用 :
1. 只有已定位的元素才可以使用z-index调整堆叠次序
2. 兄弟元素之间,通过z-index调整堆叠次序,数值越大越靠上;数值相等,后来者居上(代码书写顺序)
3. 父子关系不受z-index影响,永远子元素在上
4. 固定定位 fixed
特点 : 固定定位的元素,永远参照浏览器窗口进行偏移,固定显示在窗口的某个位置,不会跟随页面滚动而滚动(聊天窗)
取值 : inline/block/inline-block/none;
作用 : 调整元素的显示方式,取值对应标签分类
inline 行内元素
inline-block 行内块元素
block 块元素
none 元素隐藏不显示,隐藏元素不占位
取值 : visible(默认) / hidden (隐藏)
作用 : 控制元素显示与隐藏,元素隐藏但是仍然在文档中占位
取值 : 0 (透明) ~ 1 (不透明)
特点 :
1. 使用opacity设置元素半透明,表示元素内部所有的内容都呈现半透明效果
2. 父子元素都设置opacity半透明,子元素最终的半透明效果是在父元素基础上再次半透明,值相乘
属性 : cursor
作用 : 调整鼠标在当前元素上的显示形状
取值 :
1. default 默认值
2. pointer 手指形状
3. text 文本 I
列表 : 自带上下margin,padding-left,带有项目符号
属性 :
1. list-style-type :
设置列表项目符号
2. list-style-image:
自定义项目符号
取值 : url()
3. list-style-position
取值 : outside(默认) / inside
作用 :
设置项目符号的显示位置,是否在内容框中显示,默认在padding区域显示
简写属性 :
list-style : none; 取消列表项目符号
元素的缩放,平移和旋转都称为转换操作
属性 : transform
取值 : 转换函数 转换函数 转换函数;
1. 转换原点(基准点)
默认以元素的中心点作为转换原点.
属性 : transform-origin
取值 : x y;
1. 取像素值 在元素自身左上角为原点构建的坐标系中选取点的坐标
2. 取百分比
3. 取方位值 left/center/right top/center/bottom
2. 转换函数
1. 平移变换
函数 : translate(h,v)
取值 : 可以分别设置元素沿X轴和Y轴移动的距离,正值表示向右向下平移,负值表示反方向.取一个值,表示沿X轴方向平移
其他 :
translateX(value) : 沿X轴平移
translateY(value) : 沿Y轴平移
translate(value) : 等价于translateX(value)
2. 缩放变换 改变元素在页面中的大小
函数 : scale(value)
取值情况 :
1. value为无单位的数值,表示缩放比
2. value > 1 元素放大
3. 0 < value < 1 元素缩小
4. value < 0 ,数值仍然是缩放比,负号表示元素翻转
其他函数 :
scaleX(value):X轴缩放
scaleY(value):Y轴缩放
scale(value) :沿X轴和Y轴同时缩放
3. 旋转变换
将元素旋转一定角度显示
函数 : rotate(value)
取值 : 角度deg为单位的数值,正值表示顺时针旋转,负值表示逆时针旋转
注意 : 转换基准点不同,效果不同
3D旋转 函数 : rotateX() / rotateY()
4. 转换函数的组合使用
1. 转换原点会影响最终结果
2. 转换函数的先后顺序,也会影响结果:
旋转操作会连带坐标轴一起旋转
浏览器解释型语言,嵌套在HTML文件中交给浏览器解释和执行.
实现用户交互(键盘或者鼠标操作);实现页面动效;小游戏制作等.
1. 核心语法 (ECMAScript)
2. BOM : Browser Object Model,浏览器对象模型,提供一系列与浏览器相关的属性和方法
3. DOM : Document Object Model 文档对象模型,提供一系列操作页面的属性和方法
4. 自定义对象
事件 : 所有用户的行为都称为事件
事件处理函数 :
对应用户的行为,JS中所做的操作
onclick 单击事件
语法 :
<标签名 事件名="JS代码">
JS语句 :
alert("Hello world"); //网页弹框
console.log("控制台输出");
注意 : 脚本标签在文档中可以书写任意多次,出现在任意位置,但是不同的位置有可能影响执行结果.
语法 :
创建.js文件,在HTML中通过<script src=""></script>引入
注意 : 引入外部JS文件时,脚本标签中不能再书写JS代码
输出语句 :
prompt(""); 带有输入框的弹框,可以接受用于输入,并返回
document.write(""); 在页面中写入内容,可以识别HTML标签;
注意 :
1. document.write()代码的书写位置,决定了内容在body中的添加位置
2. 事件处理时书写的document.write(),会造成页面重写,点击会造成刷新
练习 :
1. 使用元素绑定事件的方式,为button标签添加单击事件,点击时在控制台输出"第一个JS代码"
<button onclick="console.log('');">点击</button>
2. 使用内嵌的方式,在页面中写入一级标题,内容不限
<script>
document.write("<h1></h1>");
</script>
3. 外链方式给提示框
<script src=""></script>
1. JS代码是由语句组成的,语句可以由变量,常量,运算符,关键字,函数等组成
2. JS代码中语句的结束以;为标志,可以省略
3. JS代码严格区分大小写
如:
Console.log(); //错误
consolo.log(); //错误
4. 所有的标点都是英文标点
注释 :
单行 : //单行注释
多行 : /* 多行注释 */
1. 变量表示在程序运行期间随时可以修改的数据
2. 变量创建 :
3. JS 变量使用
var 关键字表示
语法 :
var a; //变量声明,自定义变量名
a = 100; //变量赋值
var b = 200; //声明并赋值
var m,n,k; //同时声明多个变量
var s=10,y=20;//声明并赋值多个变量
4. 变量的命名规范
1. 可以由数字,字母,下划线,$组成,禁止以数字开头;
2. 禁止与关键字或保留字冲突(var const function class if do while for break continue name)
3. 变量以小写字母开头,尽量见名知意,多个单词组成的变量名,采用小驼峰
例 :
var userName;
var username;
4. 变量名严格区分大小写
5. 变量使用注意
var a = 100;
console.log(a,b,'');
alert(a); //接收一个参数
prompt(a);
document.write('<h1>'+a+'</h1>');
1. 一经声明就无法修改的数据
2. 语法 :
常量使用关键字 const 声明,必须声明的同时赋值;为了与变量区分,常量名采用全大写字母表示
例 :
const PI = 3.14;
注 : 强制修改常量,会报错
3. 练习 :
自定义半径(变量),定义圆周率(常量),计算圆的周长和面积,控制台输出结果
4. 小数位设置 toFixed(n);
保留小数点后n位
例 :
var a = 62.80000000004;
a = a.toFixed(2);
1.number 数值类型
1.整数
十进制表示
var a = 10;
八进制表示
八进制数据以0开头,采用0-7八位数字表示
var a = 010; //08(0)+18(1)
控制台一律转成十进制输出
十六进制表示
十六进制表示整数,以0x为前缀
var b = 0x35; //516(0) + 316(1)
2. 小数
小数点计数法 3.14
指数计数法 1.5e3
1.5 * 10(3)
e表示10为底,3表示10的次方数
2.string 字符串类型
字符串由一个或多个字符组成,使用引号表示,每位字符都有对应的Unicode码值
1. 语法
var s = '100';
var a = 100;
2. 查看字符对应的Unicode码值
方法 : charCodeAt(index);
参数 : 字符串默认为每个字符分配下标,从0开始.参数传入下标,获取指定位置的字符编码
使用 :
var s1 = "hello";
s1.charCodeAt(0);
3. 已知中文的Unicode码,转换为字符,中文在计算机中以十六进制存储
方法 :
toString(16); //转换为16进制 十六进制字符串转换汉字时, 需要添加\u转义字符
4. 中文范围
"\u4e00" ~ "\u9fa5"
5. 转义字符
\n : 换行
\t : 制表符
\ : 表示\
\" : 表示"
3.boolean 布尔类型
布尔类型的结果只有真和假 true/false
var isTrue = true;
转换成数值true=1,false=0;
4.null 空类型
布尔类型的结果只有真和假 true/false
var isTrue = true;
转换成数值true=1,false=0;
对象,由属性和方法组成的
1.检测数据类型
运算符(关键字) : typeof
typeof a;
typeof (code.toString(16));
2.数据类型转换
不同类型的数据进行运算,需要转换类型
3.自动(隐式)类型转换
不同类型的数据进行运算,需要转换类型
1. 字符串与其他类型的数据结合,使用+号连接时,永远表示字符串的拼接
转换规则 : 将非字符串类型的数据转换成字符串,后进行拼接,最终结果仍为字符串
2. number + boolean
转换 : 将非number类型的数据,转换成number,进行数学相加
特殊 :
//undefined首先转换number,返回NaN(not a number,转换失败)
//10 + NaN = NaN
var s2 = 10 + undefined;
var s3 = 10 + null; //10,null转number,转为0
3. boolean + boolean
布尔类型参与数学运算,会自动转换成number
4.强制类型转换
1. 转换字符串类型
方法 :
toString(); 将任意类型的数据转换成字符串类型
例 :
var a = 100;
var a1 = a.toString();
console.log(a,typeof a);
console.log(a1,typeof a1);
2. 转换number类型
1. Number(param)
将任意类型的数据转换成number类型
参数 : 需要类型转换的数据
返回 : 返回转换结果,成功则返回number值,失败返回NaN
例 :
var s1 = Number("35.5");//35.5
var s2 = Number(true);//1
var s3 = Number("18a"); //NaN
2. parseInt(param) 解析字符串中的number数据(只保留整数)
过程 :
1. 如果参数非字符串,自动转换成字符串类型
2. 从左至右,对每一位字符串进行转number的操作,当前位转换失败则停止向后解析,直接返回结果
例 :
var s1 = parseInt(35.5);
var s2 = parseInt("18.5a");
var s3 = parseInt("a18");//NaN
3. parseFloat(param)
解析字符串中的number数据,包含小数部分
例 :
var s1 = parseFloat("35.5");
var s2 = parseFloat("18.5a");
//9.3
var s3 = parseFloat("9.3.5a");
将赋值符号右侧的值赋给左边的变量
var a = 100;
+ - * / %(取余)
1. 所有涉及字符串参与的+运算,全都是字符串拼接.
例 :
• var s1 = "10" + true;
2. 非字符串类型参与算数运算,统一转换成number(自动转换),后进行计算.
字符串类型再进行除+以外的其他运算时,也先转换number再进行计算
1. 变量使用++/--,表示在自身基础上+1/-1
var a = 10; a ++;
// a += 1; a = a + 1;
console.log(a);
2. 使用 :
1. 单独与变量结合,做前缀或做后缀,没有区别
2. 与其他运算符结合使用时,前缀和后缀影响计算结果;
做前缀,先++/--,后结合其他运算;
做后缀,先结合其他运算符,最后再++/--
3. 思考 :
var n = 5;
var r = n++ + ++n + n++ + ++n +n;
解 :
表达式1 : r1 = n++; //r1=5,n=6
表达式2 : r2 = ++n; //r2=7,n=7
表达式3 : r3 = n++; //r3=7,n=8
表达式4 : r4 = ++n; //r4=9,n=9
表达式5 : r5 = n; //r5=9,n=9 r = 5 + 7 + 7 + 9 + 9;
复习 :
<div onclick="JS 语句"></div>
15 + "10" //"1510"
10 + 5 + "5" //"155"
"10" + true //"10true"
10 + "10" + true //"1010true"
10 + true + "10" //"1110"
10 + undefined //NaN
"10" + null //"10null"
true + false //1
强制
1.任意类型转换字符串
toString();
例 :
var a = true;
var a1 = a.toString();//"true"
2.任意类型转换number
1. Number(param)
例 :
Number("50.4");//50.4
Number("50a");//NaN
Number(true);//1
2.parseInt(param)
例 :
parseInt(35.5);//35
parseInt("35.5a")//35
parseInt("a35.5")//NaN
3. parseFloat(param)
例 :
parseFloat("35.5.3");//35.5
运算符
赋值运算符
算数运算符 + - * / %
例 :
"10" - 5 ; //5
"10a" - 5; //NaN
"10" + true;
"10" - true;//9
+= -= *= /= %=
例 :
var a = 10;
a += 5; // a = a + 5;
1. 单独使用放前或放后没有区别
例 :
var a = 10;
a ++;
++ a;
5 ++; //error const A = 5;
A ++; //error
注 : 自增和自减运算只能变量使用,常量无法修改
2. 与其他运算符结合使用
例 :
var n = 10;
var r = n ++ + ++n;
> >= < <= ==(相等) !=(不等)
> >===(恒等) !==(不恒等)
1. 比较运算符用来判断表达式之间的关系,结果为布尔类型
2. 分类
1. number 与其他类型之间的比较
过程 : 将非number数据转换成number,再进行比较
注意 : NaN 与任意数据比较,结果都为false
2. 字符串之间的比较
1. 字符串之间比较,不会再数据类型转换
2. 从前往后,依次比较每位字符的Unicode码
例 :
var r = "2" > "10";
var r = "20" > "21";
3. 字符串与布尔类型的比较
例 :
"10" > true //true
"10a" > true //false
注 : 先转number再比较
3. 相等与全等
1. 相等:包含自动类型转换,只要值相等,就成立
例 :
"10" == 10 //true
"10" != 10 //false
2. 全等:不会进行自动类型转换,要求类型一致,值相等,才视为成立
例 :
"10" === 10 //false
"10" !== 10 //true
1. 将多个条件表达式的结果组合成最终单一的布尔值
2. 分类 :
1. && :逻辑与
两个表达式都成立,最终结果才成立,为true. (全1则1)
例 :
5 > 3 && "10" >"2" //false
true && false
2. || :逻辑或
两个表达式中只要有一个成立,最终结果都为true. (有1则1)
例 :
5 > 3 || "10" >"2" //true
3. ! :逻辑非
对布尔结果取反操作
非真即假,非假即真.
例 :
!(5 > 3) //false
!false //true
!5 //false
注 : 除零值以外的所有值都为真,零值为假
练习 :
接收输入的年份,检测数据类型;
判断该年份是否是闰年,在控制台输出结果
闰年 :
1. 能被 400 整除
2. 能被4整除,但是不能被100整除
接收用户输入一个字符,判断输入的内容
是数字吗 ?
是字母吗 ?
是中文吗 ?
将操作数转换成二进制形式,按位进行与操作
例 :
3 & 5 = 1
011
& 101
---------
001 -> 1
注 : 任何整数与1做位与,可以判断奇偶.结果为1,操作数为奇数;结果为0,操作数为偶数
例 :
3 & 1 //011 & 001 = 001
2 & 1 //010 & 001 = 000
2. 位或 : |
对二进制位进行或操作,有1则1
例 :
3 | 5 //011 | 101 = 111
3. 异或 : ^
比较二进制位,相同为0,不同为1
例 :
3 ^ 5 //011 ^ 101 = 110
注 :
异或可以在不借助第三方变量的情况下,互换两个变量的值
var a = 3;
var b = 5;
a = a ^ b; //110 = 6
b = a ^ b; //110 ^ 101 = 011 3
a = a ^ b; //110 ^ 011 = 101 5
条件1 ? 表达式1 : 表达式2;
判断条件1是否成立?
成立,执行表达式1
不成立,执行表达式2
返回结果
1. 成绩判定
接收用户输入的成绩
>=90 A
80~90 B
60~80 C
<60 D
判断等级并输出
2. 身体指数 BMI
bmi = 体重(kg) / (身高 * 身高m);
保留两位小数
判断身体情况
bmi > 23.9 该减肥了
18.5 <= bmi <= 23.9 健康
< 18.5 偏瘦
控制代码的执行顺序
自上而下,依次执行所有的代码语句
根据条件是否成立,选择执行某段代码
1.if语句
1. if(条件){
条件成立时执行
}
注 :
1. {} 可以省略,省略之后,if条件满足时,只执行后面紧跟的一条语句
2. 零值为假 :
if(0){}
if(0.00){}
if(""){}
if(NaN){}
if(undefined){}
if(null){}
注意 :
带有空格的字符串视为真
2. if-else
语法 :
if(条件){
//成立时执行
}else{
//条件不成立时执行
}
例 :
var age = 20;
if(age >= 18){
console.log("一起开黑");
}else{
console.log("未成年人禁止入内");
}
3. 多重分支
语法 :
if(条件1){
//条件1成立执行
}else if(条件2){
//条件2成立时执行
}else if(){
}else{
}
练习 :
1. 使用if判断成绩等级
2. 日期计算器,接收用户输入的年,月,日,判断当日是该年的第几天
2.switch语句
主要用来做值的匹配
语法 :
switch(变量){
case 值1 :
//匹配成功执行的代码段
break; //结束匹配
case 值2 :
//匹配成功执行
break;
...
default:
console.log("匹配失败,默认执行的操作");
break;
}
注意 :
1. switch进行值的全等匹配,要求类型与值都一致,才能匹配成功
2. case 用来列举所有可能的取值情况
3. break用于结束匹配,可以省略;如果省略break,会从当前匹配到的case开始向后执行所有case中的代码
4. 多个case可以共用代码段 : case '1' : case '3' : case '5' : alert("红烧肉"); break;
5. default 表示默认情况,写在最后,表示所有case都匹配失败最终执行的操作
练习 :
1. 控制台输出1-100之间所有的 整数
2. 求1-100之间所有整数的和
3. 控制台输出1-100之间所有3的倍数
4. 改版日期计算器
重复执行某一段代码
循环三要素 : 循环变量; 循环执行的条件; 循环体
分类 :
1.while 循环
语法 :
循环变量;
while(循环条件){
循环体;
更新循环变量
}
例 :
var i = 1;
while(i < 101){
console.log("优秀");
//更新循环变量
i++;
}
执行流程 :
1. 定义循环变量
2. 判断循环条件
3. 条件成立,执行循环体
4. 循环体中更新循环变量,避免死循环
5. 重复2-3-4,直到条件不成立,结束循环
练习 :
1. 控制台输出1-100之间所有的 整数
2. 求1-100之间所有整数的和
3. 控制台输出1-100之间所有3的倍数
4. 改版日期计算器
2.do-while 循环
语法 :
循环变量
do{
循环体
更新循环变量
}while(循环条件);
执行流程 :
1. 定义循环变量
2. 执行循环体
3. 更新循环变量
4. 判断循环条件,条件成立,重复2-3-4;条件不成立,结束循环
练习 :
循环接收用户输入并在控制台输出,直到用户输入"exit",结束循环
总结 :
do-while 不管循环条件是否成立,至少执行一遍循环体;更适用于不确定循环次数的场合
while 先判断后执行,更适用于明确循环次数的场合
3.for 循环
for(定义变量;循环条件;更新){
循环体
}
例 :
for(var i = 1; i < 101; i++){
console.log(i);
}
循环控制 :
1. break : 用于结束循环,后面的代码都不执行
2. continue : 跳出本次循环,开始下一次循环
循环嵌套 :
在循环体中嵌套使用其他循环体
练习 :
1. 判断素数
接收用户输入的一个数字,判断是否是素数
2. 接收用户输入的年月日,判断星期几
已知 : 1990年1月1日是星期一
1900年1月1日是星期一
3. 控制台输出图案
一:
*
**
***
****
*****
二:
*
***
*****
*******
*********
4. 九九乘法表
保存一段待执行的代码
1. 函数声明
封装代码段
function 函数名 (参数列表) {
函数体
return 返回值;
}
2. 函数调用 执行代码段 函数名(实际参数)
1. 函数名自定义,见名知意,命名规范参照变量,普通函数使用小写字母开头.
2. 参数的小括号不能省略,多个参数之间使用逗号隔开
3. return关键字用于将函数内部的结果返回给外界使用,只能返回一个值(表达式),外界通过定义变量来接收.return关键字后面的代码都不执行,所以return写在函数体末尾
1. 使用变量保存匿名函数
var fun = function (){};
fun();
注 : 变量名相当于函数名
2. 匿名函数自执行 (function (){})(参数);
1. 全局作用域
1. 在函数外部定义的变量都是全局作用域中的变量,在任何地方都可以访问
2. 所有省略var关键字创建的变量都是全局变量
3. 函数作用域
在函数内部使用var关键字定义的变量都是局部变量,只在当前函数体中可以访问,外界无法使用
4. 作用域链
函数作用域中访问变量,首先从自身作用域中查找,查找失败,向外层作用中查找变量,依次类推,直至全局作用域
练习 :
5. 日期计算改用函数封装 整体功能通过函数封装,按钮点击调用 闰年判断封装函数
1. 按照顺序存储一组数据
1. 创建数组
1. 使用[]表示数组结构,数据使用逗号隔开 例 :
var arr1 = [1,2,3];
2. 使用 new 关键字,根据类型 Array,创建具体的对象 例 :
var arr2 = new Array(10,20,30);
var arr3 = new Array(5); 注 :
使用new关键字创建数组时,如果只传一个整数作为参数,表示初始化数组长度(预分配,数组长度可以动态修改)
2. 操作数组元素
3. 数组会自动为元素分配下标,默认从0开始
4. 通过元素下标实现对数组元素的读取 语法 :
arr[下标] = 10;
5. 遍历数组元素
属性 : length 表示数组长度(元素个数),通过点语法访问
语法 :
for(var i = 0; i < arr.length; i++){
console.log(arr[i]);
}
for(var j = arr.length-1; j>=0;j--){
//倒序遍历
}
快速for循环 --
for..in for(variable in array){
自定义变量variable表示数组下标
}
练习 :
1. 循环接收用户输入,将数据存储在数组中,直至用户输入"exit"表示结束输入,控制台打印数组元素
2. 声明包含若干数据的数组(number),求这一组数据中的最大值
3. 创建一个包含三个number数据的数组,按照从小到大的顺序排列输出
[67,128,30]
两两比较出结果 :
第一次 : 67 128
第二次 : 128 30 -> 30 128
第三次 : 67 30 -> 30 67
4. 声明数组包含若干元素(number),接收用户输入,查询用户输入的数据在数组中对应的下标,如果不存在,返回-1
1. 属性 length
表示数组长度
2. 方法
1. toString()
作用 : 将数组转换成字符串
返回 : 字符串
2. join(param)
作用 : 将数组中的元素按照指定的符号链接,返回字符串
参数 : 可选,用于指定元素之间的链接符,默认为逗号
3. reverse(param)
作用 : 反转数组,倒序重排
返回 : 数组,反转操作改变原始数组的结构
4. sort()
作用 : 将数组中的元素按照Unicode码值升序排列
返回 : 数组,改变原始数组的存储顺序
参数 : 可选,自定义排序算法
例 :
function sortASC(a,b) {
return a-b;
}
自定义升序排列的算法,对number按照值的大小升序排列 :
1. 参数a,b :代表数组中的两个元素.会自动传入相邻的两个元素进行比较
2. 如果a-b > 0,交换元素的位置,否则不变
例 :
function sortASC(a,b) {
return b-a;
}
自定义降序排列
5. push(data)
作用 : 在数组的末尾添加一个或者若干个元素,多个元素之间使用逗号隔开
返回 : 新数组的长度
6. pop()
作用 : 删除数组中末尾元素
返回 : 被删除的元素
7. unshift(data)
作用 : 在数组的头部添加一个或多个元素
返回 : 修改之后数组的长度
8. shift()
作用 : 删除数组中的第一个元素
返回 : 被删除元素
9. forEach(function)
作用 : 遍历数组元素
参数 : 通过函数,获取数组中元素,
执行相关操作过程 : 每取出一个元素,将元素和其对应的下标,传入函数,自动执行.
函数 : 接收两个参数,分别表示元素和下标;如果只定义一个形参,只接受元素
例 :
arr.forEach(function (elem,index){
console.log(elem,index);
});
1. 数组中的每一个元素又都是数组结构
2. 语法 :
var arr = [[1,2],[3,4],[5,6,7]];
3. 读取元素 :
var arr2 = arr[0];
var num = arr2[0];
var num2 = arr[1][0]; //3
练习 :
通过代码实现十进制转二进制,输出最终的二进制字符串
数字可以由用户输入(整数)
方法 :
1. 除2取余,直至商为0
2. 余数倒序排列
例 :
5 -> 101
5 / 2 = 2 ... 1
2 / 2 = 1 ... 0
1 / 2 = 0 ... 1
var s1 = "100";
var s2 = new String("hello");
var s3 = String("hi");
注 : 内置对象类型,创建时可以省略new关键字
length : 获取字符串长度(字符个数)
注 : 字符串采用类数组结构存储每一个字符,自动为每位字符分配下标,默认从0开始
1. toUpperCase() 将字符串中的字母转换大写
2. toLowerCase() 将字母转小写 返回 : 转换后的字符串,不会影响原始字符串
练习 :
模拟验证码 :
1. 创建数组,存放数字,字母,作为数据源
2. 生成随机验证码(4位) 随机数 : Math.random() [0,1) 随机下标 : [0,10) , 取整
3. 通过弹框提示用户输入,不区分大小写
4. 验证用户输入,提示正确与否
5. 用户点击 "获取验证码",提示用户输入
6. 验证功能封装函数
7. 生成验证码的过程也封装成函数,可以接受参数,生成指定位数的验证码
1. charAt(index) 获取指定下标的字符
2. charCodeAt(index) 获取指定下标的字符Unicode码
1. indexOf(value,fromIndex)
作用 : 获取指定字符的下标
返回 : 下标,从指定位置(默认从0开始)向后查找,返回第一次匹配成功的下标;查找失败,返回-1
参数 :
1.value : 指定字符或字符串,必填
2. fromIndex : 选填,默认为0,表示从哪一个下标开始向后查找
2. lastIndexOf(value,fromIndex)
作用 : 获取指定字符(串)最后一次出现的下标位置
参数 :
1. value : 指定字符或字符串
2. fromIndex : 指定起始下标,选填
注意 : lastIndexOf,根据给出的起始位置, 从后向前查找字符,找到即返回下标
substring(startIndex,endIndex);
作用 : 根据指定的下标范围,截取字符串并返回
参数 : 指定截取范围 [startIndex,endIndex),endIndex可以省略,表示截止末尾
练习 :
1. 自定义邮箱字符串
用户名@服务商
要求 : 从邮箱字符串中提取除用户名和服务商
2. 指定身份证号码,提取出生年月日
例: 100321 1900 01 01 0001
split(seperator);
作用 : 根据指定的分隔符,分割字符串
返回 : 数组,存放分割后的每个字符串
参数 : 指定分割符,如果字符串中不包含指定的字符,字符串不会被分割,仍然会返回数组
练习 :
"101_5&201_10&301_20"
商品id _ 商品数量
101
5 提取商品id和数量,进行输出
"商品id为...数量为...."
1. 作用 : 结合正则表达式实现指定字符串的查找和替换
2. 正则表达式 :
1. 语法 :
/正则格式/修饰符
修饰符 :
i : ignorecase 忽略大小写
g : global 全局匹配
例 :
var reg1 = /微软/g;
var reg2 = /\d{2,6}/;
3. 字符串方法
1. match(regExp/subStr);
参数 : 可以使用正则表达式表示字符串格式,或者直接使用字符串
作用 : 查找字符串中所有满足正则格式或给定字符要求的内容
返回 : 数组,存放查找到的所有字符串
2. replace(regExp/subStr,newStr)
作用 : 根据指定字符或正则查找字符串中相应内容,并替换为newStr
返回 : 替换后的新字符串,不影响原始数据
制定字符串的组成模式
1. var reg1 = /正则格式/修饰符;
2. var reg2 = new RegExp('正则格式','修饰符');
1. 属性 : lastIndex
可读可写,表示下一次匹配的起始下标
2. test(param) 验证字符串中是否存在满足正则格式的内容,返回布尔值 参数为要验证的字符串
数学常量 :
Math.PI 表示圆周率3.14或者度数 180度
Math.E 自然对数
1. 三角函数
Math.sin(x) 求正弦,参数为角度值
Math.cos(x) Math.tan(x)
注 : 可以借助Math.PI进行角度转换
例 : PI/3
2. 计算函数
Math.sqrt(x) 开平方
Math.pow(x,y) 求x的y次方
Math.log(x) 求对数
3. 数值函数
Math.abs(x) 求绝对值
Math.max(a,b,c,d,e) 求一组数据的最大值
Math.min(a,b,c,d,e) 求一组数据的最小值
Math.random() 生成[0,1) 随机小数
Math.ceil(x) 对x向上取整
Math.floor(x) 舍弃小数位,保留整数位 Math.round(x) 四舍五入取整
1. 获取当前的系统时间
var date1 = new Date();
2. 创建指定日期时间的对象
var date2 = new Date("2012/12/12 10:10:10");
1. getTime()
读取当前日期对象距离1970-01-01 00:00:00 之间间隔的毫秒数
2. 读取时间分量
1. getFullYear()
获取当前日期对象的年份
2. getMonth()
获取当前日期对象的月份,返回0-11表示12个月,需要进行+1处理
3. getDate()
获取当前对象的日期信息
4. getDay()
获取当前对象的星期数 取值0-6,对应周日-周六
5. getHours()
获取小时数
6. getMinutes()
获取分钟
7. getSeconds()
获取秒数
8. getMilliseconds()
获取毫秒数
3. 转换日期格式
1. toLocaleString()
以本地格式显示日期时间
2. toLocaleDateString()
以本地格式显示日期
3. toLocaleTimeString()
以本地格式显示时间
外置对象
浏览器对象模型 : 提供与浏览器交互的对象. 核心对象是window(窗口) window 由浏览器在打开页面时自动创建,可以直接访问
window 包含的属性和方法 :
1. 属性
history screen location document navigator
以上都是对象类型,包含自身的属性和方法
2. 方法
alert();
prompt();
confirm("");
确认框,参数为提示文本,自带确认和取消两个按钮,点击确认返回true,点击取消,返回false
window.close();
关闭当前窗口
定时器方法
3. 使用
1. 可以省略window对象,直接访问相关的属性和方法
window.alert();
window.document.write();
2. 所有的全局变量和全局函数,都是window对象的属性和方法
练习 :
使用确认框,询问用户是否要关闭当前窗口;
如果点击确定,关闭窗口 window.close();
1. 根据指定的时间间隔,不断调用相关代码
2. 语法 :
1. 开启
var timerID = setInterval(func,interval);
参数 :
1. func : 需要间歇调用的代码段
2. 时间间隔,默认以毫秒为单位
返回 : 定时器的ID
2. 关闭 clearInterval(timerID);
1. 在指定的时间间隔之后,执行一次代码
2. 语法
1. 开启 :
var timerID = setTimeout(func,interval);
2. 关闭 : clearTimeout(timerID);
3. 练习
1. 创建按钮(开始和结束) 点击开始,在控制台每个一秒输出一次系统时间 点击结束,停止输出
2. 弹框询问是否关闭窗口,如果点击确定,3秒后关闭页面
复习 :
内置对象
[startIndex,endIndex-1]
例 :
var date = "2011-11-11";
var arr = date.split('-');
全局变量和全局函数都是window对象的属性和方法,可以通过点语法访问
window对象在浏览器打开页面时自动创建,使用时可以省略
alert(str)
prompt(str) 返回输入内容(字符串)
confirm(str)返回true/false
close() 关闭当前窗口
var timerId =setInterval(func,interval);
clearInterval(timerId);
var timerId2 =setTimeout(func,timeout);
clearTimeout(timerId2);
4.属性
1. 大部分window对象的属性,又是对象类型,包含自身的属性和方法
例 : document screen location history...
2. screen 屏幕对象
保存与屏幕相关的信息
属性 :
width/height : 获取屏幕宽高
availWidth/availHeight : 实际可用的屏幕宽高(减去任务栏之后的尺寸)
3. history
保存当前窗口访问过的URL信息
属性 :
length:获取当前窗口访问过的URL数量
方法 :
back():相当于浏览器的后退按钮
forward():相当于前进按钮
go(num):参数可正可负,正值代表前进,负值代表后退
注意 :
1. 方法使用时,都是从当前页面在history中的位置开始,前进或者后退
2. 窗口的历史记录数量,跟随url变化自动添加,访问顺序决定历史记录的顺序.重复切换页面,不会影响历史记录的顺序和数量
4. location
操作当前窗口地址栏的信息
属性 :
href : 用来获取或设置当前窗口地址栏URL的信息;如果赋值,页面重定向,发生内容跳转
方法 : reload(param) 重载页面,相当于刷新
参数 : true/false
默认为false,从缓存中重载页面
true 从服务器根目录重新请求页面
重主要围绕document对象,实现对网页文档内容的操作
在JS中,认为HTML文件本身就是一篇文档,文档的层次结构,对应在JS中表现为节点树.
节点 : 网页在解析过程中,其中的标签,标签属性,文本内容都会被封装成一个节点
节点分类 :
1. 元素节点 -> 标签名
2. 属性节点 -> 标签属性
3. 文本节点 -> 文本内容
-----------------------
4. 文档节点 -> document
5. 注释节点 -> 网页中的注释
节点操作 :
1. 获取节点
2. 读取和修改节点内容
3. 创建节点
4. 添加节点
5. 删除节点
1. document.getElementsByTagName('div');
作用 : 通过标签名获取元素节点
返回值 : 节点列表(数组)
参数 : 字符串的标签名
2. document.getElementsByClassName('className');
作用 : 根据class属性值获取元素节点的数组
返回 : 节点列表
参数 : 字符串的class属性值
3. document.getElementById('id属性值');
作用 : 根据id属性值获取具体的元素节点
返回 : 节点对象
参数 : id属性值
4. document.getElementsByName("name");
作用 : 根据name属性值获取节点数组
练习 :
创建文本框和按钮,div
点击按钮时,获取文本框输入的内容,以一级标题的形式显示在div中 innerHTML
元素节点常用属性 :
1. innerHTML
读取或设置元素节点的标签内容,可以识别HTML标签语法
2. innerText
读取或设置元素节点的文本内容,不能识别标签语法
3. value
针对表单控件,表示表单元素的值
1. getAttribute('attrName')
根据属性名,获取属性值
2. setAttribute('attrName','attrValue');
为元素节点添加标签属性
3. removeAttribute('attrName');
移除指定属性
4. 标签属性也是元素节点对象的属性,可用点语法直接访问
例 : h1.id = "d1";
//避免与JS关键字冲突,标签属性class对应的属性名使用className表示
h1.className = "c1";
//移除属性值
h1.id = null;
练习 :
创建超链接,初始链接地址为百度
创建按钮,点击时修改超链接的链接地址,改为"http://www.tmooc.cn"
1. 为元素添加id/class属性,对应选择器样式
例 : h1.setAttribute('class','c1');
h1.className = "c1";
2. 操作行内样式
例 :
通过元素访问style属性,返回样式对象
h1.style : 样式对象
样式对象中包含全部的CSS属性,可以通过点语法直接操作
注 :
通过样式对象点语法访问CSS属性,对于带有连接符的属性一律更名为驼峰标识;
采用字符串为CSS属性赋值
h1.style.fontSize = "20px";
练习 :
1. 创建 div 文本框 按钮
要求用户名必须在6-18位之间
2. 点击按钮时,获取输入内容,进行验证
验证通过,设置div显示文本"用户名合法",并设置字体颜色为绿色
用户名不合法,设置div以红色文本色显示"不合法"
属性 : nodeType
返回 :
1 元素节点
2 属性节点
3 文本节点
8 注释节点
9 文档节点
属性 : nodeName
返回 :
元素节点 -> 标签名
属性节点 -> 属性名
文本节点 -> #text
注释节点 -> #comment
文档节点 -> #document
获取父节点
获取当前节点的所有子节点,返回子节点数组
(包含文本节点)
获取当前节点的所有元素子节点.返回子节点数组
(只包含元素,不包含文本节点)
获取下一个兄弟节点
nextElementSibling: 获取下一个元素兄弟节点
获取前一个兄弟节点
previousElementSibling: 获取前一个元素兄弟节点
获取当前元素节点中所有的属性节点,返回节点数组
1. 创建元素节点
var div = document.createElement('div'); 返回 : 创建成功的元素节点
2. 创建文本节点
var text = document.createTextNode('content'); 返回 : 创建成功的文本节点
3. 属性节点操作
标签属性可以通过元素节点直接访问
div.id = "d1";
练习 :
动态创建div,设置id为box;
文本内容为"动态创建的div"
控制台输出元素节点
节点的添加和删除必须由父元素操作
1. 添加在父元素的末尾
语法 :
parentNode.appendChild(childNode);
注意 :
文本节点也是元素节点的子节点
2. 在指定位置插入节点
语法 :
parentNode.insertBefore(newNode,oldNode);
在已有节点(oldNode)之前插入新节点(newNode)
注意 : 节点对象不能复用,页面中想出现几个节点,JS中需要动态创建几个节点,一一对应
语法 :
parentNode.removeChild(node);
从父元素中移除指定节点对象
练习 :
1. 静态页面 :
1. 顶部 三个输入框,一个按钮
2. 主体 表格,第一行表头信息
2. 动态添加
根据用户输入,创建行和单元格,添加到页面中显示
注意 : 表格的行分组<tbody>
系统提供的,在用户行为触发后,浏览器自动调用的函数
分类
1. 鼠标事件
onclick 单击事件
ondblclick 双击事件
onmouseover 鼠标移入
onmousemove 鼠标移动
onmouseout 鼠标移出
2. onload
文档或元素加载完毕后触发执行
3. 表单控件状态改变
onfocus 文本框获取到焦点时触发
onblur 文本框失去焦点时触发
oninput 实时监听文本框的输入
onchange 监听输入框前后输入内容是否
发生改变,要求输入框失去焦点并且前后内容不一致时触发
onsubmit 表单元素监听,点击提交按钮时
自动触发
4. 键盘事件
onkeydown 按键被按下
onkeypress 按键被按下
onkeyup 按键抬起
3.元素绑定事件的方式
1. 内联
通过标签属性的方式,将事件处理函数绑定到具体的元素上
ondblclick
2. 动态绑定事件
语法 :
h1.onclick = function (){
};
3. W3C标准事件监听
语法 :
h1.addEventListener('click',function,false);
参数 :
1. 省略'on'前缀的事件函数名
2. 事件触发后要执行的操作,以匿名函数或者函数名表示
3. 默认值为false,可省略,表示事件冒泡,设置true,表示事件捕获
事件传递机制 :
表示事件的传递顺序.
分类 :
事件冒泡 : 从里向外逐级传递事件,默认机制
事件捕获 : 从外向里逐级传递,IE不支持
1. window.onload = function (){};
等待窗口加载完毕后自动执行函数
2. form.onsubmit = function (){};
点击提交按钮时自动触发,执行处理函数.
函数中允许对表单数据做提交前的最后一步验证,通过返回值true/false控制数据是否可以提交给服务器.
true : 允许发送
false: 不允许发送
3. this关键字 :
默认情况下,指代函数或方法的调用对象
例 :
function f1(){
console.log(this);
}
f1();
window.f1();
1. 事件对象 : 伴随事件产生,浏览器自动封装的对象,包含了所有与当前事件相关的信息
2. 获取 :
事件对象会以参数的形式由浏览器自动传入事件处理函数中,我们只需要定义形参接收即可
例 : function f1(){ }
f1(100);
div.onclick = function (evt){};
3. 常用属性
不同的事件类型,事件对象中包含的信息也不同
1. srcElement/target
获取当前事件的触发对象
2. 鼠标事件对象
1. offsetX offsetY
获取鼠标在元素坐标系中的位置信息
以元素左上角为原点,向右向下为正方向,构建坐标系
2. clientX clientY
获取鼠标在网页窗口坐标系中的位置信息
3. screenX screenY
获取鼠标在屏幕坐标系中的位置信息
3. 键盘事件对象
1. onkeydown
1. which
获取当前按键的键码
2. onkeypress
只有在按下字符时才触发
1. which
获取当前按键字符的ASC码
2. key
获取字符
复习 : DOM
<h1 style = "" id="" class="">
h1.style
h1.id = "d1";
h1.className = "c1"
h1.style = "color:red;font-size:20px;";
h1.style.fontSize = "24px";
3. 层次属性
h1.parentNode;
//返回子节点数组,文本节点也是元素的子节点
h1.childNodes;
//返回元素子节点数组
h1.children;
h1.nextSibling;
h1.nextElementSibling;
h1.previousSibling;
h1.previousElementSibling;
//属性节点数组
h1.attributes;
4. 创建,添加和删除
document.createElement('');
parentNode.appendChild(elem);
parentNode.insertBefore(new,old);
parentNode.removeChild(elem);
5. 事件
1. 分类
onclick
ondblclick
onmouseover
onmousemove
onmouseout
-----------
onload
-----------
onfocus
onblur
oninput
onchange
onsubmit : form监听,点击提交按钮时触发,允许通过返回值true/false决定数据是否发送
-----------
onkeydown :按键被按下就触发
onkeypress : 按下字符按键时触发
onkeyup :按键抬起时触发
2. 绑定
1. <h1 onclick = "">
2. h1.onclick = function (){};
3. h1.addEventListener('click',func,false);
3. 事件对象
1. 获取
h1.onclick = function (event){
event.target; //事件触发对象
event.srcElement;
};
2. 鼠标事件对象
offsetX offsetY
clientX clientY
screenX screenY
3. 键盘事件对象
onkeydown/onkeyup
1. which :
获取键盘按键编码
2. key :
获取按键对应的字符(功能键的名称或者大小写字符)
onkeypress
1. which
获取按下字符的ASC码(区分大小写)
2. key
获取按下的字符(区分大小写)
复习 :
DOM
<h1 style = "" id="" class="">
h1.style
h1.id = "d1";
h1.className = "c1"
h1.style = "color:red;font-size:20px;";
h1.style.fontSize = "24px";
3. 层次属性
h1.parentNode;
//返回子节点数组,文本节点也是元素的子节点
h1.childNodes;
//返回元素子节点数组
h1.children;
h1.nextSibling;
h1.nextElementSibling;
h1.previousSibling;
h1.previousElementSibling;
//属性节点数组
h1.attributes;
4. 创建,添加和删除
document.createElement('');
parentNode.appendChild(elem);
parentNode.insertBefore(new,old);
parentNode.removeChild(elem);
5. 事件
1. 分类
onclick
ondblclick
onmouseover
onmousemove
onmouseout
-----------
onload
-----------
onfocus
onblur
oninput
onchange
onsubmit : form监听,点击提交按钮时触发,允许通过返回值true/false决定数据是否发送
-----------
onkeydown :按键被按下就触发
onkeypress : 按下字符按键时触发
onkeyup :按键抬起时触发
2. 绑定
1. <h1 onclick = "">
2. h1.onclick = function (){};
3. h1.addEventListener('click',func,false);
3. 事件对象
1. 获取
h1.onclick = function (event){
event.target; //事件触发对象
event.srcElement;
};
2. 鼠标事件对象
offsetX offsetY
clientX clientY
screenX screenY
3. 键盘事件对象
onkeydown/onkeyup
1. which :
获取键盘按键编码
2. key :
获取按键对应的字符(功能键的名称或者大小写字符)
onkeypress
1. which
获取按下字符的ASC码(区分大小写)
2. key
获取按下的字符(区分大小写)
-------------------------------------------
1. 介绍 : jQuery 是JavaScript工具库,封装了一套定义好的方法,简化JS操作
版本 : 1.xx.xx 包含IE6,7,8的兼容 2.xx.xx 不再兼容IE6,7,8
2. 功能和优势 :
3. 简化DOM操作,简化样式操作
4. 可以通过选择器直接获取元素和操作样式
5. 简化事件处理
6. Ajax技术更加简便和完善
7. 提供大量的特效或功能插件
8. 允许自定义插件
9. 使用 :
1. 引入jQuery
<script src=""></script>
注意 :引入操作必须在自定义的JS代码之前,否则无法使用jQuery语法
对原生JS对象进行封装之后,称为jquery对象
原生对象调用原生方法
jquery对象使用jquery提供的方法,不能混用
用来获取元素对象
通过传递参数执行获取
参数为字符串格式,传入选择器名称/DOM对象
选择器 :
"h1"
"#d1"
".c1"
"div h1"
练习 :
创建div/h1标签
通过$("selector")获取元素并输出
通过$()封装JS对象,返回jquery对象
注 : jquery对象使用$前缀,与原生对象区分
从jquery数组中取元素 var div = $div[0]; var div2 = $div.get(0);
说明:中可以接收选择器名称作为参数,匹配并返回元素对象,返回值是一个包含若干jquery对象的数组
语法 : $('selector');
(1) 基础选择器
id class tagName group 语法 :
1. $('#id')
2. $('.className')
3. $('tagName')
4. $('selector1,selector2')
(2) 级选择器
1. 后代选择器 $('selector1 selector2') 包含直接与间接子元素
2. 子代选择器 $('selector1>selector2') 匹配直接子元素
3. 相邻兄弟选择器 $('selector1+selector2') 匹配下一个兄弟元素,满足selector2则返回,否则匹配失败
4. 通用兄弟选择器 $('selector1~selector2'); 匹配selector1后面所有满足selector2的兄弟元素
(3) 过滤选择器 需要结合其他选择器使用
1. :first 匹配第一个元素 例 : $('p:first') 匹配第一个p元素
2. :last 匹配最后一个元素
3. :odd 匹配偶数行对应的元素(奇数下标)
4. :even 匹配奇数行对应的元素(偶数下标)
5. :eq(index) 匹配下标为index的元素
6. :lt(index) 匹配下标小于index的元素
7. :gt(index) 匹配下标大于index的元素
8. :not('selector1,selctor2') 表示除了指定选择器以外剩余的元素
(4) 属性选择器[]
1. [attrName] 匹配包含指定属性的元素
2. [attrName=value] 匹配属性名等于指定属性值的元素
3. [attrName^=value] 匹配属性值以指定字符开头的元素
4. [attrName$=value] 匹配属性值以指定字符结尾的元素
5. [attrName*=value] 匹配属性值中包含指定字符的元素
6. [attrName!=value] 匹配属性名不等于属性值的元素
(5) 子元素过滤选择器
1. :first-child 匹配第一个子元素
2. :last-child 匹配最后一个子元素
3. :nth-child(n) 匹配第n个子元素
html('')
设置或读取标签内容,可以识别标签语法,类似于
原生JS中的innerHTML
text('')
设置或读取标签内容,不能识别标签语法,类似
innerText
val('')
设置或读取表单控件的值,类似于原生value属性
练习 :
创建文本框,按钮,div
点击按钮时,将文本框的输入内容以一级标题的形式
显示在div中
使用jquery完成
1. attr('attrName','value')
设置或读取标签属性 例 : $('div').attr('id','d1'); console.log($('div').attr('id'));
2. prop('attrName','value') property 设置或读取标签属性
区分 : attr() prop()方法几乎一致,都表示属性操作
访问按钮checked属性时,取值不同
$('input').attr('checked');//checked="checked"
$('input').prop('checked');//checked="true"
3. removeAttr('attrName') 移除指定属性
1. attr()/prop()
为元素添加id/class属性,对应选择器样式
2. 操作类选择器
通过class属性值,结合选择器,修改样式
1. addClass('className')
为元素添加class属性值,可以反复调用,反复添加
2. removeClass('className');
移除指定的class属性值 省略参数,表示清空class属性值
3. toggleClass('className')
结合用户行为实现元素样式切换 元素存在指定className,就删除 不存在,则添加
3. 操作行内样式
1. css('color') 获取指定的CSS属性值
2. css('color','red') 设置元素样式
3. css(JSON对象) JSON对象 : 指定数据传输格式
使用 :
1. 使用{}表示JSON对象
2. CSS属性名和属性值都使用字符串表示
3. 属性名与属性值之间使用:隔开
4. 多组属性之间使用,隔开
例 :
css({
"width":"200px",
"height":"200px",
"background-color":"red"
})
练习 :
创建div,文本内容不限
使用css()设置:
200*200
背景色和文本色自定义
文本水平和垂直居中
元素居中
复习
1. 引入jquery文件
2. $/jQuery jquery对象 $() 工厂函数
3. 获取元素 $('selector') -> jquery对象 jquery对象与DOM互相转换:
1. dom->jquery : $(div)
2. jquery->dom : $('div')[0] / $('div').get(0)
4. 选择器 tag id class group 后代 自带 相邻兄弟选择器(+) 通用兄弟选择器(~) :first :last :eq(index) :lt(index) :gt(index) :odd :even :not() :first-child :last-child :nth-child(n) [attrName][attrName='value'] ^= $= != *=
5. 操作元素
6. 操作内容
html("")
text("")
val("")
7. 操作标签属性
attr('attrName','value') //checked
prop('attrName','value') //true
removeAttr('attrName')
8. 操作元素样式
1. 匹配类选择器
addClass('className') removeClass('className') toggleClass('className') 切换类名,匹配样式
2. 行内样式
css('attrName') css('attrName','value') css({ "width":"200px", "height":"200px" })
获取父节点
获取满足指定选择器的祖先元素,如果省略参数,返回所有祖先元素
获取所有的直接子元素
获取所有满足选择器的直接子元素
获取满足选择器的后代元素,包含直接与间接
参数省略的话,查找不到
获取下一个兄弟元素
获取下一个兄弟元素,要求满足selector,否则查找失败
获取上一个兄弟元素
获取上一个兄弟元素,要求满足selector,否则查找失败
获取所有兄弟元素
获取满足选择器的所有兄弟元素
语法1 :
var $div = $('<div></div>');
$div.html();
$div.attr();
$div.css();
语法2 :
//<h1 id='d1' style='color:red;'>一级标题</h1>
var $h1 = $("<h1 id='d1' style='color:red;'>一级标题</h1>")
$obj.append($new) 将 $new 作为 $obj 的最后一个子元素添加
$obj.prepend($new) 将 $new 作为 $obj 的第一个子元素添加
$obj.after($new) 将 $new 作为 $obj 的下一个兄弟元素添加
$obj.before($new) 将 $new 作为 $obj 的上一个兄弟元素添加
$obj.remove(); 删除$obj
// 方法一:
$(document).ready(function (){
//等待文档加载完毕后执行
});
// 方法二:
$().ready(function (){
//等待文档加载完毕后执行
});
// 方法三:
$(function (){
//等待文档加载完毕后执行
});
注意 :
原生onload事件不能重复书写,会被覆盖,只执行最后一次onload书写的代码
jquery中的ready方法,可以重复使用,相关函数会从上至下依次执行,不会产生覆盖问题
$obj.bind("事件名称",function)
参数 :
1. 事件名称 : 省略on前缀
2. function : 事件触发后执行的操作 例 :
$obj.bind('click',function (){});
$obj.事件名称(function) 事件名称作为方法名,直接绑定,省略on前缀 例 :
$obj.click(function (){});
事件对象的获取和属性操作与原生JS一致
例 :
$obj.click(function (evt){
//获取事件对象(参数接收)
console.log(evt);
//属性访问
console.log(evt.offsetX);
})
each(function (){
});
遍历数组或集合,每取出一个元素,自动执行函数
Flask 轻量级的WEB框架
AJAX 在WEB中完成异步的请求和响应
Django 重量级的WEB框架
Python WEB
1.静态网页 : 无法与服务器进行数据交互的网页
2.动态网页 : 允许与服务器进行数据交互的网页
1.WEB : 网页(HTML,CSS,JS)
2.服务器(Web Server)
能够给用户提供服务的机器就是服务器
1.硬件 和 软件
硬件 : 一台计算机
软件 : 一个能够接收用户请求并个给出响应的程序
1.作用
1.存储WEB的信息
2.能够处理用户的请求(request)和响应(response)
3.执行服务器端的处理程序
4.具备最基本的安全功能
2.服务器端的软件
1.APACHE
2.TOMCAT
3.IIS(Internet Information Service)
4.Nginx
1.什么是框架
框架是一个为了解决开放性问题而存在的一种程序结构
框架的本身提供了最基本的功能
我们只需要在框架的基础功能上搭建自己的操作就可以了
2.Python web 框架
1.Flask - 轻量级
2.Webpy - 轻量级
3.Tornado - 异步框架
4.Django - 重量级
3.框架模式
1.MTV(Flask,Django)
M : Models层,模型层,负责与数据库打交道
T : Templates层,模板层,处理用户显示的内容,如html
V : Views层,视图层,处理与用户打交道的内容(请求和响应)
2.MVC
M : Models层,模型层,负责与数据库打交道
V : Views层,视图层,处理用户显示的内容,如html
C : Controller层,控制器层,处理与用户打交道的内容(请求和响应)
M --- M
T --- V
V --- C
1.什么是Flask
Flask是一个基于Python并且依赖于Jinja2模板引擎和Werkzeug WSGI服务的一个微型框架(Micro Framework)
WSGI : Web Server Gateway Interface(WEB服务网关接口)
Flask是基于 MTV 框架模式开发出来的框架
2.安装Flask
1.查看已安装的Flask版本
在 python 的交互模式中
1.import flask
没报错 : 已经安装好了Flask,可以继续查看版本
报错 : 没安装Flask
2.flask.__version__
已安装Flask的情况下,查看安装的版本
2.安装Flask
sudo pip3 install flask
pip3 download flask
3.初始化Flask应用
见代码... ...
4.杀掉占用5000端口的进程
1.netstat -lptu
查看占用5000端口的进程ID
2.sudo kill -9 进程ID
将进程ID对应的程序杀掉
5.练习:
1.访问路径是 http://localhost:5000/login
在网页中显示:欢迎来到登录页面
2.访问路径是 http://localhost:5000/register
在网页中显示:欢迎来到注册页面
1.什么是路由
处理url和函数之间的关系的程序就是"路由"
@app.route('/login')
def login():
pass
2.路由的体现
在Flask中,路由是通过@app.route装饰器来表示的
1.基本的路由体现
http://localhost:5000/admin/login
@app.route('/admin/login')
def admin_login():
return "xxx"
2.带参数的路由
路由中可以携带参数来表示不同的数据
http://localhost:5000/show/wangwc
http://localhost:5000/show/gebilaowang
http://localhost:5000/show/chaogege
http://localhost:5000/show/xxx
1.基本带参路由
@app.route('/show/<name>')
def show(name):
# name 参数表示的就是由地址栏上传递进来的数据
pass
2.带多个参数的路由
多个参数使用 / 隔开,并继续使用 <> 来表示
@app.route('/show/<name>/<age>')
def show(name,age):
pass
3.指定参数类型的路由
使用 类型转换器 解决参数类型的问题
@app.route('/show/<name>/<int:age>')
def show():
name : 字符串类型的数据
age : 整数类型的数据
int:类型转换器
Flask中所支持的类型转换器
类型转换器 作用
缺省 字符串,不能有斜杠('/')
int: 整数
float: 浮点型
path: 字符串,允许有斜杠('/')
练习:
1.访问路径如下
http://localhost:5000/calc/数字1/数字2
2.根据以上的访问路径制定路由以及视图处理函数
3.在视图中,对两个数字进行相加,并响应在浏览器上
3.多 URL 的路由匹配
@app.route('/地址1')
@app.route('/地址2')
.... ....
def index():
return ""
练习:
当访问路径是以下任意一个的时候
http://localhost:5000
http://localhost:5000/index
http://localhost:5000/数字
http://localhost:5000/index/数字
将请求交给 index_views()去处理
判断路由中到底有没有数字传递进来:
如果有:
响应:您当前看的页数为 xxx
如果没有:
响应:您当前看的页数为 1
3.路由中设置允许接收的HTTP请求方法
所有的路由默认只接受get请求,不接受post请求
@app.route('/xxx',methods=['POST','GET'])
@app.route('/xxx',methods=['POST'])
4.URL的反向解析
正向解析:程序自动解析,会根据访问路径(@app.route('xxx')),自动来匹配处理函数
反向解析:通过视图处理函数的名称自动生成对应的访问路径
在Flask中要实现反向解析的话,需要使用:
from flask import url_for
url_for(funName,args)
funName : 要生成地址所对应的函数名
args : 该地址中要用到的参数
作业:
1.创建一个Flask项目 - Blog
2.在Blog中,创建 run.py 启动文件
3.在run.py中搭建好Flask程序结构
4.定义如下访问路径,并给出响应:
1.http://localhost:5000
响应:这是blog的首页
2.http://localhost:5000/list
响应:这是blog的列表页
3.http://localhost:5000/release
响应:这是blog的发表页
4.http://localhost:5000/info/<id>
响应:查看id为xxx的blog信息
http://localhost:5000/ : 访问index()
http://localhost:5000/index : 访问index()
1.什么是模板
模板,在Flask中就是允许给用户看的网页,动静结合的
动:允许包含服务器端的动态内容,如:变量,标签,过滤器,
静:纯HTML,CSS以及JavaScript的内容
在Flask中,模板是依赖于Jinja2的模板引擎
Jinja官网:http://jinja.pocoo.org/
2.模板的设置
默认情况下,Flask会在程序的主文件夹中会搜索一个templates的目录来作为模板的存放位置
需要手动的在程序中创建一个 templates 目录,并将所有的模板文件(html)都存放进去
3.模板的渲染
作用:在视图中,将模板文件(**.html)先变成字符串,再响应给浏览器
语法:
from flask import render_template
return render_template('xxx.html')
4.模板中的语法(重点)
1.变量
变量是一种特殊的占位符,告诉模板引擎,该位置的值是从渲染模板时的哪个数据中获取出来的
语法:
1.在视图中
@app.route('/xxx')
def xxx():
return render_template('xxx.html',变量1=值1,变量2=值2,... ...)
return render_template('01-template.html',name='wangwc',age=35)
2.在模板中
{{变量名}}
01-template.html 中:
{{name}}
练习:
创建 /03-template 路由,能够渲染 03-template.html模板,并在模板中输出以下内容:
歌名 : <<绿光>>
作词 : 宝强
作曲 : 乃亮
演唱 : 羽凡
允许传递到模板中作为变量的数据类型:字符串,整数,小数,列表,元组,字典,对象
2.过滤器
1.什么是过滤器
在变量输出前,允许修改变量的值,再进行输出
2.语法:{{变量|过滤器(参数)}}
常用过滤器:
过滤器名 说明
capitalize 首字符变大写,其他变小写
lower 将值转换为小写
upper 将值转换为大写
title 将值中的每个单词首字符变大写
trim 去掉值两端的空格
default('xx') 如果变量不存在,将采用default中的值作为默认输出
truncate(num[,bool]) 截取指定长度字符串,后面使用...显示
3.标签
1.什么是标签
在模板中,标签是属于服务器端内容
每个标签表示的是不同的服务器端的功能
2.常用标签
1. if 标签
1. 基本if标签
{% if 条件 %}
if条件为真的时候,要执行的内容
允许是 静态内容,也允许是动态内容
{% endif %}
2. if ... else 结构
{% if 条件 %}
...
{% else %}
...
{% endif %}
3. if ... elif ... elif 结构
{% if 条件1 %}
...
{% elif 条件2 %}
...
{% elif 条件3 %}
...
{% else %} -- 可选
...
{% endif %}
2. for 标签
{% for 变量 in 元组|列表|字典 %}
允许出现静态内容:html,css,js
允许出现动态内容:
变量 - {{}}
标签 - {% if %} {% endif %}
{% endfor %}
循环的内部变量 - loop
loop的作用:能够记载当前循环的一些相关信息
loop 常用属性:
1. index
作用:记录当前循环的次数,从1开始记录
2. index0
作用:同上,从0开始记录
3.first
作用:判断本次循环是否为第一次循环
值:True(是第一次循环) 或 False(非第一次循环)
4.last
作用:判断本次循环会否为最后一次循环
值:True(是最后一次循环) 或 False(非最后一次循环)
3. macro 标签 (宏)
1.作用
相当于是在模板中声明函数
2.语法
{% macro 名(参数列表) %}
xxx xxx
{% endmacro %}
3.在独立的模板文件中声明宏
1.创建 macro.html 模板文件
作用:定义项目中要用到的所有的宏
2.在使用的网页中,导入 macro.html 模板
{% import 'macro.html' as macros %}
4. include 标签
将其他的模板文件包含到当前的模板文件中
语法:{% include 'xxx.html' %}
5.静态文件的处理
1.什么是静态文件
在Flask中,不能与服务器做动态交互的文件称为静态文件
如:图片,css,js,音视频,文档... ...
2.静态文件的处理
1.所有的静态文件必须放在 static 目录中
static目录必须放在项目的根目录处
2.所有的静态文件必须通过 /static/ 路径进行访问
/static : 要到静态资源目录中进一步的搜索文件
http://localhost:5000/static/images/a.jpg
作业:
搭建Blog项目中的模板以及静态文件
在 Blog 项目的基础上,实现以下功能:
1.将所有的html页面导入到Blog项目中 -> templates
2.将所有的静态文件(css,js,图片)导入到Blog项目中 -> static
3.在模板中处理好所有的静态文件们
1.首页 - /
访问时,能够显示 index.html 中的内容
2.列表页 - /list
访问时,能够显示 list.html 中的内容
3.发布页 - /release
访问时,能够显示 release.html 中的内容
4.详情页 - /info/id
访问时,能够显示 info.html 中的内容
明天:
1.模板
模板继承
2.修改配置
3.请求(request) 和 响应(response)
1.服务器端
return render_template('xxx.html',var1=value1,var2=value2)
2.模板
{{var1}}
{{var|filter(parameters)}}
{{var|default('xxxx')}}
{{var|truncate(9,true)}}
1.if
{% if express %} ... {% endif %}
2.for
{% for var in iterator %}
{{loop.index}}
{{loop.index0}}
{{loop.first}}
{{loop.last}}
{% endfor %}
3.macro - 宏
相当于在模板中定义方法
声明:
{% macro 名(参数) %}
{% endmacro %}
调用:
{{名(参数)}}
将所有的宏声明在一个模板中 : macro.html
{% import 'macro.html' as macros %}
4.include
{% include 'xxx.html' %}
========================================================
根据静态文件的具体路径,生成静态访问路径
语法:
url_for('static',filename='file_path')
ex:
url_for('static',filename='images/a.jpg')
结果: /static/images/a.jpg
1.语法
1.父模板中
需要定义出那些东西在子模板中可以被重写
{% block 块名 %}
在父模板中可以正常显示的内容
{% endblock %}
block :
1.在父模板中可以正常显示,没任何影响
2.在子模板中可以被重写
2.子模板中
1.指定需要继承自哪个父模板
{% extends '父模板名称' %}
2.按需重写
{% block 块名 %}
此处编写的内容会覆盖掉父模板中同名block的内容
允许通过{{super()}}来调用父模板中的内容
{% endblock %}
1.构建Flask允许指定的配置信息
app=Flask(
__name__,
template_folder='xxx',
static_folder='xxx',
static_url_path='/xxx'
)
1.template_folder : 指定存放模板的文件夹的名称
2.static_folder : 指定存放静态文件资源的文件夹的名称
注意:如果没有指定static_url_path的话,则访问路径和static_folder 的名称是一致的
3.static_url_path : 指定静态文件的访问路径
2.启动程序的运行配置
app.run(debug=True,port=端口号,host='0.0.0.0')
host : 任何表示本机的地址都可以访问该项目
HTTP:Hyper Text Transfer Protocol
作用:规范了数据是如何打包以及传递的
1.通用消息
2.请求消息
1.请求起始行
1.请求方式 - GET / POST
2.请求协议 - http / https
3.协议版本 - 1.1
2.请求消息头
表达客户端浏览器要传递给服务器的信息
由 key:value 的形式组成
每个消息头会传递不同的信息给服务器
3.请求体
伴随着请求要传递给服务器端的信息就是请求体
只有 post 和 put 请求时有请求体的,其他请求方式没有请求体
3.响应消息
作用:将服务器端的信息传递给浏览器
1.响应起始行
1.协议以及版本号 : HTTP/1.1
2.响应状态码 : 200 / 404 / 500
1xx:请求已收到,继续处理
2xx:请求成功接收
3xx:该请求需要进一步处理
301 - 永久性重定向
302 - 临时性重定向
304 - 无修改,从缓存中提取数据
4xx:资源不存在或无权限
404 : 请求资源不存在
403 : Forbbiden
405 : Method Not Allowed
5xx:服务器处理请求失败
500 : Interneral Server Error
3.原因短句
以简短的英文单词解释响应状态码
200 : OK
404 : Not Found
2.响应消息头
以 key:value 的形式存在,要传递给浏览器的一些说明信息
ex:
Content-Type : application / javascript
Content-Type 作用:告诉浏览器响应回来的数据的类型
3.响应主体
request - 请求对象,封装了所有与请求相关的信息.如:请求数据,请求消息头,… …
在Flask中,要使用request的话,必须先导入:
from flask import request
允许在视图处理函数中使用request
1.request的常用成员
1.scheme : 获取请求协议
2.method : 获取本次请求的请求方式(GET / POST)
3.args : 获取以get请求方式提交的数据
4.form : 获取以post请求方式提交的数据
2.获取请求提交的数据
1.get 请求方式
1.地址栏上提交的数据
http://localhost:5000/04-request?name=abc&age=30
2.form表单中使用get方式提交
<form action="/04-request">
<input type="text" name="name">
<input type="number" name="age">
<input type="submit">
</form>
http://localhost:5000/04-request?name=abc&age=30
3.使用location.href
location.href="http://localhost:5000/04-request?name=abc&age=30"
2.post 请求方式
只有表单中设置method为post才能产生post请求
request.form 封装的就是以 post 方式请求提交过来的数据,允许按照字典的方式操作数据
request.form['控件的name值']
request.form.get('控件的name值')
作业:
1.处理 Blog 中的 登录 - login
1.如果是 get 请求,则渲染 login.html 到浏览器
2.如果是 post 请求,则接收所有的请求数据 并响应给 浏览器
2.处理 Blog 中的 注册 - register
1.如果是get请求,渲染register.html到浏览器
2.如果是 post 请求,接收所有的数据响应给浏览器
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__enter__', '__eq__', '__exit__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_cached_json', '_get_data_for_json', '_get_file_stream', '_get_stream_for_parsing', '_load_form_data', '_parse_content_type', 'accept_charsets', 'accept_encodings', 'accept_languages', 'accept_mimetypes', 'access_route', 'application', 'args', 'authorization', 'base_url', 'blueprint', 'cache_control', 'charset', 'close', 'content_encoding', 'content_length', 'content_md5', 'content_type', 'cookies', 'data', 'date', 'dict_storage_class', 'disable_data_descriptor', 'encoding_errors', 'endpoint', 'environ', 'files', 'form', 'form_data_parser_class', 'from_values', 'full_path', 'get_data', 'get_json', 'headers', 'host', 'host_url', 'if_match', 'if_modified_since', 'if_none_match', 'if_range', 'if_unmodified_since', 'input_stream', 'is_json', 'is_multiprocess', 'is_multithread', 'is_run_once', 'is_secure', 'is_xhr', 'json', 'list_storage_class', 'make_form_data_parser', 'max_content_length', 'max_form_memory_size', 'max_forwards', 'method', 'mimetype', 'mimetype_params', 'on_json_loading_failed', 'parameter_storage_class', 'path', 'pragma', 'query_string', 'range', 'referrer', 'remote_addr', 'remote_user', 'routing_exception', 'scheme', 'script_root', 'shallow', 'stream', 'trusted_hosts', 'url', 'url_charset', 'url_root', 'url_rule', 'user_agent', 'values', 'view_args', 'want_form_data_parsed']
1.Flask中数据加密 - 密码加密
1.注意问题
表单中如果有文件上传的时候,必须遵循以下两个要求:
1.提交方式 method 必须为 post
2.表单的 enctype 属性值必须为 multipart/form-data
2.服务器端处理
1.request.files 获取上传的文件
f = request.files['文件框的name值']
注意:获取到的f对象(文件),是保存在缓存区中,而并非保存在磁盘上
2.将文件保存到指定目录处
f.save('static/'+f.filename)
3.问题解决
1.文件名称
年月日时分秒微秒.扩展名
1.获取时间
import datetime ftime=datetime.datetime.now().strftime("%Y%m%d%H%M%S%f")
2.获取扩展名
ext = f.filename.split('.')[1]
3.组合成新文件名
fname = ftime+'.'+ext
2.保存路径
# 获取绝对路径
basedir=os.path.dirname(__file__)
# 拼成保存地址
upload_path=os.path.join(basedir,'static/upload',filename)
f.save(upload_path)
模型,是根据数据库中表的结构而创建出来的class
每一张表对应到编程语言中就是一个类
类中的每个属性对应到表中就是表的每个列
1.什么是ORM
ORM : Object Relational Mapping
对象 关系 映射
2.ORM的三大特征
1.数据表(table)到编程类(class)的映射
数据库中的每一张表对应到编程语言中都有一个类
2.数据类型的映射
数据库表中的列以及数据类型 对应到 类中也有对应的属性以及类型
3.关系映射
将数据库表与表之间的关系 对应到 编程语言中类与类之间的关系
3.ORM的优点
1.封装了数据库中几乎所有的操作,大大提高开发效率
2.省略了庞大的数据访问层,即便不使用SQL编码也能完成对数据的CRUD操作
C : Create
R : Retrieve
U : Update
D : Delete
Python中的ORM框架 - SQLAlchemy
pip3 install sqlalchemy
Flask中使用的也是 SQLAlchemy,但中间需要使用 Flask-SQLAlchemy 连接 Flask 和 SQLAlchemy
pip3 install flask-sqlalchemy
1.创建数据库
create database 数据库名 default charset utf8 collate utf8_general_ci;
推荐:
1.Navicate for MySQL
2.Power Designer
2.Flask中连接数据库
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
#指定数据库的配置给 app
app.config['SQLALCHEMY_DATABASE_URI']='mysql://root:123456@localhost:3306/flask'
#再将app交给SQLAlchemy,创建数据库实例
db = SQLAlchemy(app)
# 以后在Flask中操作数据库的时候可以使用 db
模型:类 (模型类 或 实体类)
语法:
class MODELNAME(db.Model):
__tablename__ = "TABLENAME"
COLUMN_NAME=db.Column(db.TYPE,OPTIONS)
COLUMN_NAME=db.Column(db.TYPE,OPTIONS)
... ...
1.MODELNAME:定义模型类的名称,尽量参考表名
2.TABLENAME:映射到数据库中表的名称
3.COLUMN_NAME:属性名,映射到数据表中列的名称
4.TYPE:映射到列的数据类型
5.OPTIONS:列选项,如:是否唯一,默认值,加索引...
db.TYPE 列类型如下:
类型名 python类型 说明
Integer int 普通整数,32位
SmallInteger int 小整数,16位
BigInteger int 不限精度整数
Float float 浮点数
Numeric deciaml.Decimal 定点数
String str 字符串
db.String(30)
Text str 字符串
Boolean bool 布尔值
db.Boolean -> tinyint
Date datetime.date 日期:年月日
Time datetime.time 时间:时分秒
DateTime datetime.datetime 日期和时间:年月日时分秒
OPTIONS 列选项:
选项名 说明
autoincrement 如果设置为True表示该列要自动增长
primary_key 如果设置为True表示该列为主键
unique 如果设置为True表示该列的值唯一
index 如果设置为True表示该列创建索引
nullable 如果设置为True表示该列允许为空 默认是非空 - False
default 为列指定默认值
练习:
1.创建Student实体类
表名:student
属性: 1.id : 主键自增
2.sname : 姓名,长度为30的字符串
3.sage : 年龄,整数
4.isActive : 启用状态,默认为True
2.创建Teacher实体类
表名:teacher
属性: 1.id : 主键自增
2.tname : 姓名,长度为30字符串
3.tage : 年龄,整数
3.创建Course实体类
表名:course
属性: 1.id , 自增,主键
2.cname,课程名称,长度为50的字符串,允许为空
作业:
1.创建数据库 Blog
2.分析login 以及 regsiter 的业务,并得出 用户实体类
3.根据分析出来的用户实体,创建实体类(属性),并映射回数据库
表名: users
类名: Users
聚集索引 和 非聚集索引
"a.jpg".split('.')[1]
1.什么是映射管理
对模型类/实体类的修改允许再映射回数据库
2.依托于第三方库完成管理
1.flask-script
pip3 install flask-script
包:flask_script
类:Manager
作用:可以对项目进行管理,如:启动项目,添加命令
2.flask-migrate
pip3 install flask-migrate
包:flask_migrate
类:
1.Migrate
作用:用于管理 app 和 db 之间的协调关系
2.MigrateCommand
作用:允许在终端中提供实体类迁移的命令
3.实现数据库的迁移
1.python3 run01.py db init
作用:做一些初始化的行为操作
特点:一个项目中只执行一次就可以了
2.python3 run01.py db migrate
作用:将编写好的实体类生成中间文件
特点:只要检测到实体类有修改,就会生成中间文件
3.python3 run01.py db upgrade
作用:将中间文件映射回数据库
1.创建实体的对象,并为属性赋值
user = User()
user.uname = 'wangwc'
user.age = 18
2.将实体对象增加回数据库
db.session.add(实体对象)
#针对非查询操作,必须要手动提交回数据库
db.session.commit()
3.配置操作自动提交
针对所有非查询操作
配置成功后,会在执行完视图之后,整体将行为提交回数据库
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN']=True
1.基于 db.session 的查询
1.db.session.query()
该函数会返回一个Query对象,类型为BaseQuery
该返回值中会包含针对某个实体或实体中的列所有的查询操作
语法:
1.db.session.query(实体类)
查询对应实体类中所有列的数据
ex:
db.session.query(User)
等同于:select * from user
2.db.session.query(实体类.属性1,实体类.属性2)
查询对应实体类中部分列的数据
ex:
db.session.query(User.id,User.uname)
等同于:select user.id,user.uname from user
2.查询执行函数
目的:在query()的基础上的得到最终的数据
语法:db.session.query(xxx).查询执行函数()
函数 说明
all() 以列表的方式返回query()中所有的数据
first() 以实体对象的方式返回query()中的第一条数据,如果没有结果,则返回None
first_or_404() 效果同上,如果查询不到数据,则响应404
count() 返回查询结果的数量
3.查询过滤器函数
作用:在db.session.query()的基础上,进行条件筛选
语法:db.session.query().查询过滤器函数().查询执行函数()
过滤器函数 说明
filter() 按指定条件进行过滤
filter_by() 按等值条件过滤时使用
limit() 获取前几行数据
order_by() 排序
group_by() 分组
过滤器函数的详解:
1.filter()
作用:实现查询中的各种条件
注意:条件必须由 实体类.属性 构成
1.查询年龄大于17的user的信息
db.session.query(User).filter(User.uage>17).all()
2.查询年龄大于17并且id大于1的user的信息
db.session.query(User).filter(User.uage>17,User.id>1).all()
3.查询年龄大于17或者id大于1的user的信息
注意:查询 或 的操作,要借助于 or_()
用法:or_(条件1,条件2)
db.session.query().filter(or_(xxx)).all()
4.查询id的值为2的user的信息
注意:等值判断要用 ==
db.session.query().filter(User.id==2).first()
5.查询uemail中包含 w 的user的信息
select * from user where uemail like '%w%'
注意:模糊查询like需要使用实体类的属性所提供的like()完成查询
db.session.query(User).filter(User.uemail.like('%w%')).all()
6.模糊查询 - in
注意:模糊查询in需要使用实体类的属性所提供的in_()完成查询
db.session.query(User).filter(User.uage.in_([15,17,19])).all()
7.模糊查询 - between and
注意:模糊查询between and 需要使用实体类的属性所提供between(值1,值2)完成查询
db.session.query(User).filter(User.uage.between(13,15)).all()
2.filter_by()
作用:只做等值条件筛选过滤,并且只用于单表查询
特点:
1.不用 实体类.属性名,直接使用 属性名即可
2.不用 == ,而用 =
db.session.query(User).filter_by(id=1).first()
3.limit()
作用:获取前几行数据
语法:db.session.query(User).limit(num).all()
1.db.session.query(User).limit(1).all()
获取前1条数据
2.使用 offset() 可以完成数据的偏移
db.session.query(User).limit(2).offset(3).all()
跳过前3条数据,再获取剩余的前2条数据
4.order_by()
1.User表中的数据按id降序排序
db.session.query(User).order_by("id desc")
2.User表中的数据按年龄升序排序,id降序排序
db.session.query(User).order_by("age,id desc")
练习:
1.访问路径 /03-queryall
2.能够渲染 03-queryall.html 模板
3.在模板中显示
用表格显示以下内容:
id 姓名 年龄 邮箱 操作
1 wangwc 16 xxxx@163 删除 修改
2 Rapwang 18 xxxx@163 删除 修改
select * from user limit 2,3
会话
ID:xxx 姓名:xxxx 年龄:xxxx 邮箱:xxxx
ID:xxx 姓名:xxxx 年龄:xxxx 邮箱:xxxx
1.增加
1.创建实体对象
2.通过db.session.add()
3.提交
1.手动提交
db.session.commit()
2.自动提交
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN']=True
2.查询
1.基于 db.session 的查询
1.db.session.query()
会返回一个query对象,类型BaseQuery
语法:
db.session.query(实体类|实体类.属性)
2.查询执行函数
作用:在基础查询上得到想要的数据
函数:
1.all()
2.first()
3.first_or_404()
4.count()
3.查询过滤器函数
db.session.query().查询过滤器().查询执行函数()
1.filter()
1. filter(User.id==1)
2. filter(User.id>1)
3. filter(User.id>1,User.age>30)
4.from sqlalchemy import or_
filter(or_(User.id>1,User.age>30))
5.filter(User.name.like('王%'))
6.filter(User.addr.in_(['北京','上海','天津','重庆']))
7.filter(User.age.between(35,50))
2.filter_by()
filter_by(id=1)
3.limit()
db.session.query().limit(2).offset(5)
db.session.query().filter().limit().offset()
4.order_by()
db.session.query().order_by("id,age desc")
db.session.query().filter().order_by()
2.基于 实体类 的查询
====================================================
1.聚合查询
1.基本聚合查询
from sqlalchemy import func
# func对象中提供了所有的聚合函数
db.session.query(func.聚合函数(实体类.属性)).all()
聚合函数:
sum() : 求和
count() : 求非空的数量
max() : 求最大值
min() : 求最小值
avg() : 求平均值
#查询user表中所有人的平均年龄(uage)是多少??
db.session.query(func.avg(User.uage)).first()
2.分组聚合查询
db.session.query(聚合).group_by('属性名').all()
练习:
1.为 User 实体类增加一个属性 isActive(为user表增加一个列isActive),默认值为True
2.到数据库中随意修改几条数据的 isActive 的值为False
3.在程序中实现,统计被激活的用户数量以及未被激活的用户数量分别是多少并打印输出
被激活: isActive = True
3.带条件的分组聚合
db.session.query(聚合).filter(条件).group_by(分组).having(分组后条件)
ex:
在 user 表中要统计大于16岁的用户的激活人数和未激活人数,并输出大于2人的信息
2.基于实体类进行查询
MODELS.query.查询过滤器函数(条件参数).查询执行函数()
ex:查询user表(User类)中所有的数据
1.使用 db.session
db.session.query(User).all()
2.使用 实体类
User.query.all()
ex:查询id为1的user的信息
1.使用db.session
db.session.query(User).filter_by(id=1).first()
2.使用 实体类
User.query.filter_by(id=1).first()
User.query.filter(User.id==1).first()
1.查
将要修改的信息查询出来
2.改
通过实体对象.属性 = 值
3.保存
db.session.add(实体对象)
1.查
查询出要删除的实体对象
2.删
db.session.delete(要删除的实体对象)
重定向:在服务器端,指定重新向一个新的地址发送请求
1.一对多
1.什么是一对多
A表中的一条数据能够关联到B表中的多条数据
B表中的一条数据能够关联到A表中的一条数据
ex:
1.博客系统中的用户与发表的文章
1个用户允许发表多篇文章
1篇文章只能由一个用户发表
2.老师(Teacher) 与 课程(Course)
1名老师只能教授一门课程
一门课程可以被多名老师所教授
课程(1) : 老师(M)
2.一对多在数据库中的实现
依托于 主外键 关系创建
在"多"表中增加外键 要 引用自"一"表的主键依托于 主外键 关系创建
在"多"表中增加外键 要 引用自"一"表的主键
3.在 Flask-SQLAlchemy 上的实现
在"多"实体类中增加对"一"实体类的引用
1.在 "多" 实体类中:
增加一个列,引用自"一"表(类)的主键
外键列名=db.Column(db.Integer,db.ForeignKey('主键表.主键列'))
ex: 模拟 Course(1) 类 与 Teacher(多) 类
2.在"一"实体类中:
增加关联属性以及反向引用关系属性(难点)
1.关联属性:
在"一"的实体中,要通过哪个<<属性>>来获取到对应的所有的"多"的实体对象们
2.反向引用关系属性:
在"多"的实体中,要通过哪个<<属性>>来获取对应的"一"的实体的对象
语法:
属性名=db.relationship('多实体类名',backref='反向引用关系属性名称',lazy='dynamic')
ex:
class Teacher(db.Model):
xxxx xxxx
course_id = db.Column(
db.Integer,
db.ForeignKey('course.id')
)
class Course(db.Model):
xxx xxx
#增加关联属性以及反向引用关系属性
teachers=db.relationship('Teacher',backref='course',lazy='dynamic')
2.一对一
3.多对多
course = Course.query.filter_by(id=1)
可以通过 course.teachers 来得到对应的所有的老师的信息
SELECT user.`isActive` AS `user_isActive`, count(user.`isActive`) AS count_1
FROM user
WHERE user.uage > %(uage_1)s GROUP BY user.`isActive`
HAVING count(user.`isActive`) > %(count_2)s
select xxxxxx
from xxx
where
group by xxx
having xxx
#查询user表中所有的用户的年龄(uage)的和是多少
select sum(uage) as 'sumAge',avg(uage) as 'avgAge' from user
select uid,uname,uemail,uage > (select uage from xxx where ...) from user
inner join course on xxx where xxx
[
(Decimal('16.0000'), Decimal('16')),
(Decimal('18.0000'), Decimal('18')),
(Decimal('38.0000'), Decimal('114'))
]
[
(16, Decimal('16.0000'), Decimal('16')),
(18, Decimal('18.0000'), Decimal('18')),
(38, Decimal('38.0000'), Decimal('114'))
]
在Flask中:
1.在"多"类增加一个属性,表示对"一"类进行引用
属性 = db.Column(db.Integer,db.ForeignKey("主表.主键"))
2.在"一"类增加关联属性和反向引用关系属性
如:Course类(course表) 和 Teacher类(teacher表)
关联属性:在Course类中增加的一个属性,表示对应的所有的Teacher对象
反向引用关系属性:在Teacher类中增加一个属性,表示对应的Course对象是谁
属性名=db.relationship(
"多类名",
backref="反向引用关系属性名",
lazy="dynamic"
)
lazy : 指定延迟加载模式,指定如何加载关联数据
1.select
首次访问时,加载关联数据
2.immediate
源对象使用后,马上加载关联数据
3.subquery
效果同上,但是会使用子查询的方式加载关联数据
4.noload
永不加载记录
5.dynamic
默认不加载记录,但会提供加载记录的查询
class Course(db.Model):
__tablename__ = "course"
id = db.Column(db.Integer,primary_key=True)
xxxx xxxx
#关联属性和反向引用关系属性
teachers = db.relationship(
"Teacher",
backref='course',
lazy="dynamic")
class Teacher(db.Model):
__tablename__ = "teacher"
xxxx xxxx
#外键引用
course_id = db.Column(db.Integer,db.ForeignKey('course.id'))
1.什么是一对一
A表中的一条记录只能与B表中的一条记录相关联
B表中的一条记录只能与A表中的一条记录相关联
2.在数据库中的体现
关联的两张表的任意一张表中:
增加外键,引用自另外一张表的主键,并施加唯一约束
3.在实体类中的体现
1.在任意一个类中增加:
外键列名=db.Column(db.Integer,db.ForeignKey('主表.主键'),unique=True)
class User(db.Model):
__tablename__ = "user"
xxxx xxxx
class Wife(db.Model):
__tablename__ = "wife"
xxxx xxxx
user_id=db.Column(db.Integer,db.ForeignKey('user.id'),\
unique=True)
2.在另外一个实体类中增加:
关联属性 和 反向引用关系属性
属性 = db.relationship(
"关联的实体类",
backref="反向引用关系属性名称",
uselist=False
)
uselist : 该属性将使用标量来表示,而不是列表
class User(db.Model):
__tablename__ = "user"
xxxx xxxx
wife = db.relationship("Wife",backref="user",uselist=False)
class Wife(db.Model):
__tablename__ = "wife"
xxxx xxxx
user_id=db.Column(db.Integer,db.ForeignKey('user.id'),\
unique=True)
练习:完成一对一的查询操作
1.一对多关系映射
2.一对一关系映射
class User(db.Model):
xxxx
wife=db.relationship("Wife",backref="user",uselist=False)
class Wife(db.Model):
xxxx
user_id=db.Column(db.Integer,db.ForeignKey('user.id'),unique=True)
1.什么是多对多
A表中的一条数据可以与B表中的任意多条数据相关联
B表中的一条数据可以与A表中的任意多条数据相关联
2.在数据库中的体现
在数据库中使用第三张关联表
3.在Flask-SQLAlchemy中的实现
1.创建关联表(实体类)
class TeacherStudent(db.Model):
__tablename__ = "teacher_student"
id=db.Column(db.Integer,primary_key=True)
teacher_id=db.Column(db.Integer,db.ForeignKey
('teacher.id'))
student_id=db.Column(db.Integer,db.ForeignKey
('student.id'))
2.增加关联属性 和 反向引用关系属性
class Teacher(db.Model):
__tablename__ = "teacher"
xxx xxx
students = db.relationship(
"Student",
secondary="teacher_student",
lazy="dynamic",
backref=db.backref("teachers",lazy="dynamic")
)
1.什么是cookies
cookies是一种数据存储手段
将一段文本保存在客户端(浏览器)的一种存储手段,并可以长时间保存
2.cookies的使用场景
1.记住密码
2.记住搜索关键词
3.特点
1.cookies是以浏览器为单位,不同的浏览器之间的cookies是不共享的
2.各个网站之间的cookies也是相互独立的,不共享
优点:
1.可以解决服务器端的一些存储问题
允许将非重要的数据保存在客户端浏览器中,从而节省服务器端的位置
2.可以长时间保存数据
缺点:
1.明文显示所有的数据
2.cookie中的内容在客户端是允许被修改的
3.Flask中使用 cookies
1.保存cookies
要通过 响应对象 将cookies从服务器端带到浏览器上
响应对象:
1.resp = redirect('/重定向地址')
resp 是一个响应对象
2.from flask import make_response
resp = make_response("字符串"|render_template())
resp 是一个响应对象
return resp
添加cookies的语法
响应对象.set_cookie(key,value,max_age)
key:要保存的cookie的名称
value:要保存的cookie的值
max_age:该cookie存活的最大时间(以s为单位,但s省略不写)
1. 1 表示1秒
2. 60 表示1分钟
3. 60*60 表示1小时
4. 60*60*24 表示1天
5. 60*60*24*365 表示1年
ex:
from flask import make_response
@app.route('/01-addcookie')
def addcookie_views():
resp=make_response("添加cookie成功")
resp.set_cookie("uname","wangwc",60*60*24*365)
return resp
2.获取cookies
每当浏览器向服务器发送请求时,都会把当前站点的cookies们都封装到request中并带到服务器上
语法:
request.cookies
3.删除cookies
响应对象.delete_cookie('key')
1.什么是session
session是保存在服务器上,为每个浏览器所开辟的一段空间
2.保存进session的数据
服务器端在会话过程中经常要用到的数据要保存进session
3.session在Flask中的实现手段
1.配置 SECRET_KEY
app.config['SECRET_KEY']='aixieshaxiesha'
2.使用session
from flask import session
1.保存数据到session中
session['key'] = value
2.从session中获取数据
value=session['key']
value=session.get('key')
if 'key' in session:
xxxx xxxx
3.从session中删除数据
del session['key']
{
'csrftoken': 'HCDh1rsAlRRvdc3T9grSbW2nLGtZT8Ih6Ljqm0zvkEKnVfFS9pEpC0rD5MzBPtjy',
'uname': 'wangwc',
'Pycharm-b723704f': '18dbae5b-b244-47d1-80f5-c6ea522f3ef9'
}
resp = redirect('/')
return resp
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fkVoXitO-1603212105538)(C:\Users\Administrator\Desktop\python复习\登录流程_看图王.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tocBH57n-1603212105540)(C:\Users\Administrator\Desktop\python复习\练习1-cookie_看图王.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MKPLXuYW-1603212105541)(C:\Users\Administrator\Desktop\python复习\练习2-session_看图王.png)]
Asynchronous Javascript And Xml
Asynchronous : 异步的
Xml : eXtensible Markup Language
可扩展的标签语言
JSON:JavaScript Object Notation,用来取代繁琐的xml
解释:通过JS异步的向服务器发送请求,并接收响应回来的XML(JSON)格式的数据
同步请求:
当客户端向服务器发送请求时,服务器在处理的过程中,浏览器只能等待,效率低
异步请求:
当客户端向服务器发送请求时,服务器在处理的过程中,客户端可以做其他的操作,不需要一直等待
AJAX优点:
1.异步 访问
2.局部 刷新
使用场合:
1.搜索建议
2.表单验证
3.前后端完全分离
1.异步对象 - XMLHttpRequest
简称为 xhr
称为"异步对象",代替浏览器向服务器发送异步的请求并接收响应
2.创建异步对象
主流的异步对象是 XMLHttpRequest 类型的,并且主流的浏览器(IE7+,Chrome,Firefox,Safari,Opera)全部都支持XMLHttpRequest。但在IE低版本的浏览器中(IE7以及以下),就不支持XMLHttpRequest。使用 ActiveXObject() 来创建异步对象
支持XMLHttpRequest:
var xhr = new XMLHttpRequest();
不支持XMLHttpRequest:
var xhr = new ActiveXObject("Microsoft.XMLHTTP");
练习:根据不同的浏览器支持性创建不同的异步对象
1.声明一个方法 - createXhr()
2.方法中判断浏览器支持 XMLHttpRequest 还是 ActiveXObject
3.根据支持性创建不同的异步对象并返回
Django
2005年发布,采用Python语言编写的开源框架
早期的时候Django主要做新闻以及内容管理的网站
Django中自带强大的后台管理功能
版本:2.1.5
使用:1.11
官网:http://www.djangoproject.com
中文文档:http://djangobook.py3k.cn/2.0/
MTV:
M -- Models
T -- Templates
V -- Views
1.查看已安装的版本
1.进入到python交互模式
python3 / ipython3
2.输入 import django
3.输入 django.VERSION
2.安装
使用 pip3
pip3 install django
(安装Django的最新版本)
pip3 install django==1.11.8
(安装Django的指定版本)
1. 创建项目的指令
指令:django-admin
语法:django-admin startproject 项目名
2.Django项目的目录结构
1.manage.py
功能:包含项目管理相关的子命令
如:
启动服务:runserver
创建应用:startapp
创建管理员:createsuperuser
数据迁移:migrate
.... ....
2.主文件夹(与项目名称一致的文件夹)
1. __init__.py
项目初始化文件,服务启动时自动运行
2.wsgi.py
Web服务网关接口的配置文件
部署项目时使用
3.urls.py
项目的基础路由配置文件
所有动态路径必须走该文件进行匹配
4.settings.py
功能:项目的主配置文件,启动服务时自动调用
1.BASE_DIR
作用:表示当前项目的绝对路径
2.DEBUG
作用:是否启用条用模式
取值:
1.True
使用调试模式
(开发阶段推荐使用)
2.False
不使用调试模式
(生产环境中要使用)
3.ALLOWED_HOSTS
作用:设置允许访问到本项目的地址列表
取值:
1.如果为空
表示只有localhost或127.0.0.1能访问
2.['*']
任何表示本机的地址都能访问当前项目
如:
localhost / 127.0.0.1 / 0.0.0.0 / IP地址
注意:如果要在局域网内被访问的话
./manage.py runserver 0.0.0.0:端口号
4.INSTALLED_APPS
作用:指定已安装的应用
5.MIDDLEWARE
作用:注册中间件
6.TEMPLATES
作用:指定模板的配置信息
7.DATABASES
作用:指定数据库的配置信息
8.LANGUAGE_CODE
作用:指定语言设置
取值:中文:zh-Hans
9.TIME_ZONE
作用:指定时区
取值:中国时区:Asia/Shanghai
1.urls.py
默认在主文件夹中,主路由配置文件,包含最基本的路由-视图的映射关系
该模块文件中会包含 urlpatterns 的列表,用于描述路由-视图的映射
在urlpatterns中,通过若干 url() 来表示具体的路由-视图映射关系
2.url() 的语法
from django.conf.urls import url
语法:
url(regex,views,kwargs=None,name=None)
1.regex:字符串类型,匹配的请求路径,可以是正则
2.views:指定地址所对应的视图处理函数的名称
3.kwargs:向views传参
4.name:为url起别名,在地址反向解析时使用
3.带参数的url
http://localhost:8000/show-02/2019
http://localhost:8000/show-02/1996
使用正则表达式的子组进行传参 - ()
一个子组是一个参数,多个参数的话要使用多个子组,并且使用 / 隔开
http://localhost:8000/show-02/xxxx
xxxx表示的是四位数字
urlpatterns = [
url(r'^show-02/(\d{4})/$',views.show_02)
]
def show_02(request,year):
year:表示的就是地址中的第一个子组对应的参数
练习:
访问地址: http://localhost:8000/show_03/四位整数/两位整数/两位整数
最终输出:生日为:xxxx年xx月xx日
ex: http://localhost:8000/1977/11/11
最终输出:生日为:1977年11月11日
1.什么是应用
应用是WEB项目中的一个独立的业务模块,可以包含自己的路由,视图,.... ....
在Django中,主文件夹不再处理用户的具体请求。主文件夹的主要工作就是项目的初始化以及请求的分发(分布式请求处理),具体的请求由应用(app)进行处理的
2.创建 & 配置应用
1.创建应用的指令
./manage.py startapp 应用名称
ex:
./manage.py startapp music
2.配置应用
在 settings.py 中进行应用的注册
INSTALLED_APPS = [
... ...,
'自定义的应用名称'
]
3.应用的结构组成
1.migrations 文件夹
保存数据迁移的中间文件
2.__init__.py
应用的初始化文件
3.admin.py
应用的后台管理配置文件
4.apps.py
应用的属性配置文件
5.models.py
与数据库相关的模型映射类
6.tests.py
应用的单元测试文件
7.views.py
定义视图处理函数的文件
4.分布式路由系统
如果访问路径是:
http://localhost:8000/music/xxx
则将请求转交给music应用中的urls进一步处理
作业:
1.创建一个Django项目 - DjangoDemo01
2.创建以下应用们,并注册:
1.创建 index 应用
2.创建 music 应用
3.创建 sport 应用
4.创建 news 应用
3.创建分布式路由访问系统
主文件夹只做路由的分发
每个应用只处理与自己相关的业务(路由和视图)
1.localhost:8000/index/index
交给 index 应用中的 index() 函数处理
2.localhost:8000/music/index
交给 music 应用中的 index() 函数处理
3.localhost:8000/sport/index
交给 sport 应用中的 index() 函数处理
4.localhost:8000/news/index
交给 news 应用中的 index() 函数处理
1.路由改版
访问路径 :localhost:8000/music/index
改版路径 :localhost:8000/music/
访问 index() 视图处理函数
访问路径 :localhost:8000/index/index
改版路径 :localhost:8000/
访问 index 应用中的 index()视图函数
访问路径 :localhost:8000/login
访问 index 应用中的 login()视图函数
访问路径 :localhost:8000/register
访问 index 应用中的 register()视图函数
1.Django中的模板
Django中的模板引擎是由Django自己提供,并不是Jinja2,索引Django中的模板语法与 Flask中的模板语法会稍有不同
2.模板的配置
在 setting.py 中有一个 TEMPLATES 变量
1.BACKEND:指定模板的引擎
2.DIRS:指定存放模板的目录们
1.如果写东西:则按照写好的路径去查找模板
2.保存为空:Django会自动的到每个应用中的templates目录中去查找模板文件
推荐:'DIRS': [os.path.join(BASE_DIR, 'templates')]
3.APP_DIRS
是否要搜索应用中的指定名称的目录们
3.模板的加载方式
1.通过loader获取模板,通过HttpResponse响应
from django.template import loader
#1.通过 loader 加载模板
t = loader.get_template("模板名称")
#2.将模板转换成字符串
html = t.render()
#3.再通过HttpResponse进行响应
return HttpResponse(html)
2.使用 render() 直接加载并响应模板
from django.shortcuts import render
return render(request,'模板的名称')
4.模板的语法
1.变量
1.作用
传递后端的数据到模板上进行显示
2.允许做为变量的数据类型
字符串,数字,列表,元组,字典,函数,对象
3.变量的语法
变量必须封装到字典中才允许传递到模板上
dic = {
"变量1":"值1",
"变量2":"值2",
... ...
}
1.使用 loader 加载模板
t=loader.get_template('xxx.html')
html=t.render(dic)
return HttpResponse(html)
2.使用 render 渲染模板
return render(request,'xxx.html',dic)
4.在模板中使用变量:{{变量名}}
2.标签
1.作用
将服务器端一些功能嵌入到模板中
2.语法
{% 标签内容 %}
{% 结束标签 %}
1.for 标签
1.语法:
{% for 变量 in 可迭代变量 %}
{% endfor %}
2.内置变量 - forloop
1. forloop.counter
得到当前循环遍历的次数
2. forloop.counter0
得到当前循环遍历的下标
3. forloop.first
是否为第一次循环
4. forloop.last
是否为最后一次循环
2.if 标签
1.作用
在模板中完成判断的操作
2.语法
1. if
{% if 条件 %}
满足条件时执行的内容
{% endif %}
2. if ... else
{% if 条件 %}
满足条件执行的内容
{% else %}
不满足条件时执行的内容
{% endif %}
3. if ... elif ... else
{% if 条件1 %}
{% elif 条件2 %}
{% elif 条件3 %}
{% else %}
{% endif %}
3.过滤器
1.作用: 在变量输出前对变量的值进行筛选或过滤
2.语法: {{变量|过滤器:参数值}}
3.常用过滤器
4.静态文件
1.静态文件的配置
在 settings.py 中设置以下两点:
1.静态文件访问路径
通过哪个地址访问静态的资源们
STATIC_URL = '/static/'
static 就是访问静态资源的路径
2.静态文件存储路径
指定静态文件要存放在服务器的哪个目录
STATICFILES_DIRS=(os.path.join(BASE_DIR,'static'),)
2.访问静态文件
1.使用 静态文件访问路径 进行访问
http://localhost:8000/static/xxxx
ex:
<img src="http://localhost:8000/static/images/b04.jpg">
<img src="/static/images/b04.jpg">
2.使用{% static %}进行访问
{% static %} 表示的就是静态资源访问路径
1.加载 static
{% load static %}
2.使用静态资源时
<img src="{% static 'images/a.jpg' %}">
练习:
1.创建Django项目 - FruitDay
2.创建应用 - index
3.配置路由
http://localhost:8000/xxxx
一律交给index的路由做进一步的处理
4.将html阶段中
将 果园的首页,登录页 以模板的方式设置到 FruitDay项目中以及配置好所有的静态文件
5.
首页:http://localhost:8000
登录:http://localhost:8000/login/
5.模板的继承
1.语法
1.在父模板中
要标识出哪些内容在子模板是允许被修改的
{% block 块名 %}
{% endblock %}
block作用:
1.在父模板中,正常显示
2.在子模板
不重写,采用父模板中的效果
重写,则按照重写的效果显示
2.在子模板中
1.指定继承自哪个模板
{% extends '父模板名称' %}
2.重写父模板中的内容
{% block 块名 %}
{% endblock %}
6.url()的name参数
1.url的语法
url(regex,views,kwargs,name='别名')
name:为了给当前的url起别名,反向解析时使用
url(r'^user_login/$',views.login,name='log')
2.反向解析
1.在模板上做反向解析
{% url '别名' %}
{% url '别名' '参数1' '参数2' %}
2.使用场合
1.访问路径过长时,推荐使用别名访问
2.访问地址经常变换时,推荐使用别名
ORM :Object Relational Mapping
三大特征:
1.表 到 类的映射
2.数据类型的映射
3.关系映射
1.创建数据库
create database webdb default charset utf8 collate utf8_general_ci;
2.Django中的数据库配置
settings.py中找到DATABASES变量
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
1.ENGINE
指定数据库引擎,mysql引擎如下:
'ENGIN':'django.db.backends.mysql'
2.NAME
指定要连接的数据库的名称
'NAME':'webdb'
3.USER
指定登录到数据库的用户名称
'USER':'root'
4.PASSWORD
指定登录到数据的用户密码
'PASSWORD':'123456'
5.HOST
指定要连接到的主机地址
'HOST':'localhost'
6.PORT
指定要连接到的主机的端口号
'PORT':3306
3.Django中的数据库迁移
1. ./manage.py makemigrations
作用:
将每个应用下的models.py文件生成一个中间迁移文件,并将中间文件保存在 migrations的目录中
2. ./manage.py migrate
作用:
将每个应用下migrations目录中的中间文件同步回数据库
4.编写Models
1.编写示例
见代码
2.Models的语法规范
class CLASSNAME(models.Model):
NAME=models.FIELDTYPE(FIELDOPTIONS)
1.CLASSNAME
实体类名称,表名组成的一个部分
默认表名组成规范:
应用名称_CLASSNAME
2.NAME
属性名,映射回数据库就是字段名称
3.FIELDTYPE
字段类型:映射到表中的字段的类型
1.BooleanField()
编程语言中使用True或False表示该列值
数据库中使用 1 或 0 表示具体的值
数据类型为:tinyint
2.CharField()
数据类型为:varchar
注意:
必须要指定max_length参数值
3.DateField()
编程语言中使用字符串来表示该列值
数据库中使用的日期来表示
数据类型为:date
4.DateTimeField()
数据类型为:datetime
5.DecimalField()
编程语言中使用小数表示该列的值
数据库中使用定点小数表示值
数据类型:decimal
money=models.DecimalField
(max_digits=7,decimal_places=2)
6.FloatField()
数据库以及编程语言中都使用小数表示
数据类型为:float
7.EmailField()
编程语言中使用字符串表示该列的值
数据库中也是字符串
数据类型为:varchar
8.IntegerField()
编程语言和数据库中都使用整数
数据类型为:int
9.URLField()
编程语言和数据库中都使用字符串
数据类型为:varchar
10.ImageField()
存储图片的路径
编程语言和数据库中都是用字符串
image=models.ImageField(upload_to='image/users/')
注意:
必须指定上传路径
所以在后台上传时会自动的将文件保存在指定目录处
4.FIELDOPTIONS
字段选项,指定创建列的额外信息
1.primary_key
如果设置为True,表示该列为主键
2.null
如果设置为Ture,表示该列允许为空
默认为False
3.default
设置所在列的默认值
4.db_index
如果设置为True,则为所在列添加索引
5.unique
如果设置为True,表示所在列的值要唯一
6.db_column
指定映射到列的列名,如果不指定的话则采用属性名称作为列名
练习:
在 index 应用中再追加两个model类
1.Author - 作者
1.name - 姓名
2.age - 年龄
3.email - 邮箱(允许为空)
2.Book - 图书
1.title - 书名
2.publicate_date - 出版时间
5.相关指令
1.通过数据库自动导出models
./manage.py inspectdb > 文件名.py
2.数据的版本切换
1. ./manage.py migrate
执行所有应用中最新版本的数据库迁移文件
2. ./manage.py migrate 应用名称 版本号
./manage.py migrate index 0001
1.增加数据
1.Entry.objects.create(属性=值,属性=值)
返回值:返回创建好的实体对象
2.创建 Entry 的对象,并调用save()进行保存
obj = Entry(属性=值,属性=值,...)
obj.属性=值
obj.save()
无返回值,保存成功后,obj会被重新赋值
3.使用字典创建对象,并调用save()进行保存
dic = {
'属性1':"值1",
'属性2':"值2",
... ...
}
obj=Entry(**dic)
obj.save()
练习:
使用以上三种方式,向Book和Publisher表中各增加至少三条数据
2.查询数据(重点)
通过 Entry.objects 属性调用查询接口
ex:
Entry.objects.all()
Entry.objects.filter()
Entry.objects.values()
.... ....
1.基本查询操作
语法:all()
用法:Entry.objects.all()
作用:查询Entry实体中所有行所有列的记录
SQL:select * from Entry
返回:QuerySet
1.所有的QuerySet都可以通过query属性得到对应的SQL语句
2.所有的QuerySet都可以当成列表操作
2.查询返回指定列
语法:values() | values('列1','列2',)
用法:
Entry.objects.values('列1','列2')
Entry.objects.all().values('列1','列2')
返回值:QuerySet
会将查询出来的数据封装到字典中再封装到列表中
3.查询返回指定列
语法:values_list('列1','列2')
用法:
Entry.objects.values_list()
Entry.objects.all().values_list()
返回:QuerySet
会将查询出来的数据封装到元组中再封装到列表中
练习:
1.创建路由 /03-queryall
2.查询Author实体中所有的数据
并渲染到03-queryall.html模板上
3.在03-queryall.html模板上
显示所有的数据
姓名 年龄 邮箱 操作
xx xx xxx 删除 修改
4.根据条件查询部分行数据(重难点)
语法:filter(条件)
用法:Entry.objects.filter(条件)
返回:QuerySet
ex:
1.查询id为1的Author的信息
authors=Author.objects.filter(id=1)
2.查询publicate_date为2018-10-12的Book的信息
books=Book.objects.filter(publicate_date='2018-10-12')
3.查询id为1并且publicate_date为2018-10-12的Book的信息
books=Book.objects.filter(id=1,publicate_date='2018-10-12')
如果要非等值查询条件,需要使用查询谓词
Django:Field Lookup
查询谓词:是一个独立的查询功能
语法:filter(属性__查询谓词=值)
ex:
__exact : 等值匹配
__contains : 包含指定值
__in : 在指定范围内的值
__gt : 大于指定值
__gte:
__lt :
__lte:
__startswith : 以 xx 作为开始
__endswith : 以 xx 作为结束
__range : 在指定区间范围
__date : 获取日期部分数据
__year : 获取年
__month
__day
.. ..
练习:
1.查询Author表中age 大于等于95的Author的信息
2.查询Author表中所有姓"鲁"的人的信息
3.查询Author表中Email中包含'sh'的人的信息
4.查询Author表中Age大于"鲁迅"的age的人的信息
5.不等的条件筛选
语法:exclude(条件)
用法:Entry.objects.exclude(条件)
6.排序
语法:order_by('列1','-列2')
用法:Entry.objects.order_by('列')
说明:
默认是按升序排序,降序则在列前增加'-'即可
7.查询只返回一条数据
语法:get(条件)
用法:Entry.objects.get(条件)
注意:
该方法必须只能返回一条数据
返回多条数据:抛异常
无数据返回 :抛异常
<QuerySet
[
{'name': '莫言', 'id': 1, 'age': 65, 'email': 'moyan@163.com', 'isActive': True},
{'name': '老舍', 'id': 2, 'age': 105, 'email': 'laoshe@163.com', 'isActive': True},
{'name': '鲁迅', 'id': 3, 'age': 95, 'email': 'zhoushuren@163.com', 'isActive': True},
{'name': '巴金', 'id': 4, 'age': 100, 'email': 'eightJin@163.com', 'isActive': False}
]
<QuerySet [
<Author: Author object>,
<Author: Author object>,
<Author: Author object>,
<Author: Author object>]>
SELECT `index_author`.`id`, `index_author`.`name`, `index_author`.`age`, `index_author`.`email`, `index_author`.`isActive` FROM `index_author`
1.聚合查询(不带分组)
语法:aggregate()
用法:Entry.objects.aggregate(名=聚合函数('列'))
聚合函数()
from django.db.models import Avg,Sum,Count,Max,Min
2.聚合查询(带分组)
语法:annotate()
用法:
Entry.objects
.values('分组列名')
.annnotate(名=聚合函数('列'))
.values('查询列名')
练习:
1.查询 Book 表中共有本图书
result = Book.objects.aggregate(count=Count('*'))
2.查询 每个时间 所发布的书籍的数量
Book.objects.values('publicate_date')
.annotate(count=Count('*'))
3.查询 2015 年之后所出版的图书数量
Book.objects.filter(publicate_date__year__gte=2015)
.aggregate(count=Count('*'))
4.查询 Publisher中,City为北京的出版社数量
Publisher.objects.filter(city='北京').aggregate
(count=Count('*'))
1.修改单个实体
1.查
通过 get() 得到要修改的实体对象
2.改
通过得到的对象去修改属性值
对象.属性=值
3.保存
通过对象.save()保存数据回数据库
2.批量修改
直接调用QuerySet的update(属性=值)实现批量修改
调用实体对象/查询结果集的 delete() 实现删除
1.删除单个对象
Author.objects.get(id=1).delete()
2.批量删除
Author.objects.filter(isActive=False).delete()
1.F查询 - F()
1.作用:
在执行操作过程中用于获取某列的值
2.语法:
from django.db.models import F
F('列名')
3.示例
更新Author表中所有的数据的age都加10岁
Author.objects.all().update(age=F('age')+10)
2.Q查询 - Q()
1.作用:
在查询条件中来实现 or 的操作的
2.语法:
from django.db.models import Q
Q(条件1)|Q(条件2)
3.示例:
查询Author表中id=1或age>=90的人的信息
Author.objects.filter(Q(id=1)|Q(age__gte=90))
1.查询
1.语法:
raw(sql语句)
2.用法
Entry.objects.raw('sql')
3.返回值
QuerySet
2.增删改
from django.db import connection
def doSQL(request):
#更新index_author表所有数据的isActive=1
with connection.cursor() as cursor:
cursor.execute("update index_author set isActive=1")
return ''
登录地址:http://localhost:8000/admin
使用指令创建后台管理员
./manage.py createsuperuser
1.在应用中的 admin.py 中注册要管理的数据
1.admin.py
作用:
注册要管理的Models类
2.注册Models
from django.contrib import admin
from .models import *
admin.site.register(Entry)
admin.site.register(Entry)
2.定义Models的展现形式
1.通过 __str__ 定义展现形式
class Author(models.Model):
xxxx xxxx
def __str__(self):
return self.name
2.通过 verbose_name 字段选项,修改名称
name=models.CharField(
max_length=30,
verbose_name='姓名'
)
3.通过Meta内部类 修改展现形式
class Author(models.Model)
class Meta:
1.db_table
指定当前类映射到的表名
(设置完成后立马同步数据库)
2.verbose_name
定义实体类在admin中的显示名称
(单数)
3.verbose_name_plural
效果同上(复数)
4.ordering
指定数据的排序方式
取值为一个列表
练习:
1.修改 Publisher 后台管理功能
1.更改表名为 publisher
2.修改后台的展示名称 - 出版社
3.修改每个属性对应的中文名称
2.修改 Book 后台管理功能
1.更改表名为 book
2.修改后台的展示名称 - 书籍
3.修改每个属性对应的中文名称
4.指定排序方式 - 按出版时间倒序排序
1.在 admin.py 中创建高级管理类并注册
1.定义类EntryAdmin,继承自admin.ModelAdmin
class AuthorAdmin(admin.ModelAdmin):
pass
2.注册高级管理类
admin.site.register(Entry,EntryAdmin)
2.在EntryAdmin中所管理的功能
通过 属性 管理功能
1.list_display
作用:定义在列表页上允许显示的字段们
取值:由属性名组成的列表或元组
2.list_display_links
作用:定义在列表页中能连接到详情页的字段们
取值:同上
注意:取值必须要出现在list_display中
3.list_editable
作用:定义在列表页中就允许修改的字段们
取值:同上
注意:取值必须出现在list_display中但不能出现在list_display_links中
4.search_fields
作用:添加允许被搜索的字段们
取值:同上
5.list_filter
作用:列表页右侧增加一个过滤器快速筛选
取值:同上
6.date_hierarchy
作用:列表页中增加时间分层选择器
取值:只能取一个值,必须是DateField或DateTimeField的
7.fields
作用:在详情页中,指定要显示的字段以及顺序
取值:由属性名称组成的元组或列表
8.fieldsets
作用:详情页中,对字段们进行分组
注意:fieldsets与fields不能共存的
取值:
fieldsets = (
#分组1
('组名',{
'fields':('属性1',"属性2",),
'classes':('collapse',)
}),
#分组2
()
)
练习:完成Publisher的高级管理功能
1.在列表页中显示name,address,city属性
2.address 和 city 是可编辑的
3.右侧增加过滤器,允许按照city筛选
4.顶部增加搜索框,允许按照name和website搜索
5.详情页中分组显示
1.name,address,city : 基本信息
2.conuntry,website : 高级信息,并可折叠
1.语法
在关联的两个类中的任何一个类中:
属性=models.OneToOneField(Entry)
2.示例
class Author(models.Model):
xxxx xxxx
class Wife(models.Model):
xxxx xxxx
author=models.OneToOneField(Author)
Author中也会有一个隐式属性 - wife
练习:
1.查询 巴金 的夫人的信息
2.查询 金夫人 的对应的Author的信息
1.语法
在"多"实体中增加对"一"实体的引用
属性 = models.ForeignKey(Entry)
ex:
一个出版社允许出版多本图书
一本图书只能属于一个出版社
出版社(1) : 图书(多)
class Publisher(models.Model):
xxxx
class Book(models.Model):
xxxx
publisher = models.ForeignKey(Publisher)
2.数据管理
1.增加数据
1.通过 book.publisher_id 插入关联数据、
book = Book(xxx xxx)
book.publisher_id = 1
book.save()
2.通过 book.publisher 插入关联数据
book = Book(xxx)
pub = Publisher.objects.get(id=2)
book.publisher = pub
book.save()
2.查询数据
1.正向查询
通过 Book 查询 Publisher
book = Book.objects.get(id=1)
pub = book.publisher
2.反向查询
通过 Publisher 查询对应的所有的 Book
Django会在Publisher中增加一个属性表示对Book的查询引用
属性 :book_set --> (Entry.objects)
1.语法
在关联的两个类的任意一个类中,增加:
属性 = models.ManyToManyField(Entry)
class Author(models.Model):
xxx
class Book(models.Model):
xxx
author_set = models.ManyToManyField(Author)
2.数据管理
1.增加数据
通过关联属性的add()方法实现数据的增加
2.删除数据
通过关联属性的remove()实现删除数据
3.查询数据
1.正向查询
通过Book查询Author,可以通过关联属性来表示对Author的查询对象 --> objects
示例:查询射雕英雄传对应所有的作者
book=Book.objects.get(title='射雕英雄传')
book.author_set.all()
2.反向查询
通过Author查询Book,可以通过Django增加的隐式属性book_set来获取对应的book的查询对象 --> objects
author=Author.objects.get(name='金庸')
books = author.book_set.all()
1.声明类EntryManager继承自models.Manager
Entry.objects的类型为 models.Manager
允许在EntryManager中添加自定义函数
示例:
class EntryManager(models.Manager):
ef 函数名(self,自定义参数列表):
.... ....
return .... ....
2.使用EntryManager覆盖Models类中原有的objects
class Entry(models.Model):
objects = EntryManager()
name = models.CharField(xxxx)
练习:通过自定义的objects类型完成
1.查询Author中姓名中包含指定字符的所有信息
2.查询Book中出版时间是指定年份的所有信息
HttpRequest,在Django中就是请求对象。
在Django中,请求对象被封装到视图处理函数中的参数里-request
1.request.scheme : 请求协议
2.request.body : 请求主体
3.request.path : 请求具体资源路径
4.request.get_full_path : 请求完整路径
5.request.get_host() : 请求的主机/域名
6.request.method : 请求方式
7.request.GET : get请求方式中封装的数据
8.request.POST : post请求方式中封装的数据
9.request.COOKIES : 请求中cookie的相关数据
10.request.META : 请求的元数据(消息头)
request.META.HTTP_REFERER : 请求源地址
1.使用get方式
1.语法
request.GET['参数名']
request.GET.get('参数名')
request.GET.getlist('参数名')
2.能够产生get请求方式的场合
1.地址栏的请求
1.<a href="地址?参数=值&参数=值">
2.location.href='地址?参数=值&参数=值'
2.表单中method为get
<form method='get'>
姓名: <input type="text" name='uname'>
</form>
注意:Django中URL的参数是不能用此方式
url(r'^01-xxx/(\d+)',...)
此写法属于Django,只在Django中有效而并非HTTP协议标准
2.使用post方式
1.语法
request.POST['参数名']
request.POST.get('参数名')
request.POST.getlist('参数名')
2.CSRF
Cross-Site Request Forgery
跨 站点 请求 伪装
(跨站点请求攻击)
解决方案:
1.取消 csrf 验证(不推荐)
删除 settings.py 中 MIDDLEWARE 中的 CsrfViewMiddleware 中间件
2.开放验证
在视图处理函数上增加 : @csrf_protect
@csrf_protect
def post_views(request):
pass
3.通过验证
需要在表单中增加一个标签
{% csrf_token %}
练习-果园项目的注册部分
1.创建数据库 - fruitday
2.创建实体类 - Users
1.uphone - varchar(11)
2.upwd - varchar(200)
3.uemail - varchar(245)
4.uname - varchar(20)
5.isActive - tinyint,默认值为 1(True)
3.完善注册 - /register/
1.如果是get请求,则去往 regsiter.html
2.如果是post请求,则处理请求数据
验证uphone是否存在,如果存在回到前端并给出提示
1.forms模块的作用
通过forms模块,允许将表单与class相结合
允许通过class 生成 表单
2.使用forms模块
1.在应用中创建 forms.py 文件
2.导入 django 提供的 forms 模块
from django import forms
3.创建 class , 一个class会生成一个表单
class ClassName(forms.Form)
4.在 class 中创建属性
一个属性对应到表单中称为一个控件
3. forms.Form 的语法
属性=forms.类型(参数)
1.类型
forms.CharField()
forms.DateField()
.... ....
每个类型都会生成一个表单控件
2.参数
1.label
控件前的文本
2.initial
控件的初始值
3.widget
指定小部件
4.error_messages
指定数据错误时的提示文本
.... ....
4. 在模板中解析form对象
1.注意
1.需要自定义<form>
2.表单中的按钮需要自定义
2.解析form对象
在视图中创建form对象并发送到模板中解析
ex:
form = RemarkForm()
return render(request,'xx.html',locals())
1.手动解析
{% for field in form %}
{{field.label}}:控件中label的值
{{field}}:表示的就是控件
{% endfor %}
2.自动解析
1.{{form.as_p}}
将form中的每个属性都使用p标记进行表示
2.{{form.as_ul}}
将form中的每个属性使用li标记包裹再显示
注意:必须手动提供<ol></ol>或<ul></ul>
3.{{form.as_table}}
将form中的每个属性使用tr标记包裹
注意:必须手动提供<table></table>
1.通过forms.Form的子类的构造器来接收post数据
form = RemarkForm(request.POST)
2.必须使form通过验证,才能取值
form.is_valid()
返回True:通过验证
返回False:未通过验证
3.获取表单数据
通过 form.cleaned_data 来接收表单数据
练习:
1.创建一个数据库 - djangodb
2.创建实体类 - Users
uname - varchar(30),upwd - varchar(30)
uage - int,uemail - varchar(30)
3.创建forms模块 - forms.py
1.创建RegisterForm -> forms.Form
2.属性根据Users实体类创建
4.解析forms并接收数据
1.将 RegisterForm 的对象发送到模板
04-register/ -> 04-register.html
2.post提交时接收数据,并将数据保存回数据库
将 Models 和 Forms 结合到一起使用
1. 在forms.py中创建class
继承自 forms.ModelForm
2. 创建内部类 Meta,关联Model
1.model : 指定要关联的实体类
2.fields : 指定从Model中取哪些字段生成控件
1.取值为 "__all__"
取全部属性生成控件
2.取值为 列表
将允许生成控件的属性名放在列表中
3.labels : 指定每个属性对应的label值
取值为字典
labels = {
'uname':'登录名称',
... ...
}
练习:使用ModelForm完成
1.从 Users 类中取出 uname,upwd两个字段生成表单
2.提交数据时验证登录的成功与否
1.什么是小部件
表示的是生成到网页上的控件的类型以及其他的一些html属性
2.常用小部件类型
1.TextInput : type="text"
2.PasswordInput : type="password"
3.NumberInput : type="number"
4.EmailInput :type="email"
5.URLInput :type="url"
6.HiddenInput : type="hidden"
7.CheckboxInput : type="checkbox"
8.CheckboxSelectMultiple : type="checkbox"
以 <ul>和<li> 生成多个 checkbox 控件
9.RadioSelect : type="radio"
以 <ul>和<li> 生成多个 radio 控件
10.Textarea : <textarea></textarea>
11.Select :<select></select>
12.SelectMultiple:
<select multiple></select>
3.小部件的使用
1.继承自forms.Form
1.基本版
1.语法
属性=forms.CharField(
label='xxx',
widget=forms.小部件类型
)
2.示例
upwd = forms.CharField(
label='用户密码',
widget=forms.PasswordInput
)
2.高级版
1.特征
在指定控件类型的基础之上还能指定控件的一些html属性
2.语法
属性 = forms.CharField(
label = '标签',
widget = forms.小部件类型(
attrs={
'html属性名':'值',
'html属性名':'值',
}
)
)
2.继承自forms.ModelForm
class LoginForm(forms.ModelForm):
class Meta:
model = Users,
fields = ['uname','upwd']
labels = {
'uname':'用户名称',
'upwd':'用户密码',
}
#指定小部件
widgets = {
'upwd':forms.PasswordInput(
attrs={
'html属性名':'值'
}
),
}
练习:果园登录,改版成forms与models的结合
1.Django中使用cookie
使用 响应对象 将cookie保存进客户端
1.响应对象
1.HttpResponse()
resp = HttpResponse("响应一句话")
2.render()
resp = render(request,'xxx.html',locals())
3.redirect()
resp = redirect('/')
2.保存cookie
响应对象.set_cookie(key,value,expires)
key:cookie的名字
value:cookie的值
expires:默认是以 s 为单位的数字
取值为0表示要删除该cookie值
3.获取cookie
request.COOKIES
封装了当前站点下所有的cookie - 字典
1.保存session的值到服务器
request.session['KEY']=VALUE
2.从服务器中获取session的值
VALUE=request.session['KEY']
3.删除session值
del request.session['KEY']
4.在 settings.py中有关session的设置
1.SESSION_COOKIE_AGE
作用:指定sessionid在cookies中保存时长
SESSION_COOKIE_AGE=60*60*24*2
2.SESSION_EXPIRE_AT_BROWSER_CLOSE = True
只要浏览器关闭,session就失效
1、定义:网络蜘蛛、网络机器人,抓取网络数据的程序
2、总结:用Python程序模仿人去访问网站,模仿的越像越好
3、爬取数据目的:通过有效的大量数据分析市场走势
1、公司自有数据
2、第三方数据平台购买
数据堂、贵阳大数据交易所
3、爬虫爬取数据
市场上没有,价格太高,利用爬虫程序爬取
请求模块、解析模块丰富成熟,强大的scrapy框架
PHP :对多线程、异步支持不太好
JAVA:代码笨重,代码量很大
C/C++:虽然效率高,但是代码成型很慢
1、通用网络爬虫(搜索引擎用,遵守robots协议)
https://www.taobao.com/robots.txt
2、聚焦网络爬虫
自己写的爬虫程序:面向需求的爬虫
1、确定要爬取的URL地址
2、通过HTTP/HTTS协议获取相应的页面
3、提取响应中有用的数据
1、所需数据,保存
2、页面中有其他的URL,继续第 2 步
1、Anaconda :集成的开发环境
2、Spyder快捷键
1、注释/取消注释 :ctrl + 1
2、运行程序 :F5
1、安装步骤(打开浏览器)
1、右上角 - 更多工具 - 扩展程序
2、点开右上角 - 开发者模式
3、把插件 拖拽到 浏览器页面,释放鼠标,点击添加扩展程序
2、插件介绍
1、Proxy SwitchOmega : 代理切换插件
2、Xpath Helper : 网页解析数据插件
3、JSON View : 查看JSON格式的数据
1、HTTP和HTTPS
HTTP:80
HTTPS:443,HTTP的升级版,加了安全套接层
2、GET和POST
1、GET :查询参数在URL地址上显示出来
2、POST:查询参数和需要提交的数据隐藏在Form表单中,不会在URL地址上都显示
3、URL :统一资源定位符
https://item.jd.com/37289659363.html#detail
协议 域名/IP地址 访问资源路径 锚点
4、User-Agent
记录用户浏览器、操作系统等,为了让用户获取更好的页面效果
Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1
1、python2: urllib、urllib2
python3: 合并,urllib.request
2、常用方法
1、作用 :向网站发起请求并获取响应对象
字节流 = response.read()
字符串 = response.read().decode('utf-8')
encode() : 字符串->bytes
decode() : bytes ->字符串
2、不支持重构User-Agent
1、使用流程
1、创建请求对象(Request())
req = urllib.request.Request(...)
2、发请求获响应(urlopen())
res = urllib.request.urlopen(req)
3、获取响应内容(read().decode('utf-8'))
html = res.read().decode('utf-8')
1、read()
2、getcode() : 返回HTTP的响应码
200 :成功
4XX :服务器页面出错
5XX :服务器出错
3、geturl() : 返回实际数据的URL地址
1、urlencode({字典})
key = {'wd':'美女'}
data = urllib.parse.urlencode(key)
## data为编码后的字符串
示例:在终端输入搜索内容,得到百度的搜索结果,保存到本地文件
2、quote('字符串')
s = urllib.parse.quote('旭叔')
## s为编码后的字符串
3、unquote('%E8%E7%D5...')
1、要求
1、输入抓取的贴吧名称
2、输入起始页
3、输入终止页
4、保存到本地 : 第1页.html 第2页.html ...
2、步骤
1、找URL规律
1、不同吧:http://tieba.baidu.com/f?kw=??
2、不同页
第1页:http://tieba.baidu.com/f?kw=??&pn=0
第2页:http://tieba.baidu.com/f?kw=??&pn=50
第n页: pn=(n-1)*50
2、获取网页内容(发请求获响应)
3、保存(本地文件、数据库)
1、GET
1、特点 :查询参数在URL地址中
2、案例 :抓取百度贴吧
2、POST(在Request()中添加data参数)
1、urllib.request.Request(url,
data=data,
headers=headers)
data : 表单数据以bytes类型提交
2、处理表单数据data为bytes类型
1、先把data定义为字典 {}
2、urlencode(data).encode()
Day01回顾
1、请求模块(urllib.request)
1、Request(url,data=data,headers=headers)
2、urlopen(请求对象)
2、响应对象res的方法
1、res.read() ##bytes
res.read().decode('utf-8') ##字符串
2、res.getcode()
3、res.geturl()
3、url编码模块(urllib.parse)
1、urlencode({字典})
1个查询参数 :{'kw':'美女吧'}
##编码后 'kw=%E8....'
2个查询参数 :{'kw':'美女吧','pn':'50'}
##编码后 'kw=%E8...&pn=50'
2、quote('字符串')
s = '屠龙刀'
quote(s) : '%E5....'
3、unquote('编码后的字符串')
s = '%E5....'
unquote(s) : 屠龙刀
4、数据爬取步骤
1、找URL规律(拼接)
2、获取响应内容
3、保存
5、请求方式
1、GET :查询参数在URL地址上显示
2、POST:参数名data,查询参数在Form表单里
注意 :data一定要以bytes数据类型提交
data = {....}
data = urllib.parse.urlencode(data).encode()
6、json模块
Dict = json.loads('json格式的字符串')
1、数据的分类
1、结构化数据
特点:固定格式,HTML,JSON,XML
2、非结构化数据
图片,音频,视频,一般存储为二进制
2、正则解析模块re使用流程
1、rList = re.findall(r'表达式','字符串',re.S)
2、写法2
1、创建编译对象
p = re.compile(r'',re.S)
2、进行字符串匹配
rList = p.findall(html)
3、元字符
. : 匹配任意1个字符(不包括\n)
\d : 1个数字
\s : 空白字符
\S : 非空白字符 #[\s\S]可匹配任意1个字符
[] : 包含[]内容
\w : 普通字符
\W : 特殊字符
* : 0次或N次
+ : 1次或N次
? : 0次或1次
{m} : m次
4、贪婪匹配和非贪婪匹配
1、贪婪匹配(.*) : 在整个表达式匹配成功的前提下,尽可能多的匹配*
2、非贪婪匹配(.*) : 在整个表达式匹配成功的前提下,尽可能少的匹配*
5、分组(findall())
## 在网页中,你想要什么数据,你就加()
先按照整体正则匹配出来,然后再匹配()中
如果有2个(),则以元组形式显示
6、正则分组练习
<div class="animal">
<p class="name">
<a title="Tiger"></a>
</p>
<p class="contents">
Two tigers two tigers run fast
</p>
</div>
<div class="animal">
<p class="name">
<a title="Rabbit"></a>
</p>
<p class="contents">
Small white rabbit white and white
</p>
</div>
第1步实现:[("Tiger","Two ..."),("Rabbit","Sm..")]
第2步实现:
动物名称 :Tiger
动物描述 :Two tigers two tigers ...
******************************
动物名称 :Rabbit
动物描述 :Small whilte rabbit ...
1、导入模块
import csv
2、打开csv文件
## 一定要加newline='',否则会多出空行
with open('XX.csv','w',newline='') as f:
3、初始化写入对象
writer = csv.writer(f)
4、写入数据
writer.writerow([列表])
1、网址 :猫眼电影 - 榜单 - top100榜
2、目标 :电影名称、主演、上映时间
3、步骤
1、找URL规律
第1页:https://maoyan.com/board/4?offset=0
第2页:https://maoyan.com/board/4?offset=10
第n页:offset=(n-1)*10
2、写正则表达式
'<div class="movie-item-info">.*?title="(.*?)".*?class="star">(.*?)</p>.*?class="releasetime">(.*?)</p>',re.S
3、代码实现
1、(管理员方式)进入到Anaconda Prompt
2、执行安装命令
conda install pymongo
conda install pymysql
1、pymongo回顾
1、连接对象
conn = pymongo.MongoClient('IP',27017)
2、库对象
db = conn['库名']
3、集合对象
myset = db['集合名']
4、执行插入语句
myset.insert_one({字典})
>>>show dbs
>>>use 库名
>>>show collections
>>>db.集合名.find().pretty()
>>>db.集合名.count()
>>>db.dropDatabase()
2、pymysql回顾
1、创建数据库对象
2、创建游标对象
3、执行命令
4、(重要)提交到数据库执行
3、warnings模块
import warnings
# 过滤警告/忽略警告
warnings.filterwarnings('ignore')
4、猫眼电影存入MySQL数据库
1、建库
mysql> create database mydb charset=utf8;
2、建表
use mydb;
create table top100(
id int primary key auto_increment,
name varchar(50),
star varchar(150),
time varchar(50)
)charset=utf8;
3、写程序
4、SQL查询
1、查询1990-2000年的电影信息
select name,time from top100 where time>='1990-01-01' and time<'2001-01-01'
2、查询20年以前的电影
select name,time from top100 where time<=(now()-interval 20 year);
1、开启远程连接
sudo -i
cd /etc/mysql/mysql.conf.d/
subl mysqld.cnf
把下面这行注释掉
#bind-address = 127.0.0.1
重启数据库服务
/etc/init.d/mysql restart
service mysql restart
2、添加授权用户
mysql> grant all privileges on *.* to 'lion'@'%' identified by '123456' with grant option;
mysql> flush privileges;
3、关闭Ubuntu防火墙
sudo ufw disable
1、打开防火墙
sudo ufw enable
2、关闭防火墙
sudo ufw disable
3、添加防火墙规则
sudo ufw allow 端口号
sudo ufw allow 3306
4、查看状态
sudo ufw status
1、配置Fiddler
1、Tools->Options
1、HTTPS
1、Decrypt Https Traffic (选中,自动添加证书信任窗口)
2、...from browsers only
2、Connections
1、监听端口 :8888
2、手机抓包 :Allow remote computers to connect(选中)
2、重启Fiddler(重要)
2、配置浏览器代理
1、浏览器右上角:SwitchOmega->选项->+新建情景模式->AID1809(名字)->创建
2、HTTP:// 127.0.0.1 8888(Fiddler端口)
3、点击 :应用选项
4、点击SwitchOmega可切换代理(AID1809)
1、Inspector:查看抓到的数据包详细内容
整体氛围请求(Request)和响应(Response)两部分
2、常用菜单
1、Headers
显示客户端发送到服务器的请求头,包含客户端信息、cookie、传输状态
2、WebForms
显示POST请求的数据<body>中
3、Raw
将整个请求显示为纯文本
allChars = sting.whitespace + string.punctuation
username = input("请输入用户名:")
for u in username:
if u in allChars:
print('用户名不能包含特殊字符')
Day02回顾
1、关于正则分组
1、分组(想要抓取什么内容就加小括号())
2、正则方法
p = re.compile(r'',re.S)
rList = p.findall(html)
结果:[(),(),(),()]
3、贪婪匹配 .*
4、非贪婪匹配 .*? 或者 [\s\S]*?
2、爬取网站思路
1、找URL规律,分析POST请求数据
2、写正则表达式
3、定义类,写程序框架
4、补全代码
3、存入csv文件
import csv
with open('XXX.csv','w',newline='') as f:
writer = csv.writer(f)
writer.writerow([])
4、MySQL流程
1、db = pymysql.connect('IP地址',......)
2、cursor = db.cursor()
3、cursor.execute('sql命令',[])
4、db.commit()
5、cursor.close()
6、db.close()
5、MongoDB流程
1、conn = pymongo.MongoClient('IP地址',27017)
2、db = conn['库名']
3、myset = db['集合名']
4、myset.insert_one({字典})
## 命令行操作
>>> show dbs
>>> use 库名
>>> show collections | show tables
>>> db.集合名.find().pretty()
>>> db.集合名.count()
>>> db.dropDatabase()
6、远程连接MySQL数据库
1、开启远程连接
sudo vi /etc/mysql/mysql.conf.d/mysqld.cnf
#bind-address = 127.0.0.1
2、重启数据库服务
sudo /etc/init.d/mysql restart
sudo service mysql restart
3、授权
mysql>grant all privileges on *.* to '用户名'@'%' identified by '密码' with grant option;
## 刷新权限
mysql>flush privileges;
4、设置防火墙,允许外部访问本机3306端口
sudo ufw allow 3306
sudo ufw allow 27017
7、Ubuntu中防火墙(ufw)基本操作
1、状态 :sudo ufw status
2、打开 :sudo ufw enable
3、关闭 :sudo ufw disable
4、规则 :sudo ufw allow 端口号
8、Anaconda安装模块
1、右键,以管理员身份打开:Anaconda Prompt
2、(base)C:\Users\Administrator:执行安装命令
conda install 模块名
9、Fiddler常用菜单
1、Inspector :请求/响应两部分
2、常用选项
1、Headers
2、WebForms :Form表单数据<body>
3、Raw :将整个请求显示为纯文本
1、安装
管理员Anaconda Prompt: conda install requests
2、常用方法
1、requests.get(url,headers=headers)
向网站发起请求并获取响应对象res
2、响应对象(res)属性
1、encoding : 响应字符编码
res.encoding = 'utf-8'
2、text :字符串
3、content: 字节流
4、status_code : HTTP响应码
5、url :返回实际数据的URL
3、非结构化数据保存(图片)
html = res.content
with open('XXX','wb') as f:
f.write(html)
1、查询参数(params)
params : 字典
res = requests.get(url,params=params,header..)
# 自动对params字典进行编码,然后和url进行拼接
输入搜索内容,爬取第2页的内容
2、代理参数(proxies)
1、获取代理IP的网站
西刺代理网站
快代理
全网代理
2、普通代理
1、格式:proxies={'协议':'协议://IP:端口号'}
2、测试网站
http://httpbin.org/get
https://www.whatismyip.com/ (每天5次)
3、私密代理
1、格式
proxies = {"协议":"协议://用户名:密码@IP地址:端口号'}
3、Web客户端验证(auth)
1、auth=('用户名','密码')
auth=('tarenacode','code_2013')
2、达内笔记下载
1、网址:http://code.tarena.com.cn
2、正则:<a href="(.*?)/.*?</a>
3、参数:auth=('tarenacode','code_2013')
4、SSL证书认证参数(verify)
1、verify=True:默认,进行SSL证书认证
2、verify=False:不去检查认证
3、res = requests.get(url,headers=headers,verify=False)
抛出异常:SSLError
1、requests.post(url,data=data,headers=headers)
2、data :Form表单数据,字典,不用编码,不用转码
1、F12,抓包,多抓几次观察Form表单中数据变化
salt、sign、ts、bv(没变)
2、加密一定为js文件做的,抓js文件,找到相关加密算法
3、F12,浏览器重新向有道翻译发起请求,抓到1个js文件:fanyi.min.js, Preview选项查看js代码,放到本地文件
4、Ctrl+F搜索想要的字段,salt、sign,找到8240多行
var t = n.md5(navigator.appVersion)
, r = "" + (new Date).getTime()
, i = r + parseInt(10 * Math.random(), 10);
return {
ts: r,
bv: t,
salt: i,
sign: n.md5("fanyideskweb" + e + i + "p09@Bn{h02_BIEe]$P^nG")
5、分开查找这几个字段
1、ts :r = "" + (new Date).getTime()
时间戳(13位):1548320769934
r = int(time.time()*1000)
2、salt
i = r + parseInt(10 * Math.random(), 10)
i = int(time.time()*1000)+random.randint(0,10)
3、sign
sign: n.md5("fanyideskweb" + e + i + "p09@Bn{h02_BIEe]$P^nG")
## e:要翻译的单词
sign = "fanyideskweb" + key + str(salt) + "p09@Bn{h02_BIEe]$P^nG"
s = hashlib.md5()
s.update(sign.encode())
sign = s.hexdigest()
3、内涵段子脑筋急转弯(mongodb)
1、网址 :www.neihan8.com
2、步骤
1、找URL规律
第1页:https://www.neihan8.com/njjzw/
第2页:https://www.neihan8.com/njjzw/index_2.html
2、写正则
<div class="text-column-item.*?title=.*?>(.*?)</a>.*?<div class="desc">(.*?)</div>
3、写代码
第一次:
salt: 15483207699341
sign: 267b98fe9abb20763b0d9a4560fb5b0b
ts: 1548320769934
bv: 363eb5a1de8cfbadd0cd78bd6bd43bee
第2次:
salt: 15483208701106
sign: b2c45f55e8b58b58046eba0a89c17a61
ts: 1548320870110
bv: 363eb5a1de8cfbadd0cd78bd6bd43bee
第3次:
salt: 15483209185268
sign: 300bd04be8c337d5dcf6054a3936bb92
ts: 1548320918526
bv: 363eb5a1de8cfbadd0cd78bd6bd43bee
Day03回顾
1、requests模块
1、get()
1、查询参数:params->{}
2、代理参数:proxies->{}
{'协议':'协议://IP:端口号'}
{'协议':'协议://user:pwd@IP:端口'}
3、Web验证:auth->(元组)
auth=('tarenacode','code_2013')
4、SSL认证:verify->True/False
verify=False : 忽略证书认证
2、post()
data -> 字典,Form表单数据
3、响应对象res的属性
1、text : 字符串
2、content : 字节流
3、encoding: 字符编码
4、status_code :HTTP状态码
5、url :实际数据URL
1、在XML文档中查找信息的语言,同样适用于HTML文档的检索
2、xpath辅助工具
1、Chrome插件:XPath Helper
打开/关闭:Ctrl + Shift + x
2、Firefox插件:XPath Checker
3、XPath编辑工具:XML Quire
3、xpath匹配演示
1、查找所有的book节点 ://book
2、查找book下的title子节点中,lang属性为'en'的节点
//book/title[@lang="en"]
3、查找bookstore下的第2个book节点下的title子节点
//bookstore/book[2]/title
4、查找所有book/title节点中lang属性的值
//book/title/@lang
4、选取节点
1、// :从所有子节点和后代节点中查找
//price 、 //book//price
2、@ :选取某个节点的属性值
选取1类节点 : //title[@lang="en"]
获取节点属性值: //title/@lang
3、匹配多路径: |
xpath表达式1 | xpath表达式2
4、函数
1、contains()
匹配一个属性值中包含某些字符串的节点
找到所有lang属性值包含'e'的title节点
//title[contains(@lang,'e')]
2、text() : 获取文本
//title[contains(@lang,'e')]/text()
1、lxml库安装
Anaconda Prompt: conda install lxml
2、使用流程
1、导模块
from lxml import etree
2、创建解析对象
parseHtml = etree.HTML(html)
3、调用xpath
rList = parseHtml.xpath('xpath表达式')
## 只要调用xpath,结果一定是列表 ##
1、目标:抓取指定贴吧所有图片
2、思路
1、获取贴吧主页URL,下一页:找URL规律
2、获取1页中所有帖子的URL
[帖子1链接,帖子2链接,...]
3、对每个帖子URL发请求,获取所有图片的URL
[图片1链接,图片2链接,...]
4、对每个图片URL发请求,以wb方式写入到本地文件
3、思路梳理
帖子链接列表 = parseHtml.xpath('....')
for 1个帖子链接 in [帖子链接列表]:
图片链接列表 = 对帖子发请求后xpath出来的
for 1个图片链接 in [图片链接列表]:
html = 对1张图片链接发请求
with open(filename,'wb') as f:
f.write(html)
4、步骤
1、获取贴吧主页URL,找URL规律
http://tieba.baidu.com/f?kw=??&pn=50
2、找到页面中所有帖子的URL
xpath表达式: //div[@class="t_con cleafix"]/div/div/div/a/@href
3、帖子中图片链接xpath表达式
//div[@class="d_post_content j_d_post_content clearfix"]/img[@class="BDE_Image"]/@src
4、帖子中视频xpath表达式
//div[@class="video_src_wrapper"]/embed/@data-video
# 百度对响应内容做了更改,向1个帖子发起请求,获取到响应内容保存到本地,进行页面分析
1、网址:
2、xpath匹配
1、基准xpath表达式:匹配所有段子节点对象
[<div1>,<div2>,.....]
//div[contains(@id,"qiushi_tag_")]
2、用户昵称: ./div/a/h2
段子内容: .//div[@class="content"]/span
好笑数量: .//i[@class="number"]
评论数量: .//i[@class="number"]
Day04回顾
1、lxml使用流程
1、from lxml import etree
2、parseHtml = etree.HTML(html)
3、rList = parseHtml.xpath('')
2、xpath匹配规则
1、获取节点对象 : //div[@class="tiger"]
2、获取属性值 : //div[@class="a"]//a/@src
3、函数 ://div[contains(@id,"aa")]//a/@href
3、xpath高级
1、基准xpath表达式(节点对象列表)
2、for r in [节点对象列表]:
username = parseHtml.xpath('./....')
1、特点 :滚动鼠标滑轮时加载
2、抓包工具(F12) :QueryString
1、网址 :豆瓣电影-排行榜-剧情
2、目标 :电影名称、评分
3、F12/抓包工具
滚动鼠标滑轮抓包,找到2个数据
1、Request URL(Raw) :GET的地址
2、QueryString(WebForms) : 发送的数据
4、代码实现
type: 11
interval_id: 100:90
action:
start: 100
limit: 20
1、selenium
1、定义 :Web自动化测试工具,用于Web自动化测试
2、特点
1、可运行在浏览器,根据指定命令操作浏览器,让浏览器自动加载页面
2、只是工具,必须与第三方浏览器结合使用
3、安装selenium
Anaconda Prompt: conda install selenium
2、phantomjs浏览器
1、定义 :无界面浏览器(无头浏览器)
2、特点 :把网站在内存进行页面加载,运行高效
3、安装
1、下载对应安装包(.exe),将文件放到Python安装目录的Scripts目录下
D:\Anaconda3\Scripts
3、chromedriver安装
1、下载网址 https://chromedriver.storage.googleapis.com/index.html
2、安装
1、查看本机Chrome浏览器版本
设置-帮助-关于Google Chrome
2、下载对应版本的chromedriver.exe(notes.txt)
3、拷贝到Python安装目录的Scripts目录下
4、cmd终端 :chromedriver -v
4、示例代码1
5、示例代码2
6、常用方法
1、driver.get(url)
2、driver.page_source : 获取响应的html源码
3、driver.page_source.find('字符串')
作用:从html源码中搜索指定字符串
-1 :查找失败
4、单元素查找(返回值为1个节点对象)
1、driver.find_element_by_id('').text
2、driver.find_element_by_name('')
3、driver.find_element_by_class_name('')
4、driver.find_element_by_xpath('表达式')
5、多元素查找(节点对象列表)
1、driver.find_elements_by_...('')
6、节点对象.send_keys('内容')
7、节点对象.click()
8、driver.quit()
1、opt = webdriver.ChromeOptions()
2、opt.set_headless()
3、driver = webdriver.Chrome(options=opt)
5、京东商品爬取
1、网址 :https://www.jd.com/
2、目标 :输入搜索商品,爬取内容如下:
1、商品名称
2、商品价格
3、评论数量
4、商家名称
3、准备工作
1、搜索框属性值 : class->text
2、搜索按钮属性值: class->button
3、下一页属性值
能点 :class->pn-next
不能点:pn-next disabled
4、页面商品节点对象列表xpath表达式
//div[@id="J_goodsList"]/ul/li
4、保存数据
## 把下拉菜单拉到最底部
driver.execute_script(
'window.scrollTo(0,document.body.scrollHeight)'
)
1、网址 :https://www.douyu.com/directory/all
2、目标
1、主播名称
2、观众人数
3、统计一共有多少个主播,观众总数是多少
1、进程
1、系统中正在运行的一个程序
2、1个CPU核心1次只能执行1个进程,其他非运行
2、线程
1、进程中包含的执行单元,1个进程可包含多个线程
2、线程可使用所属进程空间
3、互斥锁:防止多个线程同时使用共享空间
3、GIL:全局解释锁
执行通行证,仅此1个,拿到通行证可执行,否则阻塞
4、应用场景
1、多进程 :大量的密集计算
2、多线程
爬虫 :网络I/O
写文件:本地磁盘I/O
#######操作共享资源的问题产生的原理######
number = 5000
f1 : number=number+1 加100次
f2 : number=number-1 减100次
计算值执行:
x1 = number+1 x1:5001
number = x1 number:5001
x2 = number-1 x2:5000
number = x2 number:5000
x1 = number+1 x1:5001
x2 = number-1 x2:4999
number = x2 number:4999
number = x1 number:5001
Day05回顾
1、Ajax动态加载
1、抓包工具抓参数 :WebForms -> QueryString
2、params = {QueryString一堆的查询参数}
3、URL地址 :抓包工具抓到Raw下的GET地址
2、selenium+phantomjs
1、selenium : 自动化测试工具
2、phantomjs: 无界面浏览器(内存中页面加载)
3、使用流程
1、from selenium import webdriver
2、driver=webdriver.PhantomJS(executable_path=)
3、driver.get(url)
4、driver.find_element_by_id('').send_keys('')
5、driver.find_element_by_id('').click()
6、driver.quit()
4、常用方法
1、driver.get(url)
2、driver.page_source
3、driver.page_source.find('')
-1 失败
4、driver.find_element_by_name('').text
5、driver.find_element_by_class_name('').text
6、driver.find_element_by_xpaht('')
7、节点对象.text
3、selenium+chromedriver
1、下载对应版本chromedriver
2、将chromedriver.exe放到python安装目录的Scripts
3、设置无界面模式
1、opt = webdriver.ChromeOptions()
2、opt.set_headless()
3、driver = webdriver.Chrome(options=opt)
4、driver执行JS
driver.execute_script('window.scrollTo(0,document.body.scrollHeight)')
4、多线程爬虫
1、多进程 :大量密集的计算
2、多线程 :I/O密集(爬虫网络I/O频繁)
1、原理 :图
2、知识点
1、队列(from multiprocessing import Queue)
1、put()
2、get()
1、get(block=True,timeout=2)
## 阻塞2秒钟,没有得到值抛出超时异常
2、get(block=False)
## 不阻塞,获取不到值马上抛异常
2、线程模块(from threading import Thread)
t = Thread(target=函数名)
t.start()
t.join()
1、网址 :百度搜 小米应用商店
2、目标 :应用分类(聊天社交)
1、应用名称
2、应用链接
3、抓取查询参数,F12->QueryString
URL :http://app.mi.com/categotyAllListApi?
params = {
page: ??
categoryId: 2
pageSize: 30
}
1、定义 :HMTL或XML解析器,依赖于lxml
2、安装
Anaconda Prompt: conda install beautifulsoup4
3、使用流程
1、导入模块
from bs4 import BeautifulSoup
2、创建解析对象
soup = BeautifulSoup(html,'lxml')
3、对象调用方法查找节点
rList = soup.find_all(条件)
4、BeautifulSoup支持的解析库
1、lxml :速度快,文档容错能力强
2、html.parser :Python标准库,速度一般,容错一般
3、xml :速度快,文档容错能力强
5、常用方法
1、find_all() :返回列表
rList = soup.find_all('div',{'id':'test'})
2、节点对象.get_text()
3、节点对象.string
1、网址 :https://bj.lianjia.com/ershoufang/
2、目标
1、名称
2、户型
3、面积
4、年份
5、楼层
6、地点
7、单价
8、总价
1、定义 :异步处理框架,可配置和可扩展程度非常高,Python中使用最广泛的爬虫框架
2、安装
1、Windows安装
Anaconda Prompt :conda install Scrapy
2、Ubuntu安装
1、安装依赖库
sudo apt-get install libssl-dev
sudo apt-get install libffi-dev
sudo apt-get install build-essential
sudo apt-get install python3-dev
sudo apt-get install liblxml2
sudo apt-get install liblxml2-dev
sudo apt-get install libxslt1-dev
sudo apt-get install zlib1g-dev
2、升级pyasn1模块
sudo pip3 install pysan1==0.4.4
3、sudo pip3 install Scrapy
1、引擎(Engine) : 整个框架核心
2、调度器(Scheduler) : 接受从引擎发来URL入队列
3、下载器(Downloader)
下载网页源码,返回给爬虫程序
4、项目管道(Item Pipeline)
数据处理
5、爬虫程序(spider)
6、下载器中间件(Downloader Middlewares)
引擎 ----> 下载器
7、蜘蛛中间件(Spider Middlewares)
引擎 ----> 爬虫程序
8、item :定义爬取的数据结构
1、新建项目
scrapy startproject 项目名
2、明确目标(items.py)
3、制作爬虫程序
scrapy genspider 文件名 域名
4、数据处理(pipelines.py)
5、全局配置(settings.py)
6、运行爬虫
scrapy crawl 爬虫名
1、目录结构
Baidu
├── Baidu # 项目目录
│ ├── items.py # 定义数据结构
│ ├── middlewares.py # 中间件实现
│ ├── pipelines.py # 数据处理
│ ├── settings.py # 全局配置
│ └── spiders
│ └── baidu.py # 爬虫文件
└── scrapy.cfg
2、setting.py配置
*1、是否遵守robots协议
ROBOTSTXT_OBEY = False
2、设置并发数量
CONCURRENT_REQUESTS = 32
3、下载延迟时间
DOWNLOAD_DELAY = 1
*4、请求头(添加User-Agent)
DEFAULT_REQUEST_HEADERS = {}
*5、项目管道
ITEM_PIPELINES = {
'Baidu.pipelines.BaiduPipeline': 300,}
1、scrapy startproject Baidu1
2、cd Baidu1
3、scrapy genspider baidu1 www.baidu.com
4、修改items.py(此项目不用改)
5、修改爬虫文件baidu1.py
def parse(self,response):
print('*'*50)
with open('百度.html','w',encoding='utf-8') as f:
f.write(response.text)
print('*'*50)
6、修改管道文件pipelines.py(此项目不用更改)
7、修改settings.py
1、是否遵守robots协议->False
2、DEFAULT_REQUEST_HEADERS = {添加User-Agent}
8、运行爬虫文件
scrapy crawl baidu1
1、创建begin.py(和scrapy.cfg文件同目录)
2、begin.py内容:
from scrapy import cmdline
cmdline.execute('scrapy crawl baidu1'.split())
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-feAwTWtZ-1603212105545)(C:\Users\Administrator\Desktop\python复习\scrapy框架流程_看图王.png)]
Day06回顾
1、多线程爬虫
1、URL队列 :put(url)
2、PARSE队列:get(url)->put(html)
3、创建多个线程
2、一边采集,一边解析
while True:
try:
....get(block=True,timeout=2)
...
except:
break
3、先采集,再解析
while True:
if not parseQueue.empty():
...get()
else:
break
4、BeautifulSoup
1、使用流程
from bs4 import BeautifulSoup
soup = BeautifulSoup(html,'html.parser')
rList = soup.find_all('div',{})
rObj = soup.find('div',{})
2、支持解析库
lxml、html.parser、xml
3、soup.find_all('div',{'class':'abc'})
4、soup.find('div',{'class':'abc'})
5、节点对象.get_text() : 文本(包含子节点)
节点对象.string : 文本(不包含子节点)
5、scrapy框架 :异步处理框架
1、组成
Engine、Scheduler、Downloader、Item Pipeline、Spider、Downloader Middlewares、Spider Middlewares
2、流程
1、Engine向Spider索要URL(第1个要爬取的)
2、交给Scheduler入队列
3、出队列,通过Downloader Middlewares给下载器
4、下载完后,通过Spider Middlewares交给Spider
5、Spider数据提取:
1、数据交给Item Pipeline
2、需要跟进URL,交给Scheduler入队列
6、创建项目流程
1、scrapy startproject Lianjia
2、cd Lianjia
3、scrapy genspider lianjia lianjia.com
4、items.py : 定义要爬取的数据结构
class LianjiaItem(scrapy.Item):
name = scrapy.Field()
price = scrapy.Field()
5、lianjia.py
import scrapy
class LianjiaSpider(scrapy.Spider):
name = 'lianjia'
allowed_domains = ['lianjia.com']
start_urls = ['http://www.lianjia.com/']
def parse(self,response):
pass
6、pipelines.py
class LianjiaPipeline(object):
def process_item(self,item,spider):
pass
class LianjiaMysqlPipeline(object):
def process_item(self,item,spider):
pass
7、settings.py
1、ROBOTSTXT_OBEY = False
2、USER_AGENT =
3、DEFAULT_REQUEST_HEADERS = {}
4、ITEM_PIPELINES = {
'Lianjia.pipelines.LianjiaPipeline' : 100,
'Lianjia.pipelines.LianjiaMysql...' : 200,
}
8、scrapy crawl lianjia
7、pycharm运行爬虫项目
1、begin.py(scrapy.cfg同级目录)
from scrapy import cmdline
cmdline.execute('scrapy crawl lianjia'.split())
1、作用:把1个函数当做1个生成器来使用
2、特点:让函数暂停,等待下1次调用
1、网址 :https://blog.csdn.net/cpongo4/article/details/86613730
2、标题、发布时间、阅读数
标题: //h1[@class="title-article"]/text()
时间: //span[@class="time"]/text()
数量: //span[@class="read-count"]/text()
3、流程
1、scrapy startproject Csdn
2、scrapy genspider csdn blog.csdn.net
3、item.py
4、csdn.py
from Csdn.items import CsdnItem
def parse(self,response):
item = CsdnItem()
...
yield item
5、pipelines.py
def process_item(self,item,spider):
....
return item
6、settings.py
ITEM_PIPELINES = {
'Csdn.pipelines.CsdnPipeline' : 300,
}
7、scrapy crawl csdn
1、extract() : 获取选择器对象中的文本内容
response.xpath('')
结果: [<selector ... data='文本内容'>,<>]
response.xpath('').extract()
结果: ['文本内容1','文本内容2']
2、pipelines.py中必须有1个函数叫:
def process_item(self,item,spider):
return item
LOG_LEVEL = ''
LOG_FILE = '文件名.log'
5层日志级别
1、CRITICAL : 严重错误
2、ERROR : 普通错误(显示ERROR和严重错误)
*3、WARNING : 警告信息(显示WARNING及以上信息)
4、INFO : 一般信息(显示INFO及以上级别)
5、DEBUG : 显示DEBUG及以上级别信息
1、网址调试信息:https://hr.tencent.com/position.php?start=??
2、xpath表达式
基准 :
//tr[@class="even"] | //tr[@class="odd"]
1、职位名称: ./td[1]/a/text()
2、职位类别: ./td[2]/text()
3、招聘人数: ./td[3]/text()
4、招聘地点: ./td[4]/text()
5、发布时间: ./td[5]/text()
6、职位链接: ./td[1]/a/@href
1、json文件
scrapy crawl tengxun -o tengxun.json
设置导出编码 : FEED_EXPORT_ENCODING = 'utf-8'
2、csv文件
scrapy crawl tengxun -o tengxun.csv
csv文件出现空行解决方法(修改源码)
D:\Anaconda3\Lib\site-packages\scrapy\exporters.py 做如下修改(搜索'csv'):
self.stream = io.TextIOWrapper(
file,
newline='', # 添加此行
1、通过F12抓包,抓取到QueryString中参数如下:
ch: beauty # 图片分类
sn: 90
# sn表示图片编号,0(1-30张),30(31-60张)
listtype: new
temp: 1
2、Request URL:
http://image.so.com/zj?ch=beauty&sn=90&listtype=new&temp=1
***3、项目实现
1、在items.py中定义图片链接字段
2、爬虫文件,可重写start_requests方法
1、去掉 start_urls = ['']
2、def start_requests(self):
... ...
yield scrapy.Request(url,callback=)
3、管道文件pipelines.py
# 导入scrapy定义好的图片管道类
from scrapy.pipelines.images import ImagesPipeline
# 定义类,继承图片管道类
class SoPipeline(ImagesPipeline):
# 重写方法
def get_media_requests(self,item,info):
# 把图片链接发给调度器
yield scrapy.Request(item['imgLink']
4、settings.py中定义图片存储路径
IMAGES_STORE = 'D:\\爬虫'
盗墓笔记:http://www.daomubiji.com/dao-mu-bi-ji-1
标题名称
章节数量
章节名称
链接
Day07回顾
1、response.xpath('')
结果:列表,选择器对象
extract():提取文本内容,将列表中所有元素序列化为Unicode字符串
2、MongoDB持久化存储
1、settings.py设置相关变量
2、pipelines.py自定义管道类
class CsdnMongoPipeline(object):
def __init__(self):
pass
def process_item(self,item,spider):
return item
# 爬虫程序结束时执行此方法
def close_spider(self,spider):
pass
3、settings.py添加ITME_PIPELINES={}
ITME_PIPELINES={
'Csdn.pipelines.CsdnMongoPipeline':500,
}
3、settings.py常用变量
LOG_LEVEL = ''
LOG_FILE = ''
FEED_EXPORT_ENCODING = ''
IMAGES_SOTRE = ''
4、日志级别
DEBUG < INFO < WARNING < ERROR < CRITICAL
5、保存为csv、json文件
1、scrapy crawl 爬虫名 -o XXX.json/XXX.csv
2、FEED_EXPORT_ENCODING = 'gb18030'
3、解决csv文件空行问题
找到exporters.py改一下源码(csv的类):
files,
newline = '',
6、图片管道类
1、items.py
imgLink = scrapy.Field()
2、pipelines.py
from scrapy.pipelines.images import ImagesPipeline
import scrapy
class SoPipeline(ImagesPipeline):
# 重写方法
def get_media_requests(self,item,info):
yield scrapy.Request(item['imgLink'])
3、settings.py
IMAGES_STORE = ''
7、重写爬虫文件start_requests()方法
1、作用 :不再爬取start_urls地址
2、流程
1、把start_urls去掉
2、def start_requests(self):
pass
8、scrapy.Request(url,callback=解析方法名)
1、scrapy shell URL地址
*2、request.headers : 请求头(字典)
*3、request.meta : 定义代理等相关信息(字典)
4、response.text : 字符串
5、response.body : 字节流
6、response.xpath('')
1、url
2、callback
3、headers
*4、meta : 定义代理等相关信息{}
*5、dont_filter : 是否忽略域组限制
默认False,检查allowed_domains=['']
6、encoding : 默认utf-8,不用配置
1、安装pip
1、从官网下载pip安装包,并解压
2、cd到解压路径,执行如下命令
python setup.py install
####################################
如果pip版本低则升级pip
python -m pip install --upgrade pip
####################################
2、升级Scrapy
python -m pip install --upgrade Scrapy
1、以前setting.py(少量User-Agent)
1、USER_AGENT=''
2、DEFAULT_REQUEST_HEADERS={}
2、现在middlewares.py设置中间件
1、项目目录新建useragents.py,存放大量agent
uaList = ['','','','']
2、middlewares.py中创建中间件类
from Testmid.useragents import *
class RandomUAmiddleware(object):
def process_request(self,request,spider):
# 此处注意 headers 属性
request.headers['User-Agent'] = ...
3、开启中间件(settings.py)
DOWNLOADER_MIDDLEWARES={
'Testmid.middlewares.RandomUAmiddleware':300,
}
request.meta['proxy']=random.choice(proxyList)
1、OCR
光学字符识别,通过字符形状-->电子文本
2、tesseract-ocr(OCR的一个底层识别库,不能导入)
1、安装(windows)
1、windows下载安装,并添加到环境变量
https://sourceforge.net/projects/tesseract-ocr-alt/files/tesseract-ocr-setup-3.02.02.exe/download
2、环境变量路径
C:\Program Files (x86)\Tesseract-OCR
2、安装(Ubuntu和Mac)
sudo apt-get install tesseract-ocr
brew install tesseract
3、验证(测试)识别
cmd终端: tesseract test1.jpg test1
4、pytesseract模块
1、安装
Anaconda Prompt: pip install pytesseract
2、使用示例
1、tesseract-ocr识别率很低,很多文字变形,干扰,导致无法识别
2、在线打码
1、云打码平台 :http://www.yundama.com/
2、注册用户 - 充值 - 下载接口(开发文档)
3、题分价格(类型码,在程序中写正确)
3、示例
1、调整接口文档(YDM.py)
2、写主体程序
1、Windows
1、直接下载安装
2、启动并连接
1、服务端启动
cmd -> redis-server.exe redis.conf
2、客户端连接
cmd -> redis-cli.exe
3、安装图形界面管理工具RedisDesktopManager
左下角新建连接 + Connect to Redis Server
2、Ubuntu
1、安装 :sudo apt-get install redis-server
2、启动 :redis-server
3、连接 :redis-cli -h IP地址
1、原理 :多台机器共享1个爬取队列
2、实现 :重写scrapy调度器(scrapy_redis模块)
安装 :Anaconda Prompt:
pip install scrapy_redis
3、为什么使用redis
1、Redis是非关系型数据库,key-value形式存储
2、Redis集合,存储每个request的指纹
1、在settings.py中添加如下代码
# 使用scrapy_redis调度器
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
# 使用scrapy_redis的去重机制
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
# 不清除请求指纹
SCHEDULER_PERSIST = True
# 设置管道
ITEM_PIPELINES = {
'scrapy_redis.pipelines.RedisPipeline':500,
}
REDIS_HOST = '192.168.1.103'
REDIS_PORT = 6379
2、运行爬虫,数据会存储到Redis数据库
tengxun:dupefilter : 请求指纹
tengxun:items : 数据
tengxun:requests : 请求头信息
1、把ITEM_PIPELINES管道设置为mongodb的管道
2、把代码拷贝一份到Ubuntu,同时启动爬虫
3、查看mongdb中的集合数据,不会有重复
## 在12步的基础之上改写爬虫文件tengxun.py
1、from scrapy_redis.spiders import RedisSpider
2、class TengxunSpider(RedisSpider):
# 去掉start_urls,添加redis_key
redis_key='tengxunspider:start_urls'
3、多台机器同时启动项目
4、进入redis命令行,发送执行
>>>lpush tengxunspider:start_urls https://hr.tencent.com/position.php?start=0
1、设置手机
1、设置无线DHCP服务为手动
IP地址 :你电脑的IP(ipconfig)
端口号 :8888
2、手机打开浏览器,输入 http://IP:8888 下载证书并安装
2、设置电脑(见图,更改注册表)
3、设置Fiddler
1、Tools -> Options
1、HTTPS选项卡 :...from all processes
2、Connections选项卡
1、端口号:8888
2、Allow remote computers to Connect
4、重启Fiddler
1、运维概述
1、什么是运维
服务器运行维护
2、名词
1、IDC(互联网数据中心)
服务器租用、服务器托管、机柜租用
2、监控软件
常用监控软件 :zabbix、nagios、cactti
3、常用Linux操作系统
RedHat
CentOS
Ubuntu
4、虚拟化(见图)
5、Web正向代理
1、访问原来无法访问的资源(google)
2、对Web服务器隐藏用户信息
6、nginx反向代理
1、流程
客户端->代理服务器->将请求转发给公司内部网络的服务器
2、作用
1、保证内网安全,使用反向代理阻止WEB攻击
2、负载均衡,优化网站负载
3、负载均衡规则
1、轮询 :逐一循环调度
2、权重(weight) : 指定轮询几率,权重值和访问比例成正比
3、ip_hash:根据客户端IP分配固定的后端服务器
3、nginx反向代理实现负载均衡
修改nginx配置文件配置nginx调度器
upstream servers{
server 10.10.10.11;
server 10.10.10.12 weight=2;
server 10.10.10.13;
server 10.10.10.14 backup;
}
server{
listen 80;
server_name www.lion.com;
localtion /{
proxy_pass http://servers
...
...
}
}
2、运维工具
1、xshell(软件,安装在windows)
安全终端模拟软件
2、xshell使用方法
文件-新建-输入服务器IP-输入用户名-输入密码-确认连接
3、windows <-> Linux
1、安装lszrz
sudo apt-get install lrzsz
2、windows -> Linux
xshell终端 :rz
3、Linux -> windows
xshell终端 :sz 文件名
3、Linux常用命令
1、ifconfig : IP地址和MAC地址
2、ping :测试网络连通性
ping IP地址 -c 次数
3、nslookup : 解析域名对应的IP地址
nslookup www.baidu.com
4、sudo /etc/init.d/networking restart
重启网络
5、top
Linux下任务管理器,动态显示CPU及内存使用率
6、ps -aux
显示系统进程命令(PID)
ps -aux | grep 'mysql'
7、ssh
远程连接到服务器
ssh 用户名@IP地址
8、scp
复制文件到远程服务器
scp 文件名 用户名@IP地址:绝对路径
9、kill
杀死一个进程
sudo kill 进程PID号
10、df -h
查看磁盘使用情况
11、ls -lh 文件名: h提供易读容量单位
12、chmod
修改文件权限
chmod +x 文件名
chmod 644 文件名
rw-r--r--
r : 4
w : 2
x : 1
13、wc -l
统计文件行数
wc -l /etc/passwd
14、sort
对文件内容进行排序
sort 文件名
15、uniq -c
去重重复行,并统计每行出现的次数(相邻行)
sort 文件名 | uniq -c
16、du -sh 目录名: 显示目录大小
17、du -ah 目录名: 显示目录下所有文件,子目录,子目录中文件所占空间
18、grep
ps -aux | grep mysql
^ : 开头
$ : 结尾
19、find
1、find 路径 -name '文件名'
find 路径 -iname '文件名' ##忽略大小写
2、find 路径 -ctime +3 # 3天以前文件
-1 # 1天以内文件
find 路径 -cmin +5
3、find 路径 -size +10M
find 路径 -size -1G
4、周期性计划任务
1、进入周期性计划任务设置
crontab -e
按4
2、设置周期性计划任务
* * * * *
分 时 日 月 周
分:0-59
时:0-23
日:1-31
月:1-12
周:0-6
* :所有可能值
, :多个时间点
00 00 1,5 * * python3 /home/tarena/a.py
/ :指定时间间隔频率
*/10 * * * * python3 /home/tarena/a.py
- :指定一个时间段
0点到6点之间,每隔1个小时执行命令
0 0-6/1 * * * python3 /home/tarena/a.py
1、每分钟执行一次a.py
* * * * * python3 /home/tarena/a.py
2、每小时的第3分钟和第15分钟执行
3,15 * * * * python3 /home/tarena/a.py
3、每天18:00-23:00,每小时执行
0 18-23/1 * * * python3 /home/tarena/a.py
4、每周六、日的0点0分执行
0 0 * * 6,0 python3 /home/tarena/a.py
5、awk的使用
1、语法格式 :awk 选项 '动作' 文件列表
2、用法 :Linux 命令 | awk 选项 '动作'
3、示例
1、awk '{print "AAA"}' ip.txt
2、df -h | awk '{print $1}'
3、显示当前系统的所有用户名
cat /etc/passwd | awk -F ":" '{print $1}'
4、提取本机的IP地址
ifconfig | head -2 | tail -1 | awk '{print $2}' | awk -F ':' '{print $2}'
5、nginx的访问日志路径:
/var/log/nginx/access.log
访问记录 :
127.0.0.1 - - [29/Jan/2019:19:34:42 +0800] "GET / HTTP/1.1" 200 396 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:64.0) Gecko/20100101 Firefox/64.0"
1、把访问过我的IP地址输出
awk '{print $1}' access.log | sort | uniq
2、统计有多少个IP访问过我
awk '{print $1}' access.log | sort | uniq | wc -l
*3、统计每个IP地址访问我的次数,把访问次数最多的前10个IP输出
awk '{print $1}' access.log | sort | uniq -c | sort -rn -k 1 | head -10
4、sort的参数
sort -n : 以数值方式来排序
sort -r : 倒序排列
sort -k 数字: 按照第 几 列进行排序
sort -rnk 1 : 将第1列按照数值方式倒序排
目标:
打开浏览器输入:www.tiger.com进入django项目首页
1、概念
1、Django项目(Web应用)
2、Web服务
1、nginx :高并发处理的好
2、apache:稳定
LAMP :Linux、Apache、MySQL、Python/Php
LNMP :Linux、Nginx、MySQL、Python/Php
3、uwsgi
是Web服务与Web框架之间简单而通用的接口
2、项目部署(nginx+uwsgi+django)
1、部署环境准备
1、确保django项目能够运行
2、安装nginx(使用apt-get安装)
1、安装 :sudo apt-get install nginx
2、启动 :sudo /etc/init.d/nginx restart
3、验证 :打开浏览器,输入127.0.0.1:80-->出现Welcome to Nginx界面
3、安装uwsgi(必须使用pip3安装)
1、安装 :sudo pip3 install uwsgi
2、验证 :uwsgi --http :8888 --chdir /home/tarena/project/fruitday/ --module fruitday.wsgi
3、部署在线商城项目
1、配置uwsgi(配置文件)
1、在项目目录(manage.py所在路径)中新建uwsgi配置文件:fruitdayUwsgi.ini
2、vi fruitdayUwsgi.ini
[uwsgi]
# 指定和nginx通信的端口
socket=127.0.0.1:8001
# 指定项目路径
chdir=/home/tarena/project/fruitday
# 指定wsgi.py路径
wsgi-file=fruitday/wsgi.py
# 进程数
processes=4
# 线程数
thread=2
# 本项目的uwsgi自身占用端口
stats=127.0.0.1:8080
2、配置nginx(配置文件)
1、sudo -i
2、cd /etc/nginx/sites-enabled
3、vi projectNginx.conf
server{
# 监听本项目的端口,浏览器输入的端口
listen 80;
server_name www.lion.com;
charset utf-8;
# 收集项目静态文件的路径
location /static{
alias /home/tarena/project/fruitday/static;
}
# 和uwsgi通信端口和通信文件uwsgi_params
location /{
include uwsgi_params;
uwsgi_pass 127.0.0.1:8001;
}
}
4、sudo /etc/init.d/nginx restart
5、拷贝uwsgi_params文件到项目目录
cp /etc/nginx/uwsgi_params /home/tarena/project/fruitday/
6、关闭nginx默认监听端口80
1、sudo -i
2、cd /etc/nginx/sites-enabled/
3、vi default
# 把原来默认的80改为800
listen 800 default_server
listen [::]:800 default_server;
7、sudo /etc/init.d/nginx restart
3、收集静态文件(配置django项目)
1、在settings.py中添加路径(STATIC_ROOT)
STATIC_ROOT = '/home/tarena/project/fruitday/static/'
2、收集静态文件
python3 manage.py collectstatic
4、uwsgi启动项目
1、切换到项目目录
cd /home/tarena/project/fruitday
2、利用uwsgi启动项目
uwsgi --ini fruitdayUwsgi.ini
5、添加本地DNS解析
1、sudo -i
2、vi /etc/hosts
## 添加如下内容:
127.0.0.1 www.lion.com
3、重启网络
/etc/init.d/networking restart
6、最终验证
打开浏览器,输入:www.lion.com/user/login
跳转到登录界面,部署成功
#### pip3不能使用的解决方法 #####
1、cd /home/tarena/project/setuptools-33.1.1
2、sudo python3 setup.py install
3、sudo apt-get autoremove python3-pip
4、sudo python3 easy_install.py pip
5、sudo apt-get install python3-pip
## 执行pip3 list会报错 ##
错误:cannot import name 'main'
6、sudo vi /usr/bin/pip3
把原来的3行代码注释掉,添加新代码后保存退出:
from pip import __main__
if __name__ == '__main__':
sys.exit(__main__._main())
7、pip3 list
接
cmd -> redis-cli.exe
3、安装图形界面管理工具RedisDesktopManager
左下角新建连接 + Connect to Redis Server
2、Ubuntu
1、安装 :sudo apt-get install redis-server
2、启动 :redis-server
3、连接 :redis-cli -h IP地址
#### 9、分布式爬虫
```python
1、原理 :多台机器共享1个爬取队列
2、实现 :重写scrapy调度器(scrapy_redis模块)
安装 :Anaconda Prompt:
pip install scrapy_redis
3、为什么使用redis
1、Redis是非关系型数据库,key-value形式存储
2、Redis集合,存储每个request的指纹
1、在settings.py中添加如下代码
# 使用scrapy_redis调度器
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
# 使用scrapy_redis的去重机制
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
# 不清除请求指纹
SCHEDULER_PERSIST = True
# 设置管道
ITEM_PIPELINES = {
'scrapy_redis.pipelines.RedisPipeline':500,
}
REDIS_HOST = '192.168.1.103'
REDIS_PORT = 6379
2、运行爬虫,数据会存储到Redis数据库
tengxun:dupefilter : 请求指纹
tengxun:items : 数据
tengxun:requests : 请求头信息
1、把ITEM_PIPELINES管道设置为mongodb的管道
2、把代码拷贝一份到Ubuntu,同时启动爬虫
3、查看mongdb中的集合数据,不会有重复
## 在12步的基础之上改写爬虫文件tengxun.py
1、from scrapy_redis.spiders import RedisSpider
2、class TengxunSpider(RedisSpider):
# 去掉start_urls,添加redis_key
redis_key='tengxunspider:start_urls'
3、多台机器同时启动项目
4、进入redis命令行,发送执行
>>>lpush tengxunspider:start_urls https://hr.tencent.com/position.php?start=0
1、设置手机
1、设置无线DHCP服务为手动
IP地址 :你电脑的IP(ipconfig)
端口号 :8888
2、手机打开浏览器,输入 http://IP:8888 下载证书并安装
2、设置电脑(见图,更改注册表)
3、设置Fiddler
1、Tools -> Options
1、HTTPS选项卡 :...from all processes
2、Connections选项卡
1、端口号:8888
2、Allow remote computers to Connect
4、重启Fiddler
1、运维概述
1、什么是运维
服务器运行维护
2、名词
1、IDC(互联网数据中心)
服务器租用、服务器托管、机柜租用
2、监控软件
常用监控软件 :zabbix、nagios、cactti
3、常用Linux操作系统
RedHat
CentOS
Ubuntu
4、虚拟化(见图)
5、Web正向代理
1、访问原来无法访问的资源(google)
2、对Web服务器隐藏用户信息
6、nginx反向代理
1、流程
客户端->代理服务器->将请求转发给公司内部网络的服务器
2、作用
1、保证内网安全,使用反向代理阻止WEB攻击
2、负载均衡,优化网站负载
3、负载均衡规则
1、轮询 :逐一循环调度
2、权重(weight) : 指定轮询几率,权重值和访问比例成正比
3、ip_hash:根据客户端IP分配固定的后端服务器
3、nginx反向代理实现负载均衡
修改nginx配置文件配置nginx调度器
upstream servers{
server 10.10.10.11;
server 10.10.10.12 weight=2;
server 10.10.10.13;
server 10.10.10.14 backup;
}
server{
listen 80;
server_name www.lion.com;
localtion /{
proxy_pass http://servers
...
...
}
}
2、运维工具
1、xshell(软件,安装在windows)
安全终端模拟软件
2、xshell使用方法
文件-新建-输入服务器IP-输入用户名-输入密码-确认连接
3、windows <-> Linux
1、安装lszrz
sudo apt-get install lrzsz
2、windows -> Linux
xshell终端 :rz
3、Linux -> windows
xshell终端 :sz 文件名
3、Linux常用命令
1、ifconfig : IP地址和MAC地址
2、ping :测试网络连通性
ping IP地址 -c 次数
3、nslookup : 解析域名对应的IP地址
nslookup www.baidu.com
4、sudo /etc/init.d/networking restart
重启网络
5、top
Linux下任务管理器,动态显示CPU及内存使用率
6、ps -aux
显示系统进程命令(PID)
ps -aux | grep 'mysql'
7、ssh
远程连接到服务器
ssh 用户名@IP地址
8、scp
复制文件到远程服务器
scp 文件名 用户名@IP地址:绝对路径
9、kill
杀死一个进程
sudo kill 进程PID号
10、df -h
查看磁盘使用情况
11、ls -lh 文件名: h提供易读容量单位
12、chmod
修改文件权限
chmod +x 文件名
chmod 644 文件名
rw-r--r--
r : 4
w : 2
x : 1
13、wc -l
统计文件行数
wc -l /etc/passwd
14、sort
对文件内容进行排序
sort 文件名
15、uniq -c
去重重复行,并统计每行出现的次数(相邻行)
sort 文件名 | uniq -c
16、du -sh 目录名: 显示目录大小
17、du -ah 目录名: 显示目录下所有文件,子目录,子目录中文件所占空间
18、grep
ps -aux | grep mysql
^ : 开头
$ : 结尾
19、find
1、find 路径 -name '文件名'
find 路径 -iname '文件名' ##忽略大小写
2、find 路径 -ctime +3 # 3天以前文件
-1 # 1天以内文件
find 路径 -cmin +5
3、find 路径 -size +10M
find 路径 -size -1G
4、周期性计划任务
1、进入周期性计划任务设置
crontab -e
按4
2、设置周期性计划任务
* * * * *
分 时 日 月 周
分:0-59
时:0-23
日:1-31
月:1-12
周:0-6
* :所有可能值
, :多个时间点
00 00 1,5 * * python3 /home/tarena/a.py
/ :指定时间间隔频率
*/10 * * * * python3 /home/tarena/a.py
- :指定一个时间段
0点到6点之间,每隔1个小时执行命令
0 0-6/1 * * * python3 /home/tarena/a.py
1、每分钟执行一次a.py
* * * * * python3 /home/tarena/a.py
2、每小时的第3分钟和第15分钟执行
3,15 * * * * python3 /home/tarena/a.py
3、每天18:00-23:00,每小时执行
0 18-23/1 * * * python3 /home/tarena/a.py
4、每周六、日的0点0分执行
0 0 * * 6,0 python3 /home/tarena/a.py
5、awk的使用
1、语法格式 :awk 选项 '动作' 文件列表
2、用法 :Linux 命令 | awk 选项 '动作'
3、示例
1、awk '{print "AAA"}' ip.txt
2、df -h | awk '{print $1}'
3、显示当前系统的所有用户名
cat /etc/passwd | awk -F ":" '{print $1}'
4、提取本机的IP地址
ifconfig | head -2 | tail -1 | awk '{print $2}' | awk -F ':' '{print $2}'
5、nginx的访问日志路径:
/var/log/nginx/access.log
访问记录 :
127.0.0.1 - - [29/Jan/2019:19:34:42 +0800] "GET / HTTP/1.1" 200 396 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:64.0) Gecko/20100101 Firefox/64.0"
1、把访问过我的IP地址输出
awk '{print $1}' access.log | sort | uniq
2、统计有多少个IP访问过我
awk '{print $1}' access.log | sort | uniq | wc -l
*3、统计每个IP地址访问我的次数,把访问次数最多的前10个IP输出
awk '{print $1}' access.log | sort | uniq -c | sort -rn -k 1 | head -10
4、sort的参数
sort -n : 以数值方式来排序
sort -r : 倒序排列
sort -k 数字: 按照第 几 列进行排序
sort -rnk 1 : 将第1列按照数值方式倒序排
目标:
打开浏览器输入:www.tiger.com进入django项目首页
1、概念
1、Django项目(Web应用)
2、Web服务
1、nginx :高并发处理的好
2、apache:稳定
LAMP :Linux、Apache、MySQL、Python/Php
LNMP :Linux、Nginx、MySQL、Python/Php
3、uwsgi
是Web服务与Web框架之间简单而通用的接口
2、项目部署(nginx+uwsgi+django)
1、部署环境准备
1、确保django项目能够运行
2、安装nginx(使用apt-get安装)
1、安装 :sudo apt-get install nginx
2、启动 :sudo /etc/init.d/nginx restart
3、验证 :打开浏览器,输入127.0.0.1:80-->出现Welcome to Nginx界面
3、安装uwsgi(必须使用pip3安装)
1、安装 :sudo pip3 install uwsgi
2、验证 :uwsgi --http :8888 --chdir /home/tarena/project/fruitday/ --module fruitday.wsgi
3、部署在线商城项目
1、配置uwsgi(配置文件)
1、在项目目录(manage.py所在路径)中新建uwsgi配置文件:fruitdayUwsgi.ini
2、vi fruitdayUwsgi.ini
[uwsgi]
# 指定和nginx通信的端口
socket=127.0.0.1:8001
# 指定项目路径
chdir=/home/tarena/project/fruitday
# 指定wsgi.py路径
wsgi-file=fruitday/wsgi.py
# 进程数
processes=4
# 线程数
thread=2
# 本项目的uwsgi自身占用端口
stats=127.0.0.1:8080
2、配置nginx(配置文件)
1、sudo -i
2、cd /etc/nginx/sites-enabled
3、vi projectNginx.conf
server{
# 监听本项目的端口,浏览器输入的端口
listen 80;
server_name www.lion.com;
charset utf-8;
# 收集项目静态文件的路径
location /static{
alias /home/tarena/project/fruitday/static;
}
# 和uwsgi通信端口和通信文件uwsgi_params
location /{
include uwsgi_params;
uwsgi_pass 127.0.0.1:8001;
}
}
4、sudo /etc/init.d/nginx restart
5、拷贝uwsgi_params文件到项目目录
cp /etc/nginx/uwsgi_params /home/tarena/project/fruitday/
6、关闭nginx默认监听端口80
1、sudo -i
2、cd /etc/nginx/sites-enabled/
3、vi default
# 把原来默认的80改为800
listen 800 default_server
listen [::]:800 default_server;
7、sudo /etc/init.d/nginx restart
3、收集静态文件(配置django项目)
1、在settings.py中添加路径(STATIC_ROOT)
STATIC_ROOT = '/home/tarena/project/fruitday/static/'
2、收集静态文件
python3 manage.py collectstatic
4、uwsgi启动项目
1、切换到项目目录
cd /home/tarena/project/fruitday
2、利用uwsgi启动项目
uwsgi --ini fruitdayUwsgi.ini
5、添加本地DNS解析
1、sudo -i
2、vi /etc/hosts
## 添加如下内容:
127.0.0.1 www.lion.com
3、重启网络
/etc/init.d/networking restart
6、最终验证
打开浏览器,输入:www.lion.com/user/login
跳转到登录界面,部署成功
#### pip3不能使用的解决方法 #####
1、cd /home/tarena/project/setuptools-33.1.1
2、sudo python3 setup.py install
3、sudo apt-get autoremove python3-pip
4、sudo python3 easy_install.py pip
5、sudo apt-get install python3-pip
## 执行pip3 list会报错 ##
错误:cannot import name 'main'
6、sudo vi /usr/bin/pip3
把原来的3行代码注释掉,添加新代码后保存退出:
from pip import __main__
if __name__ == '__main__':
sys.exit(__main__._main())
7、pip3 list
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8KmUu9kO-1603212105547)(C:\Users\Administrator\Desktop\python复习\用户访问浏览器过程_看图王.png)]
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。