爬虫
2017-03-06 20:59:43 0 举报
AI智能生成
爬虫,又被称为网页蜘蛛,是一种自动化程序,用于在互联网上进行数据抓取。它通过模拟人类浏览网页的行为,自动访问网站并提取所需的信息。爬虫可以根据预定的规则和算法,遍历整个网络结构,搜索和收集特定类型的数据。它可以从网页中提取文本、图片、链接等各种元素,并将其整理存储为结构化的数据形式。爬虫在各个领域都有广泛的应用,如搜索引擎、数据分析、市场调研等。然而,由于爬虫可能会对网站的服务器造成过大的负载压力,因此在使用时需要遵守相关的法律和道德规范,尊重网站的访问规则和隐私权。
作者其他创作
大纲/内容
准备工作
概念
使用html 协议从网站采集提取数据的过程
web前端
html
定义网页内容
css
定义网页样式,表现
javascript
定义网页行为,交互
http超文本传输协议
编程语言 python
http编程
python 标准库 urllib
requests 第三方库
数据采集
文本
图片
子主题
子主题
工具
环境
系统
window
linux
mac
python
开发工具
pycharm
sublime text
数据库
sqlite
mongoDB
MongoChef
浏览器
chrome
http
postman
fiddler
子主题
web前端
概念
网页
资源
网站
这种是叫实体字符
css
级联样式表
定义网页表现
选择器
类选择器
.
id 选择器
#
<style type="text/css">
定义方式
直接定义在标签里
padding 文本内容到边框的距离
定义在head里
定义在css文件里
javascript
定义网页行为
有浏览器就可以执行
<script>
html 内部引用
<script> document.write('<h1>hello world</h1>'); </script>
js存到js文件里
<script src='scripts/custom.js'></script>
增强用户体验
js执行浏览器后退
onclick="javascript:window.history.go(-1)" 向前一步是1 ,向前两步是2 ,后退一步是-1
浏览器跳转到哪个链接
window.location.href=url
html
标签
标签描述元素
元素
element
定义呈现内容
属性
attribute
将元素描述更彻底
网页结构 ,首先头部是文档声明,<html></html> 网页构成,head头部中内容不直接呈现在网页上,body 的内容呈现是网页上 ,charset 可以看到网页是用的什么编码,需要确认下,这样爬虫才好处理文本的编码,不同标签可能呈现的文本样式雷同,标签可以嵌套使用,就是一个标签可以放在另一对标签里面。
img标签里面的src 是 source的缩写,alt 是图片对应的文本声明,在图片不能显示的时候,显示图片的文本信息
定义网页内容
form 用来收集用户输入的信息
textarea 多行文本
用来包含语义内容(默认不显示)
div
块级元素
span
区分一段范围
行级元素
meta 是元数据声明
站点 WebSite
网页 Web Page
数据采集
文本采集
正则
模块
re
正则对象
模式对象
编译:re.compile('模式')
预定义的字符类
.
表示除\n以外的所有字符
\d
数字[0-9]
\D
非数字[^0-9]
\s
空白字符
\S
非空白字符
\w
字母数字[a-zA-Z0-9]
\W
非字母数字[^a-zA-Z0-9]
量词
? 0 或1 次
* 0 到多次
+ 1到多次
{n,m} 特定次数
匹配对象
爬虫例子
import requests
import re
def extra_links():
url = 'http://www.xinshipu.com/caipu/17844/'
base_url = 'http://www.xinshipu.com'
headers = {'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:50.0) Gecko/20100101 Firefox/50.0'}
r = requests.get(url,headers=headers)
if r.status_code == 200:
html = r.text
hrefs = re.findall(r'<a href="(.*?)" title=".*?" class="shipu">',html)
with open('links.txt','w',encoding='utf-8') as f:
for link in hrefs:
f.write('{}{}{}'.format(base_url,link,'\n'))
del r
if __name__ == '__main__':
extra_links()
import re
def extra_links():
url = 'http://www.xinshipu.com/caipu/17844/'
base_url = 'http://www.xinshipu.com'
headers = {'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:50.0) Gecko/20100101 Firefox/50.0'}
r = requests.get(url,headers=headers)
if r.status_code == 200:
html = r.text
hrefs = re.findall(r'<a href="(.*?)" title=".*?" class="shipu">',html)
with open('links.txt','w',encoding='utf-8') as f:
for link in hrefs:
f.write('{}{}{}'.format(base_url,link,'\n'))
del r
if __name__ == '__main__':
extra_links()
图片下载
一次性将图片塞到图片文件里
if r.status_code == 200:
... with open('005.jpg','wb') as f:
... f.write(r.content)
... with open('005.jpg','wb') as f:
... f.write(r.content)
将图片切割成若干块存到文件
if r.status_code == 200:
... with open('004.jpg','wb') as f:
... for chunk in r.iter_content(1024):
... f.write(chunk)
... with open('004.jpg','wb') as f:
... for chunk in r.iter_content(1024):
... f.write(chunk)
>>> import requests
>>> img_url = 'http://pisces.bbystatic.com/BestBuy_US/store/ee/2015/com/pm/nav_2in1_1115.jpg'
>>> r = requests.get(img_url)
>>> img_url = 'http://pisces.bbystatic.com/BestBuy_US/store/ee/2015/com/pm/nav_2in1_1115.jpg'
>>> r = requests.get(img_url)
标注库 urllib
urllib.request.urlretrieve() 接受检索一个地址的信息,接受img_url ,保存到006.jpg 这个文件里面
>>> import urllib.request
>>> urllib.request.urlretrieve(img_url,'006.jpg')
('006.jpg', <http.client.HTTPMessage object at 0x1057309e8>)
>>> urllib.request.urlretrieve(img_url,'006.jpg')
('006.jpg', <http.client.HTTPMessage object at 0x1057309e8>)
过滤字节顺序标记('/u') ,把encoding="utf-8" 改成encoding="utf-8-sig"
数据文件存储
csv
实例
子主题
读取例子
with open('data.csv') as f:... reader = csv.DictReader(f)... for row in reader:... for k in row.keys():... print (row.get(k))
with open('data.csv') as f:... reader = csv.DictReader(f)... for row in reader:... print (row)
with open('data.csv') as f:... reader = csv.DictReader(f)... for row in reader:... for k,v in row.items():... print ('{}--{}'.format(k,v))
读取器
reader = csv.reader(f)
>>> with open('course.csv') as f:... reader = csv.reader(f)... for row in reader:... print (row)... ['id', 'title', 'lecture', 'price']['1', 'pthon', 'eason', '120']['2', 'flask', 'lily', '99']['3', 'linux', 'liua', '99']
以字典表形式读取
reader= csv.DictReader(f)
>>> with open('course.csv') as f:... reader = csv.DictReader(f)... for row in reader:... print (row)... {'price': '120', 'lecture': 'eason', 'id': '1', 'title': 'pthon'}{'price': '99', 'lecture': 'lily', 'id': '2', 'title': 'flask'}{'price': '99', 'lecture': 'liua', 'id': '3', 'title': 'linux'}
写入例子
import csv
with open('course.csv','w',encoding='utf8') as f:... writer = csv.writer(f)... writer.writerow(header)... writer.writerows(rows)...
header = ['id','title','lecture','price']
rows = [(1,'pthon','eason',120),(2,'flask','lily',99),(3,'linux','liua',99)]
写入器
writer = csv.writer(f)
.writerow(序列) 写入行
.writerows(序列) 写入多行
excel
openpyxl
工作薄 Workbook
.sheetnames 所有工作表名称
.wb.active 获取当前工作表
.save('**.xlsx')
工作表 Worksheet
.title 标题
['A1'] 行列坐标
.cell(row=行,column=列,value= 值) 单元格
文本
实例创建
open('file.txt','r|w|a',encoding='utf8' )
读取
.read()
.readline()
.readlines()
移动指针
.seek(0)
写入
.write()
.writelines()
表单提交与登录
http 请求方法
get
post
shell
awk
内置函数
字符串函数
sub
用于在记录中查找能够匹配正则表达式的最长且最靠左的子串,然后用替换串取代找到的子串
sub函数只对目标串中出现的第一个匹配字符串进行替换
gsub
gsub函数对字符串中的正则表达式进行全局替换,即替换所在记录$0 中出现的正则表达式
index
返回子串在字符串中第一次出现的位置
返回low 在 hollow 中第一次出现的位置,偏移量从1开始计算
length
返回字符串中字符的个数
length("hello") 返回字符串hello 的字符个数,是5个
substr
返回字符串指定位置开始的一个子串
substr("shang hai",6,3) 返回 hai,打印位置从6开始,长度为3的子串
match
返回正则表达式在字符串中出现的位置,如果未出现,返回0
match("hello WORLD",/[A-Z]+$/) 返回尾部大写字母,开始的位置,7
split
分隔函数,使用第三个参数指定字段分隔符,把字符串拆成一个数组
split("10/08/2019",date,"/") 以/作为字段分隔符,拆分 10/08/2019 这个字符串到date这个变量中,date 是数组形式
sprintf
返回一个指定格式表达式
sprintf("%-15s %6.2f",$1,$3) 设置第一个字段左对齐,占15个字符,第三个字段右对齐,占六个字符,保留两位小数
toupper
仅适用于gawk,将所有的小写字母均转换成大写字母,返回字符串
awk 'BEGIN{ print toupper("LUInx"), tolower("HWWllo")}' 返回 LUINX hwwllo
tolower
仅适用于gawk,将所有的大写字母转换成小写字母,返回字符串
算术函数
int
int(x),x的整数部分,当x>0,向下取整
rand
函数生成一个大于或等于0,小于1的伪随机浮点数
每次生成的随机数一致
srand() 每次生成的随机数不一致
自定函数
函数中的任何变量,只要不是从参数列表中传来的,就被视为全局变量
如果变量在参数列表中,那么就是局部变量,通常放在参数列表的末端。
当调用函数时,如果没有指定某个形参的值,该参数就会被初始化为空
子主题
gawk 的时间函数
systime
awk 'BEGIN{now=systime();print now}' 返回时间当前时间的时间戳
strftime
awk 'BEGIN{now=strftime("%D");print now}'
08/10/19
awk 'BEGIN{now=strftime("%T");print now}'
19:43:20
sed
grep
bash shell
ps 显示正在运行的进程
环境
一个进程的环境包括 :变量、打开的文件、当前的工作目录、函数、资源限额、信号等
/etc/profile 是一个系统级的初始化文件
定义了可以从一个进程继承到下一个进程的特性,以及对当前工作环境的配置
source
对一个文件执行source命令会使这个文件中的所有设置成为当前shell 的一部分,也就是不会创建子shell
初始化文件是否执行source ,取决于shell 是一个登录shell ,一个交互式shell (但不是登录shell)还是一个非交互shell (一个shell 脚本)
登录时 ,如果在用户的主目录下存在 .bash_prdfile 就source .bash_profile,没有化去找.bash_login,也没有找.profile
内置的bash 命令
通常用来初始化经过修改的配置文件
提示符
bash shell 提供4种提示符
PS1
保存主提示符
登录并等待用户输入
在 /etc/bashrc,.bash_profile 或 .profile 中定义
用专用转义序列设置提示符
PS1="[\u@\h \W]\\$"
\u 登录用户名,\h主机名,\W 当前工作目录的基名
PS2
次提示符
初值 是向右的尖括号(>)
它的值显示在标准错误输出(默认为屏幕)上,如果没有输入完整的命令或期望更多的输入,就会出现这个提示符
[root@java-test etc]# echo "hello
> world"
hello
world
> world"
hello
world
PS3
PS4
搜索路径
变量PATH 被bash 用于定位用户在命令行键入的命令,路径是一个用冒号分隔的目录列表,shell 用这个路径来查找命令
如果在路径列出的所有目录中都未找到目标命令,shell 就会向标准错误输出发送这样一条消息: filename :not found
如果是 bash shell ,通常是在.bash_profile 文件中设置; 如果是sh ,则是在.profile中设置
hash命令
控制系统内部的一个哈希表,shell 用这个表来提高命令查找的效率
dot 命令
就是一个句点,来自 bourne shell 是source 的另一个名字
开机启动
init 系统启动后打开的第一个进程
init 派生一个getty 的进程,负责打开终端端口,提供标准输入的来源
/etc/profile
etc 是给所有用户可以使用的变量
/root/.bash_profile or .bash_login or .profile
/root/.bashrc
家目录是给当前用户使用的
/etc/bashrc 系统级别的函数和别名可以在/etc/bashrc 文件中设置 ,主提示符也常在这里设置
/root/.profile
profile 文件是一个用户定义的初始化文件,它在用户的主目录下,只有当运行 sh(bourne shell )登录时才对它执行source命令
.logout 是一个用户定义文件,它包含那些在注销前执行的命令,这些命令将完成清除临时文件,记录注销时间等任务
/root/.bash_logout 用户注销(退出登录shell )时,如果此文件存在,就执行source命令。该文件包含一些命令,这些命令将完成清除临时文件、清空历史文件、记录管理信息等任务。
禁止执行启动文件的选项
如果带 --noprofile 选项运行bash,那么将不会对启动文件 /etc/profile ,/root/.bash_profile , /root/.bash_login,/root/.profile 执行source 命令
如果用-p选项调用bash , 那么bash 将不会读取用户的 /root/.profile 文件
用内置的set 和shopt 命令设置bash选项
set -o
当是使用开关 -o 时 ,set 命令可以设置选项
列出所有当前设置的和复位的选项
shopt
在新版本的bash 中,shopt 内置命令是set 命令的一种替代 ,shopt 在许多方面和set 内置命令一样,但它为配置shell 增加了更多的选项。
shopt -p
列出所有可设置的shell 选项和他们的当前值,设置(-s 打开) 或复位(-u 关闭)
命令行
shell 就是命令解释器,以交互方式运行时,shell 从终端读取命令,把命令拆分为若干个词
命令可以是一个unix/linux 可执行程序,比如 ls 或date ;也是是shell的一条内置命令,比如 cd 或pwd ; 或是shell 脚本
处理命令的顺序
命令行的第一个词就是将要执行的命令
默认先执行内置命令,在搜索可执行命令
命令可能是
别名
关键字
比如 ,if 、function、while、until
函数
内置命令
内置命令和函数是在shell 中定义的,因此在当前shell 的环境中运行它们将快得多
内置命令和help 命令
内置命令是shell 内部源代码的一部分
help pw
可执行文件和脚本
像ls 和date 这样的脚本和可执行程序是存储在磁盘上的,shell 运行它们必须现在path 中找到它们
查看命令类型 type pwd
改变命令行处理的顺序
shell 提供了3个内置命令 可以忽视命令行处理的顺序
command、 builtin、enable
command 只 处理搜索路径中的内置命令和可执行程序
builtin 只查找内置命令
enable 可以打开和关闭内置命令,默认是打开的
enable -n test 关闭test内置命令,优先执行用户脚本名为test 的脚本
enable 列出所有的内置命令
退出状态
命令或程序终止后,会向父进程返回一个退出状态,退出状态是一个0-255之间的整数
退出状态是0 ,表示命令执行成功;退出状态非0 ,表示命令因某种原因而执行失败
shell 没有找到命令,退出状态是 127
如果是命令执行中被终止,那么是退出状态128 加上终止命令的信号编号,比较control+c 信号是2 ,那么被终止的进程返回状态是128+2 = 130
含有多条命令的命令行
一个命令行可以包含多条命令,命令之间用分号隔开,命令以换行符终止。退出状态是一列命令中的最后一条命令
ls;pwd;date
[root@java-test testalisa]# ls ;pwd;date
awk.sc test0803.txt testfile.txt
/home/testalisa
2019年 08月 11日 星期日 15:57:39 CST
awk.sc test0803.txt testfile.txt
/home/testalisa
2019年 08月 11日 星期日 15:57:39 CST
命令编组
(ls ;pwd;date)> testfile 将三个命令输出内容重定向到testfile 文件中
命令到条件执行
&&
&& 左边命令执行成功,也就是左边命令退出状态是0 ,才执行&& 右边的命令
||
|| 左边命令执行失败,退出状态不为0 ,执行 || 右边的命令
在后台执行的命令
执行命令时 ,命令通常在前台运行 。要等命令执行完之后,提示符才会重新出现。
命令末尾加上&, 命令就会在后台运行,shell 会立即返回提示符
作业控制
一个正在运行的程序称为进程或作业
命令行快捷方式
命令和文件名补全
历史
bash shell 提供命令行历史机制
历史机制将在命令行键入的命令保存在一个带编号的清单,并在退出时添加到历史文件中
内置命令,history 读取的是/root/.bash_history文件中的内容
fc -l 查出来的命令带有行号
默认打印历史清单中最后16行
fc -l 15 20 打印历史清单中第15 到20行数据
fc -ln 显示历史记录不显示记录号
从历史文件访问命令
命令行编辑
670 13.5.4
vi 快捷键
k
向 上移动一行
j
向下移动一行
h
向前移动一个字符
l
向后移动一个字符
u
撤销修改
cc
修改文本
gg
切换到最顶端
yy
移出当前行到内存
pp
将内容贴到当前行下方
别名
alias mroe=more
创建别名mroe,将more的功能赋给mroe
unalias mroe
删掉mroe这个别名
操作目录栈
目录栈是一系列的目录
pushd 将目录压入栈
popd 将目录弹出
元字符
元字符是一种可以用来代表自身以外的内容的特殊字符,也称为通配符
文件名替换(globbing)
将元字符展开为文件名的过程又被称作文件名替换或globbing
如果没有文件名能够跟所有的元字符匹配,shell 就会把这个元字符作为一个字面字符
通配符
*
匹配零个或任意多个字符
?
匹配单个字符
当文件名中包含一个或多个问好时,shell 把问号替换为在文件名中匹配到的字符
方括号
括号用于匹配包含指定字符组或字符范围内某个字符的文件名
花括号
用来匹配一组用逗号分隔的字符串中的任一个
转义元字符
反斜杠用于屏蔽某一单个字符的特殊含义,被转义的字符将只代表其本身
代字符号和连字符扩展
代字符号指代的是用户的主目录的完全路径名
~ 叫代字符号
控制通配符(globbing)
扩展的文件名 globbing
shopt -s extglob
extglob 选项被打开
打开之后正则表达式操作符可以被识别
glob 通配符的意思
ext 提取的意思
此命令执行后就是允许bash识别扩展的模式匹配字符
变量
变量分为 局部变量和环境变量
局部变量:只在创建它们的shell中可用
局部变量和作用域
变量的作用域是指变量在一个程序中的哪些地方可见
变量赋空值时,可以在等号后跟一个换行符
local 函数创建的局部变量,只能在函数内使用
$$
当前变量的pid
declare name=alisa
declare创建的变量 ,可以通过declare 修改变量的值,但是不能 unset name,会提示报错
环境变量:在创建它们的shell 及其派生出来的任意子进程中使用
通常被称为全局变量 ,环境变量应该大写,环境变量是已经用export 内置命令导出的变量
HOME、LOGNAME、PATH、SHELL 在用户登录之前已经被 /bin/login 程序设置好了
环境变量定义并保存在用户主目录下的.bash_profile文件中
设置环境变量的方式
export 变量=值
变量=值;export 变量
declare -x 变量=值
-x 是将变量输出到子shell 中
命名:
包含字母,数字或下划线,但只能以字母或下划线开头
age=123
let age=123+12 可以用于计算,了解就可以了
name=`cat filename` 将命令结果赋值给name
name=$(cat filename) 与上同理
字符串需要用"" 或''
内置命令
declare/typeset
列出所有已设置的变量
复位变量
只要不被设为只读,局部变量和环境变量都可以用unset 命令复位
unset 从shell存储器中删除变量
显示变量值
echo
将它的参数显示到标准输出上
echo -e 允许使用大量控制输出外观的转义序列
转义序列
\n
换行
\r
回车
\t
tab
printf
printf "%s's avg was %.2f%%.\n" "alisa" $(( (8+9+10)/3 ))
alisa's avg was 9.00%.
printf "|%-20s|%-15s|%10d|\n" "alisa" "hello" 90
|alisa |hello | 90|
变量扩展修饰符
用一些专用修饰符来测试和修改变量
name=alisa echo ${name:-judy}
alisa
name有被赋值且不为空
name=alisa echo ${newname:-judy}
judy
newname没有定义
name= echo ${name-JOE}
空
没有冒号不检查name是否有被设置过为空,name即使是空也是被设置过的
name= echo ${name:-JOE}
JOE
冒号使得修饰符检查变量是否未设置或为空
name= echo ${name:=peter}
peter
:=将检查变量 name 是否尚未被设置,如果已经设置过,就不改变name的值 ,未设置或值为空,就将peter 赋给name ,并且是持久的
echo name
peter
echo ${foo:+alisa} :+ 检查变量是否有被设置且不为空,如果有被设置,那么输出alisa 不改变foo原本的值,echo $foo ,还是输出foo原本的值
echo ${namex:?"namex hahah"}
:? 检查namex 是否被设置,尚未设置输出问号后面的 内容
vaw=dshajdahsk echo ${vaw:2:5}
输出 hajda,从第二位开始,输出长度为5的字符串
子串的变量扩展
模式匹配变量用来在串首或 串尾截掉串的某一特定部分
alisanem="alisa/home/bin/new/bin" echo ${alisanem%%/bin*} 尾部%%最大匹配,返回 alisa/home
alisanem="alisa/home/bin/new/bin" echo ${alisanem%/bin*} 尾部%最小匹配,返回 alisa/home/bin/new
echo ${alisanem#alisa*} 返回 /home/bin/new/bin #首部最小匹配
echo ${alisanem##*/} 返回bin ,## 首部最大匹配
位置参量
$* 所有的参数
$1
第一个位置参量的值
$# 有几个参数就返回数字几
$0 指当前shell 的脚本名称
${10} 超过10 的参数的表示形式
其他特殊变量
$$ 当前shell 的pid $! 最后一个进入后台作业的pid $? 上一条命令的退出值
引用
反斜杠
转义单个字符,使其免受解释
单引号里面的所有字符都被当成字面字符,单引号保护所有的元字符不被解释
双引号里面的反斜杠有转义作用
单引号
引号必须匹配成对,保护元字符不被解释,要打印单引号,就必须用双引号把它括起来,或者用反斜杠转义它
双引号
双引号允许对它所括的内容进行变量替换和命令替换
命令替换
命令替换的用处是将命令的输出结果赋给一个变量,或将命令的输出结果代入字符串。
basename 删除路径名中最后一个元素以外的所有元素
算术扩展
通过对一个算术表达式求值并替换结果来执行算术扩展
echo $[(3+4)*5]
35
$[表达式]
$((表达式))
数组
declare -a nums=(22 233 44 11 45)
声明nums 数组
echo ${nums[2]}
显示nums中下标索引为2的数据
echo ${nums[*]}
显示nums中所有的数据
unset nums[0]
删除nums 中第一个元素
echo ${#nums[*]}
显示nums中元素个数
lisa=(me [2]=you [4]=op)
定义数组,没有第二个和第四个元素
echo ${lisa[*]} 返回 me you op
函数
bash 函数用于在当前shell 环境 中通过函数名来执行一组命令,函数一经定义,就成了shell内存映像的一部分
调用函数时,shell 不必像使用脚本文件那样读取磁盘
函数常常被用来提高脚本的模块化程度,传递给函数的任何参数被当作函数内的位置参量
一个函数的位置参量对函数来说是局部的
declare -f 列出 在该shell 中定义的所有函数以及它们的定义
declare -F 列出函数名
export -f greet 声明greet函数为全局函数,即子shell 也可以获得或使用该函数
unset -f greet 删除greet这个函数
set go goto comeon 设置三个位置参量
标准 i/o 和重定向
重定向
< 重定向输入
tr '[a-z]' '[A-Z]' < testfile.txt
从 testfile.txt 读取文件内容,将小写内容转化成大写内容
tr 用于转换或删除文件中的字符
> 重定向输出
2>filename 重定向标准错误输出
2 和 1 这种是文件描述符
2>>filename 重定向和追加标准错误输出
&>filename 重定向标准输出和标准错误输出
2>&1 将标准错误输出重定向到输出的去处
1>&2 将输出重定向到标准错误输出的去处
意思是将标准输出合并到标准错误输出
0 stdin 1 stdout 3 stderr 4 new define file
exec 命令
exec 命令能够在不启动新进程到前提下,将当前正在运行的程序替换为一个新的程序
exec > caa
标准输出指向 caa 文件
标准输出指向 caa 文件
终端输入 ls ,pwd,echo hello
exec > /dev/tty 关闭输出指向caa,输出重新指向终端屏幕
管道
管道将管道符左侧这条命令的输出发送到管道符右侧那条命令的输入
here 文档和重定向输入
here 文档是一种特殊格式的引用
here 文档为需要输入数据的程序(如cat 、sort 或mail),接收内置文本,直至收到用户自定义的终止符。
管道和信号一样,也是进程通信对方式之一,“|”是linux的通信工具
shell 调用选项
当shell 用bash 命令来启动时 ,它可以带上选项来更改它的行为。
选项分为单字符选项和多字符选项
set 可以打开和关闭命令选项
shopt 也可以打开或关闭命令选项
shell 内置命令
shell 中有许多内置到它到源码中的命令
因为命令是内置的,shell 无需到磁盘上定位它们,这样执行速度将快的多
shell
-o
-x
-i
什么是 shell
linux命令解释器,用于解释用户对操作系统的操作
bash,基于 bsh 重写其他shell 好用的功能,a 是again 的意思
linux 启动过程
bios 引导
输入输出功能,是在主板上面,引导一下步骤的硬盘
mbr 硬盘
linux
grub ,启动和引导内核的主要工具,选择哪个内核及指定版本
kernel
systemd 初始化,1号进程
shell
内建命令和外建命令
内建命令
内建命令不需要创建子进程
内建命令对当前对shell 生效
外建命令
进程及相关信息存放在/proc 目录中
执行方式
bash test.sh
bash 和./test.sh 一样,对当前执行环境不造成影响,因为运行时会产生一个子进程
./test.sh
需要test.sh有可执行权限
source ./test.sh
source 和. 是一样的
. ./test.sh
和source 一样,对当前运行环境造成影响,因为运行时不会产生子进程
知识结构和线路图
http
bs架构
client、browser
发送请求
mime请求修饰符
server
响应
状态
协议版本
mime消息类型
正文
URL
http:// https:// 方案
ftp 上传文件,http 浏览
www 域
codeclassroom.com 主机
:8080 端口
默认8080 不用写出来,如果不是8080 则需要写出来
/abc/xyz 路径
index.html logo.png 资源
?id=3&cat=drink 查询字符串
# xxx 片段
地址栏编码
空格 %20
! %21
# %23
>>> import urllib.parse
>>> s='我和你 you&me'
>>> s1=urllib.parse.quote_plus(s)
>>> s1
'%E6%88%91%E5%92%8C%E4%BD%A0+you%26me'
>>> urllib.parse.unquote(s1)
'我和你+you&me'
>>> d ={'id':1,'eat':'面包'}
>>> urllib.parse.urlencode(d)
'eat=%E9%9D%A2%E5%8C%85&id=1'
>>> s='我和你 you&me'
>>> s1=urllib.parse.quote_plus(s)
>>> s1
'%E6%88%91%E5%92%8C%E4%BD%A0+you%26me'
>>> urllib.parse.unquote(s1)
'我和你+you&me'
>>> d ={'id':1,'eat':'面包'}
>>> urllib.parse.urlencode(d)
'eat=%E9%9D%A2%E5%8C%85&id=1'
编码
字符串
urllib.parse.quote_plus(s)
plus 会把空格编码成+号
urllib.parse.quote(s)
字典表
urllib.parse.urlencode(d)
解码
字符串
urllib.parse.unquote_plus(s1)
urllib.parse.unquote(s1)
概念
hyper text transfer protocol
无连接
请求之后就断开
无关媒体类型
请资源的类型,请求什么样的都行
无状态
cookie 、session
无状态是请求过的东西自己不记得,没有标识请求过,没有请求过,可以通过cookie 和session 来记录你到底有没有请求过
消息
Internet mail
MIME 多消息类型
多用途互联网邮件扩展类型
application/json
text/html
消息首行
client
GET /hello.html HTTP/1.1
server
HTTP1.1 200 OK
头部信息
一般:请求和响应通用
请求头
响应头
主体
取决于资源类型
参数
http 版本
1.0
1.1
URI
日期和时间
字符集
内容编码
头部
请求头
Accept-Encoding:gzip, deflate, sdch
响应头
Content-Encoding:gzip
媒体类型
请求头
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
响应头
Content-Type:text/html; charset=utf-8
语言
请求头
Accept-Language:zh-CN,zh;q=0.8
响应
状态码
1xx 请求已经接受正在处理中
100 继续
101 切换协议
2xx 成功被接受且被理解被接受
200 ok
201 请求结束,新资源被创建
202 被接受处理,但未完成
203 头部信息来自于本地或者是第三方,并不是来自原始的服务器
204 服务器返回一半,有状态码有头部信息,但是么有正文主体
3xx 重定向
300 请求的资源还要转跳
301 永久重定向
302 临时重定向
4xx 客户端错误
400 错误的请求未被理解
401 未授权
403 被禁止
404 请求未找到
405 方法不被允许
例如 get 的你用post了
407 代理认证
5xx 服务器错误
500 服务器错误
501 未实现
502 错误的网关
503 服务器不可用,临时过载或者宕机
504 超时
请求
方法
get
用户获取信息
post
发送数据到服务器
head
用户只获取头部信息,不获取响应的报文信息
put
替换url里面指定的资源
delete
删除资源
connect
确立链接
子主题
爬虫就是用python代码来模拟浏览器操作的过程
BeautifulSoup4
解析HTML、XML、提取内容
安装
bs4
pip install beautifulsoup
解析器
标准库 html.parser
内置、稍慢、宽容度高 (宽容度高的意思是html代码写的不规范也能解析)
lxml
速度快,宽容度高
先安装最新版pip 然后pip install lxml
如果pip更新不了,那就先去 pip download 官网下载下来手动安装,更新好之后,在安装lxml
构造解析
构造
tml_soup = BeautifulSoup('<html><body><h1>hello world</h1></body></body>','lxml')
test_soup = BeautifulSoup(open('index.html',encoding="utf-8"),'lxml')
soup = BeautifulSoup(html,'lxml')
上面的lxml 都可以换成 html.parser
对象分类
标签:bs4.element.Tag
type(soup.h1)
<class 'bs4.element.Tag'>
<class 'bs4.element.Tag'>
soup.h1
<h1>优品课堂 python 爬虫</h1>
<h1>优品课堂 python 爬虫</h1>
名称 :name
type(soup.h1.name)
<class 'str'>
<class 'str'>
soup.h1.name
'h1'
'h1'
name 是在html里面用了什么标签来定义的
属性 :
tag['属性名']
tag.attrs
link.attrs
{'href': 'www.baidu.com', 'id': 'link1', 'class': ['enrol1']}
{'href': 'www.baidu.com', 'id': 'link1', 'class': ['enrol1']}
type(soup.a.attrs)
<class 'dict'>
<class 'dict'>
link.attrs['id']
'link1'
'link1'
class这个属性返回的是一个列表
te_soup = BeautifulSoup('<p class="msd1 msd">lorem</p>','lxml')
>>> te_soup.p['class']
['msd1', 'msd']
>>> te_soup.p['class']
['msd1', 'msd']
可导航字符串 :NavigableString
子主题
soup.prettify()
使获取到的html显示的更规范些
导航 DOM
获取body里面的内容,都可以用来遍历取出
soup.body.contents 直接显示获取到的文本
直接获取body里面的内容,读到内存
soup.body.children 显示下一级的节点内容
也是获取body里面的内容,以迭代器的形式存在
soup.html.descendants 显示后代的节点内容
不仅找到了下一级,所有的后代内容也都会单独打印出来
兄弟节点
前面的兄弟节点
next_sibling
next_element
一个标签会认为是一个元素
后面的兄弟节点
previous_sibling
搜索树
soup.find_all()
'标签'
name参数,要查找的标签名
soup.find_all('a')
关键字
soup.find_all(id='link1')
soup.find_all(class_="message")
class_ 是找 class 属性,不然会和python 的类定义冲突
soup.find_all(href="www.baidu.com")
[<a class="enrol1" href="www.baidu.com" id="link1">百度链接</a>] 结果是前面的
soup.find_all('a',href="www.baidu.com")
这个和上面得到的结果是一样的
string 文本
result = soup.find_all('p',string=re.compile(r'sit'))
属性
soup.find_all(attrs={'class':'enrol1',"id":"link1"})
class 和id 是and 的意思
限制数量 limit=值
soup.find_all('a',limit=1)
找出一条a标签
获取文本
links[0].string
bs对象
<class 'bs4.element.NavigableString'>
links[0].get_text()
python字符串
<class 'str'>
与bs对象区别是,不能往下查找了,bs4对象还可以继续往下查找
soup.a.findAll()
和上面的一样,就是不同时期的版本显示的问题
soup.find()
soup.select()
这个是css选择器
soup.select('a#link1')
soup.select('p.fa-copyright')
多线程
概念
进程
一个程序的执行实例
线程
多线程共享数据比较方便,多进程不方便
GIL
global 解释器锁
全局解释器锁
python 解释器在运行过的时候限制了在一个时间只有一个全局的解释器在运行,也就是解释器层级只有一个线程在运行,基于c的标准python是这样的,主循环只有一个控制线程在执行
如果运行时允许多个线程同时运行,那么数据,资源,通讯等共享会比较麻烦,所以限制使用一个线程
全局解释器锁,防止共享同步状态
程序本身是二进制文件,装好的程序或者是写好的代码本身是躺在你电脑的硬盘里面,cpu不会对它进行计算,它是不占内存的,只有程序执行的时候才会加载到内存,被操作系统调用。
代码分块
计算密集型
python语言来实现,比较消耗资源
IO密集型
文件读写,系统会释放 全局解释器锁
_thread
只有一个同步原语(锁)
功能少于threading模块
没有控制进程结束机制
.start_new_thread(function,args=()) 启动线程
threading
.Thread
.start() 启动线程
.join() 主线程等待
构造
例子
def main(): print ('主函数执行开始于:{}'.format(time.ctime())+'\n') threads = [] t1 = threading.Thread(target=func,args=(4,)) threads.append(t1) t2 = threading.Thread(target=func,args=(2,)) threads.append(t2) for t in threads: t.start() for t in threads: t.join() print('主函数执行结束于:{}'.format(time.ctime()))
.Thread(target=func,args=())
start
同步原语
锁
threading.Lock()
.acquire() 获取
.release() 释放
MongDB
NoSQL 非关系型数据库
比较
SQL
NoSQL
MongoDB
介绍
2007 10 gen
特性
文档数据模型
基于 JSON/BSON
BSON是二进制json
表 table 对应集合 collection
时间空间上唯一的一个识别码
ObjectId("59211e7f73c18a6680a43604")
这个id 是根据本地硬件标识和当前时间结合成的
构成
核心服务
JavaScript Shell
基于javascript 的一个命令行工具
数据库驱动
命令行工具
Shell 管理
启动 mongo
管理
创建或切换数据库
use 数据库名称
创建或使用集合
db.集合
文档操作
插入
db.集合.insert({})
找全部
db.student.find()
找一条
db.student.find({"name":"Peter"})
db.student.find({"name":"Peter"})
db.student.find({"age":{"$lt":22}})
年龄小于20 的
pymongo
链接mongodb
三种方式都可以构造链接
数据库名
db = client.databasename
db = client['databasename']
表名
collection = db.collection
collection = db['collection']
插入数据
res = collection.insert_one(b3)
res.acknowledged
操作结果
res.inserted_id
查看操作id
插入多条
manyres = collection.insert_many(data2)
data2 = [{"title":"flask22k","price":23},{"title":"h22tml","price":24}]
链接服务器
>>> import pymongo>>> client = pymongo.MongoClient()>>> client = pymongo.MongoClient('127.0.0.1',27017)>>> client = pymongo.MongoClient('mongodb://localhost:27017')
client = pymongo.MongoClient()
client = pymongo.MongoClient('mongodb://localhost:27017')
client = pymongo.MongoClient('127.0.0.1',27017)
查看一共有几条数据
collection.find().count()
collection.count()
查找数据
>>> for book in collection.find():... print (book)
>>> for bo in collection.find().sort('price',pymongo.DESCENDING):... print (bo)
>>> for bo in collection.find().sort('price',pymongo.DESCENDING).limit(2):... print (bo)
更新
collection.update_one({'title':'flaskk'},{'$set':{"title":"django"}})
修改title是flaskk 的数据 。把title修改成django
更新多条
collection.update_many({"price":23},{"$set":{"price":32}})
验证码
人为输入
机器识别
使用打码API
通过cookie绕过验证码
网站验证码是在服务器那头生成四个字符,然后写入到图片上,同时把字符存到会话状态session里面
测试理论基础
测试用例
测试方法
单元测试
mock 代码不是桩代码
框架
代码覆盖率
jacoco 原理
紧密耦合的代码难以隔离
代码覆盖率越往后越难覆盖
桩代码起到了隔离和补齐的作用
输入数据
调用子函数获得的数据
子主题
子主题
docker
命令
重启docker
systemctl start docker
查看docker 磁盘使用情况
docker system df
docker 停止某个容器
docker stop conid
docker 删除某个容器
docker rm conid
docker 清理磁盘
docker system prune
docker 重启 某个容器
docker start conid
过滤conid 容器ID和ip 关联关系
docker inspect --format='{{.Name}} - {{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $(docker ps -aq)
磁盘查看
df -h 查看磁盘占用情况
du -h --max-depth=1 查看文件大小
监听
ps -ef | grep java
查看出来java 的pid 是643
netstat -anp | grep 643
查出来pid 为643 的id 的监听情况
概念级
容器
什么是容器?
一种虚拟化方案
轻量级虚拟化服务
直接运行于操作系统之上的内核空间
也被称为操作系统级别虚拟化
只能运行相同或相似内核的操作系统
依赖于linux 内核特性:namespace 和cgroups(control group)
资源占用较少
依托于linux 内核的虚拟化技术
虚拟机/?
通过中间层,将一台或多台独立的机器虚拟运行于物理硬件之上
资源占用较多
目标/特点
提供简单轻量的建模方式
性能高
充分利用系统资源
同一宿主机中运行了更多的程序
去除了管理程序的开销
职责的逻辑分离
开发人员关心运行程序
运维人员关心如何管理容器
快速高效的开发生命力周期
鼓励使用面向服务的架构
什么是docker ?
将应用程序自动部署到容器的开源引擎
使用go语言编写
使用场景
创建隔离的运行环境
搭建测试环境
使用docker 容器开发、测试、部署服务
提供软件即服务(saas)应用程序
高性能、超大规模的宿主机部署
构建多用户的平台即服务(paas) 基础设施
C/s架构
基本组成
客户端 /docker client
docker client 执行各种命令,客户端将命令发送给守护进程,守护进程将执行结果返回给客户端
客户端访问守护进程,然后操作docker 容器,容器通过镜像来创建,镜像保存在仓库中
守护进程 / docker daemon
配置和操作
查看docker守护进程
ps -ef | grep docker
sudo status docker 这个我用着不好用
使用service 命令管理
service docker start
service docker stop
service docker restart
启动项
docker -d 【options】
[options] -D debug、-e、-g、-l log-level 、-p pidfile
服务器链接相关
-G group -H host -tls
remote api
存储、 设置驱动的选项
registry 相关
网络设置选项
网桥等、dns,服务器
网桥等、dns,服务器
存储、 设置驱动的选项
centos7 docker 守护进程配置文件在哪??
https://blog.csdn.net/farYang/article/details/75949611
镜像 /image
容器的基石,容器基于镜像启动和运行
层叠的只读文件系统
最底端引导文件系统 bootfs
一般引导文件系统用完就删掉了
在引导文件系统之上,第二层 root 文件系统(只读状态),可以是一种或多种的操作系统
rootfs(ubuntn)
联合加载文件系统
一次加载多个文件系统,外部看来还是一个文件系统
构建和打包阶段
用于启动容器的源文件
基本操作
保存对容器的修改,并再次使用
自定义镜像的能力
以软件的形式打包并分发服务及其运行环境
方式
docker commit 通过容器构建
-a 指定镜像作者
-m 指定镜像信息
-p 正常情况下构建容器时会暂停正在执行的容器,加上p 就不会暂停正在执行的容器
docker commit -a "alisa" -m "push by alisa" alisa user/alisa 构建一个镜像
docker run -d --name alisa0908 user/alisa nginx -g "daemon off;"
使用 user/alisa 这个镜像创建一个容器
docker build 通过Dockerfile文件构建
创建一个镜像Dockerfile
docker build -t "tag name" /dockerfile目录 和dockerfile 同一个目录下执行前面这个命令
docker images
docker images 过滤掉中间层镜像
docker images -a 显示中间层 镜像
没有id 和标签的镜像都是中间层镜像
docker images --no-trunc 显示完整的镜像id
docker images -q 只显示镜像id
容器 /container
通过镜像启动
顶层加载读写文件系统-可写层
读写层加上镜像层,加上配置数据,就构成了容器
启动和执行阶段
写时复制
仓库 / registry
保护用户构建的镜像
公有
私有
docker hub
已有的镜像
repository 仓库
一系列镜像的集合
包含一系列关联的镜像,一个个独立的镜像
registry 包含很多个repository
docker 依赖的linux 内核特性
namespaces 命名空间(封装)
编程语言
封装 ----代码隔离
操作系统
系统资源的隔离
进程、网络、文件系统。。。
种类
pid (process id) 进程隔离
net (network ) 管理网络接口
ipc(interprocess communication)管理跨进程通信的访问
mnt(mount)管理挂载点
uts (unix timesharing system)隔离内核和版本标识
control groups(cgroups)控制组 (管理隔离起来的资源)
用来分配资源
来源于google
linux kernel 2.6.24@2007
提供的功能
资源限制
优先级设定
资源计量
资源控制
可以将进程组挂起 和恢复
docker 容器的能力
文件系统隔离 : 每个容器都有自己的root文件系统
进程隔离: 每个容器都运行在自己的进程环境中
网络隔离:容器间的虚拟网络接口和ip地址都是分开的
资源隔离和分组: 使用cgroups 将cpu 和内存之类的资源独立分配给每个docker 容器
容器的基本操作
启动交互式容器
docker run -i -t image /bin/bash
-i 告诉守护进程为容器始终打开标准输入
-t 告诉docker 要为容器分配一个伪tty 终端
docker ps
-a 显示所有容器
-l 显示最新容器
docker inspect 容器id
返回容器配置信息
docker rm conid
删除已经停止的容器
docker stop conid
停止容器
docker start conid
启动容器
docker run --name=alisa -it 64b67e42f7e9 /bin/bash
启动的容器退出后是exit状态,需要执行start 才是启动状态
守护式容器
什么是守护式容器
能够长期运行
没有交互式会话
适合运行应用程序和服务
命令
ctrl + P 、ctrl+Q 将一个交互式容器转到后台
docker run -d 启动一个守护式容器
返回的一段字母是docker 守护进程分配给容器的唯一id
docker logs 查看容器日志
不指定参数返回所有日志
-f 持续跟踪
-t 显示时间戳
docker top 查看运行中容器的进程
docker exec 如何为运行中的容器启动一个新进程
docker stop/kill 如何停止一个运行中的容器
使用docker 帮助文件
man docker -run
man docker -logs
man docker -top
man docker -exec
docker attach conid 进入守护式容器
在容器中部署静态网站
设置容器的端口映射
大写的p 为容器暴露的所有端口做映射 -p, --publish-all = ture | false 默认为false
小写的p指定映射容器的哪些端口
只指定容器的端口,宿主机的端口是随机映射的
docker run -p 80 -it conid /bin/bash
同时指定宿主机端口和容器端口,这样的端口是一一对应的
docker run -p 8080:80 -it conid /bin/bash
指定ip 的端口
docker run -p 0.0.0.0:80 -it conid /bin/bash
指定ip ,宿主机端口,容器端口 都进行指定
docker run -p 0.0.0.0:8080:80 -it conid /bin.bash
如何在容器中部署nginx 的服务
创建映射80端口的交互式容器
安装nginx
安装文本编辑器vim
创建静态页面
修改nginx配置文件
运行nginx
验证网站访问
docker 的cs 模式
docker 客户端执行各种docker 命令,这些命令会传递给运行在docker的宿主机上运行的守护进程,守护进程负责实现docker 的各种功能(守护进程启动后一直在后台运行)
docker 使用者通过docker 客户端与docker 守护进程进行通信,这个命令行接口是在shell 中运行的程序,是docker 最主要的客户端接口
remote api
restful api
stdin、stdout、stderr
cs 模式链接方式,通过socket 进行链接
unix:///var/run/docker.sock
默认
tcp://host:port
fd://socketfd
docker 启动选项
子主题
dockerfile指令
指令格式
注释
#注释
指令
大写指令名 参数
指令
FORM
已经存在的镜像
基础镜像
必须是第一条非注释指令
FROM ubuntu:14.04
MAINTAINER
指定镜像的作者信息,包含镜像的所有者和联系信息
MAINTAINER author "author email"
RUN
shell 模式
exec 模式
EXPOSE
配置端口号
设置镜像目录和文件
ADD
参数两个,来源地址 和 目标地址
add 包含类似tar 的解压功能
如果单纯复制文件,docker 推荐使用copy
COPY
VOLUME
卷
容器运行时运行的命令
CMD
提供容器运行的默认命令,执行docker run 的时候后面加的命令会默认覆盖dockerfile 中cmd 后面的命令
exec 模式
CMD ["executable","param1","param2"]
shell 模式
CMD command param1 param2
ENTERYPOINT
docker run 后面如果加上指令一样会运行 dockerfile 中配置的ENTERYPOINT命令
镜像构建及容器运行时的环境设置
WORKDIR
使用绝对路径, /path/to/workdir
ENV
USER
ONBUILD
构建触发器
当一个镜像被其他镜像作为基础镜像时执行,会在构建过程中插入指令
当前构建的镜像image1 不会执行onbuild 的指令, 用image1 为基础镜像构建image2 容器时会执行 onbuild
构建过程
from头 从基础镜像运行一个容器
执行一条指令,对容器作出修改
执行类似docker commit 的操作,提交一个新的镜像层
再基于刚提交的镜像运行一个容器
执行dockerfile 中的下一条执行,循环以上指令,直至所有指令执行完毕
构建缓存
docker build 默认使用缓存
不使用缓存
docker build --no-cache
dockerfile 中可以使用 refresh命令刷新缓存,命令如右 REFRESH_DATE 2019-09-10
docker 容器的网络链接
容器的网络基础
网桥
网桥是OSI 七层模型中的数据链路层的一种设备
osi - 物理层,数据链路层,网络层,传输层,会话层,表示层,应用层
linux的虚拟网桥 docker0
可以设置ip地址,设置ip 属于网络层的内容, 但是网桥是通用网络设备中的一种,只要是网络设备就可以设置ip地址
相当于拥有一个隐藏的虚拟网卡
ifconfig docker0 192.168.0.0 netmask 255.255.255.0
brctl show 查看当前网桥设备
容器的互联
默认所有容器互联
进入到某一个容器查看ifconfig 中的ip ,然后进入另一个容器ping 前面容器的ip
docker run -it --name alisa09 --link=alisa0908:alisa cc91d4b3391c 启动容器关联alisa0908 ,进入容器直接ping alisa 查看建立的链接,这样启动会更新 /etc/hosts 文件内容,同时修改env 环境变量
拒绝容器互联
--icc=false
修改docker 启动进程选项
修改 /etc/default/docker 文件最后一行,添加DOCKER_OPIS= ["--icc=false"]
允许特定容器间的连接
--iptables=true
docker的启动配置文件添加 iptables
数据卷 Data Volume
docker 的生命周期与程序中运行的程序相一致
数据卷是经过特殊设计的目录,可以绕过联合文件系统(UFS),为一个或多个容器提供访问
数据卷设计的目的,在于数据的永久化,它完全独立与容器的生存周期,因此,Docker 不会在容器删除时删除其挂在的数据卷,页不会存在类似的垃圾收集机制,对容器引用的数据卷进行处理
特点
数据卷在容器启动时初始化,如果容器使用的镜像在挂载点包含了数据,这些数据会拷贝到新初始化的数据卷中
数据卷可以在容器之间共享和重用
可以对数据卷里的内容直接进行修改
数据卷的变化不会影响镜像的更新
卷会一直存在,即使挂载数据卷的容器已经被删除
消息中间件
具有低耦合、可靠投递、广播、流量控制、最终一致性等功能,成为异步rpc 的主要手段之一
流行的中间件
kafka
快速持久化, 通过磁盘顺序读写与零拷贝机制,可在0系统开销下进行消息持久化
高吞吐 ,普通服务器上既可达到10w/s的吞吐速率
高堆积,支持topic 下消费者较长时间离线,消息堆积量大
完全的分布式系统 ,broker ,producer,consumer 都原生自动支持分布式,依赖 zookeeper 自动实现负载均衡
支持hadoop 数据并行加载
rabbitmq
socketmq
redis
key-value 的nosql 数据库,本身支持mq功能,完全可以当作一个轻量级的队列服务来使用
当入队数据大于10k 时 ,性能较差,小于10k 性能优于 rabbitmq ,处队时 性能 较rabbitmq 好很多
中间件的组成
broker
消息服务器,作为server提供消息核心服务
producer
消息的生产者,业务的发起方,负责生产消息传输给broker
topic
主题,发布订阅模式下的消息统一汇集地,不同生产者向topic 发送消息,由mq服务器分发到不同到订阅者,实现消息的广播
consumer
消息消费者,业务的处理方,负责broker获取消息并进行业务逻辑处理
queue
队列,ptp模式下,特定生产者向特定queue 发送消息,消费者订阅特定的queue 完成指定消息的接收
message
消息体,根据不同通信协议定义的固定格式进行编码的数据包,来封装业务数据,实现消息的传输
发布订阅
queue形式
一个消息只能被一个消费者消费,消息可以保留到有一个可用的消费者
point to point
topic形式
一个消息可以被多个消费者消费
pub /sub
中间件的优势
系统解耦
交互系统之间没有直接调用关系,只通过消息传输,故系统侵入性不强
提高系统响应时间
需要立即处理的业务放在方法中调用,不需要立即处理的放在消息队列
为大数据处理架构提供服务
java 消息服务 -jms
应用场景
异步通信
消息可以不立即处理,可在需要处理的时候在处理
解耦
降低工程间的强依赖关系
冗余
消息被删除之前,可确认消息是否真的被处理
扩展性
分布式扩容
过载保护
顶住突发的访问压力,不会因为突发的超负荷的请求而完全崩溃
可恢复性
一个处理消息的进程挂掉,加入队列中的消息仍然可以在系统恢复后被处理
顺序保证
消息队列大部分都是顺序的
缓冲
缓冲层
数据流处理
收集数据
0 条评论
下一页