0%

简介

上一篇文章介绍了docker安装,并演示了HelloWorld。今天主要介绍一下镜像管理相关知识,分为三大部分:镜像、容器、仓库,首先看一下关系图:

1

仓库(Repository)

仓库是存放镜像的地方,每个仓库集中存放某一类镜像,比如存放Ubuntu镜像的仓库叫做Ubuntu仓库,可能包括14.04、16.04、latest等版本,通过tag区分。这些仓库可以存放在公开服务器Registry上面,可以搭建私有服务器。官方的服务器为Docker Hub, 网址为:https://hub.docker.com。 如果网络访问不方便,可以采用国内镜像网站。
自己可以注册账号,上传自定义镜像到服务器,共享给他人下载。

镜像(Image)

Docker镜像类似于虚拟机镜像, 可以理解成包含了文件系统的只读模板。可以从压缩文件导入或从仓库下载,我们可以在本地已有镜像的基础上自定义镜像。
以下载Ubuntu镜像为例:

1
docker pull ubuntu

2

通过docker images命令查询已经下载的镜像,我们发现之前的Hello-world和ubuntu都查询成功了。
默认如果不指定tag,下载的就是最新的latest, 相当于docker pull ubuntu:latest, 如果下载指定版本,比如14.04,命令为docker pull ubuntu:14.04
3

再次查询一下,发现有两个ubuntu镜像,但是TAG不一样,并且他们的IMAGE ID也不一样,是两个不同的镜像。
如果我们不需要ubuntu:14.04镜像了,可以通过docker rmi f216cfb59484命令进行删除:
4

删除后,查询一下,发现ubuntu:14.04镜像不见了,说明删除成功。
现在运行一下镜像ubuntu:latest,命令为:

1
docker run -ti ubuntu /bin/bash

5

运行成功后,自动创建了一个容器并运行,可以输入简单的Linux命令,比如ls。可以添加一个新文件,然后创建一个新的镜像。
6

首先创建一个文件:然后退出:

1
2
touch test.txt
exit

记录容器ID为4040e711b2a3之后,执行命令

1
docker commit -m "Add test.txt" -a "beyondspider" 4040e711b2a3 ubuntu:test

在ubuntu:latest镜像基础上创建了一个新的镜像ubuntu:test。
可以把刚才创建的镜像导出到本地压缩文件,或者上传到Docker Hub,这里就不做演示了。

容器(Container)

Docker容器类似于一个轻量级的沙箱,可以看作简易版的Linux系统环境,容器是从镜像创建的实例,会在镜像的最上层创建一个可写层,镜像是只读的,不会改变。
一个镜像可以创建多个容器,不同容器是相互隔离互不可见的。可以对容器进行启动、停止、删除等操作。
刚才的命令

1
docker run -ti ubuntu /bin/bash

其实包括两个动作,首先执行了命令创建容器:

1
docker create -ti ubuntu /bin/bash

然后执行了命令运行容器:

1
docker start

首先docker ps -a查询一下刚才创建的容器。
7

继续运行一下:

1
docker start -i 4040e711b2a3

8

我们发现和刚才的效果一样的,并且test.txt文件还在,说明容器是可写的。继续创建并运行一个新的容器:
9

我们发现新的容器8f4c252c6b0c没有test.txt文件,说明不同的容器直接是隔离的。
如果我们不需要8f4c252c6b0c容器了,可以通过docker rm 8f4c252c6b0c命令进行删除:
10

删除后,查询一下,发现8f4c252c6b0c容器不见了,说明删除成功。

小结

通常我们可以从Docker Hub下载一个镜像,然后根据镜像创建容器并运行,在容器中自定义功能后,创建新的镜像,然后上传新的镜像到服务器。下次继续分享制作镜像的详情内容,欢迎交流。

客户需求

酒店后台管理系统记录了合作酒店信息,一共300多页,每页10条数据,主要包括合作酒店的地区、价格、风险指数等信息,现在需要把这些信息整理成EXCEL,如果手工复制工作量大,而且容易出错,所以客户提出用爬虫采集数据并导出到EXCEL。

爬虫模拟

登陆

http://checkhrs.zzzdex.com/piston/login

login

列表页面

http://checkhrs.zzzdex.com/piston/hotel?page=1
list

详情页面

http://checkhrs.zzzdex.com/piston/hotel/xxxx/edit
detail

详细设计

流程

首先通过用户名密码登陆,然后打开第一页,接着打开每条记录的详情页,然后采集数据。接下来遍历第二页直到最后一页。

Scrapy

采用Python的Scrapy框架

1
pip install scrapy

核心源码

登陆成功后,自动处理cookie,这样就可以正常访问页面了。返回的数据格式为html,通过xpath进行解析。为了避免对服务器产生压力,在夜间爬取数据,并且在settings.py里面并且设置延时5S。

1
DOWNLOAD_DELAY = 5

hotel.py源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
import scrapy
from scrapy.selector import Selector
from scrapy.http import FormRequest

class HotelSpider(scrapy.Spider):
name = 'hotel'
allowed_domains = ['checkhrs.zzzdex.com']

login_url = 'http://checkhrs.zzzdex.com/piston/login'

url = 'http://checkhrs.zzzdex.com/piston/hotel'

start_urls = ['http://checkhrs.zzzdex.com/piston/hotel']

def login(self, response):
fd = {'username':'usernamexxx', 'password':'passwordxxx'}
yield FormRequest.from_response(response,
formdata = fd,
callback = self.parse_login)

def parse_login(self, response):
if 'usernamexxx' in response.text:
print("login success!")
yield from self.start_hotel_list()
else:
print("login fail!")

def start_requests(self):
yield scrapy.Request(self.login_url,
meta = {

},
encoding = 'utf8',
headers = {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36'
},
dont_filter = True,
callback = self.login)

def start_hotel_list(self):
yield scrapy.Request(self.url,
meta = {

},
encoding = 'utf8',
headers = {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36'
},
dont_filter = True)

def parse(self, response):
print("parse")
selector = Selector(response)

select_list = selector.xpath('//table//tbody//tr')

for sel in select_list:
address = sel.xpath('.//td[3]/text()').extract_first()

next_url = sel.xpath('.//td//a[text()="编辑"]/@href').extract_first()

next_url = response.urljoin(next_url)

print(next_url)

yield scrapy.Request(next_url,
meta = {
'address': address
},
encoding = 'utf8',
headers = {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36'
},
dont_filter = True,
callback = self.parseDetail)

totalStr = selector.xpath('//ul[@class="pagination"]//li[last()-1]//text()').extract_first();
print(totalStr)

pageStr = selector.xpath('//ul[@class="pagination"]//li[@class="active"]//text()').extract_first();
print(pageStr)

total = int(totalStr)
print(total)

page = int(pageStr)
print(page)

if page >= total:
print("last page")
else:
next_page = self.url + "?page=" + str(page + 1)
print("continue next page: " + next_page)
yield scrapy.Request(next_page,
meta = {
},
encoding = 'utf8',
headers = {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36'
},
dont_filter = True)

def parseDetail(self, response):
address = response.meta['address']
print("parseDetail address is " + address)

addresses = address.split('/')
print(addresses)

country = ""
province = ""
city = ""

address_len = len(addresses)

if address_len > 0:
country = addresses[0].strip()

if address_len > 1:
province = addresses[1].strip()

if address_len > 2:
city = addresses[2].strip()

selector = Selector(response)

hotelId = selector.xpath('//input[@id="id"]/@value').extract_first()

group_list = selector.xpath('//form//div[@class="form-group js_group"]')

hotelName = group_list[1].xpath('.//input[@id="hotel_name"]/@value').extract_first()

select_list = selector.xpath('//form//div[contains(@class,"company_container")]')
for sel in select_list:
company_list = sel.xpath('.//div[@class="panel-body"]//div[@class="form-group"]')

#公司
companyName = company_list[0].xpath('.//input[@id="company"]/@value').extract_first()

#单早
singlePrice = company_list[1].xpath('.//input/@value')[0].extract()

#双早
doublePrice = company_list[1].xpath('.//input/@value')[1].extract()

#风险指数
risk = company_list[2].xpath('.//input/@value').extract_first()

#备注
remark = company_list[3].xpath('.//input/@value').extract_first()

yield {
'ID': hotelId,
'国家': country,
'省份': province,
'城市': city,
'酒店名': hotelName,
'公司': companyName,
'单早': singlePrice,
'双早': doublePrice,
'风险指数': risk,
'备注': remark
}

运行

1
scrapy crawl hotel -o ./outputs/hotel.csv

从晚上10点开始爬,大概第二天中午数据全部采集完成,没有错误,最终输出成CSV,按照ID排序后转成EXCEL即可。
excel

小结

在日常工作中利用爬虫技术,可以提高工作效率,避免手重复劳动。

安装虚拟机

首先在windows机器上安装VirtualBox虚拟机,然后在虚拟机中安装CentOS操作系统,最后在CentOS中安装Docker。CentOS开启ssh服务后,通过mac远程连接CentOS,后续操作全部在mac机器上进行(非mac机器连接方式类似),本文结尾将演示Docker的HelloWorld例子。

安装VirtualBox

常见虚拟机软件包括VirtualBox和vmware,建议使用免费开源的VirtualBox,下载地址:https://www.virtualbox.org, 没有特别要求,下载最新版本即可,安装过程请参考网上教程。

安装CentOS

采用Linux系统学习Docker,建议使用CentOS操作系统
下载地址:https://www.centos.org/download/, 选择Everything ISO,从镜像链接中下载CentOS-7-x86_64-Everything-1708.iso。
由于网络受限,无法通过桥接的方式访问外网,所以网络链接方式选择“网络地址转换(NAT)”,虚拟机和windows主机共享一个IP地址。有条件的情况下,选择“桥接网卡”方式后续会更加方便一些。
8260ea86228f21cd9d058a9ef0b57432.jpg

修改hostname

执行命令:

hostnamectl set-hostname beyondspider
其中beyondspider为新的机器名称,根据实际情况修改。一旦修改了hostname,/etc/hostname将被自动更新。但是/etc/hosts不会更新,所以需要手动更新/etc/hosts,最终改完效果如下:
b2b9fe104617b54b5daa27a9c8a684ea.jpg

配置ssh

CentOS安装完之后默认已经启动了ssh服务, 可以通过如下步骤检查ssh服务是否启动。

查看端口22是否开放:
netstat -tnl
c099cfebad5e6c4b55784c7159f86414.jpg

查看ssh服务是否启动:

systemctl status sshd.service
d76c78aa5d20a2438cb3e5aa4b980faf.jpg

设置虚拟机网卡端口转发

由于NAT网络,外部无法访问虚拟机,所以设置端口转发来使用ssh服务
e9c2d0e0f53ddb798d1ca0e2981e204f.jpg

密码访问

ssh root@xx.xx.xx.xx
注意:需要根据提示输入密码。

证书访问

首先通过ssh-keygen命令生成公钥和私钥,然后用ssh-copy-id命令,自动保存公钥在对方主机的/root/.ssh/authorized_keys 文件中去
ssh-copy-id -i ~/.ssh/id_rsa.pub root@xx.xx.xx.xx
注意:需要根据提示输入密码, 下次就可以免密访问了。

ssh登录成功画面如下:
d7edb00bc85d5bdcaf1050d419fa835c.jpg

配置阿里云yum镜像

mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
yum clean all
rm -rf /var/cache/yum
yum makecache

安装Docker并启动

yum -y install docker
service docker start
检查docker版本
docker –version
a4314795ef391638e025e5bb55cc4123.jpg

修改docker加速镜像

访问阿里docker网页,登录后台获取专属加速地址, https://dev.aliyun.com

df39dbaf09550852962adad79495b200.jpg

修改后/etc/docker/daemon.json内容如下

2ecfedb19aa767b3b8c77c4a98083386.jpg

修改完记得重启docker

sudo systemctl daemon-reload
sudo systemctl restart docker

修改docker代理(可选)

如果网络不好,需要设置代理
创建文件/etc/systemd/system/docker.service.d/http-proxy.conf,参考如下内容修改:

[Service]
Environment=”HTTP_PROXY=http://proxy.xx.xx.xx:8080"

修改后效果如下:
3da4ceae821a9e259ce10bfa018e626d.jpg

修改完记得重启docker
sudo systemctl daemon-reload
sudo systemctl restart docker

运行hello-world

docker run hello-world

成功

看人如下页面表示成功,
786da34298447f7bb1d94046e8d4b59e.jpg

小结

到此,docker 在 CentOS 系统的安装完成。下回将讲解Docker镜像相关知识,欢迎交流。

超越爬虫beyondspider上线啦!程序员编程技术交流,包括前端、移动APP、Web网站、Restful API, 微服务、爬虫、docker、Jenkins、CI/CD等。

扫码关注公众号:beyondspider

logo

简介

Charles is an HTTP proxy / HTTP monitor / Reverse Proxy that enables a developer to view all of the HTTP and SSL / HTTPS traffic between their machine and the Internet. This includes requests, responses and the HTTP headers (which contain the cookies and caching information).

支持平台

支持Mac、Windows、Linux三大操作系统。
支持http抓包,通过安装证书还可以支持https协议,支持手机抓包,包括Android和iOS。
下载地址:https://www.charlesproxy.com

charles使用

charles

小结

Charles和Fiddler可以同时使用,充分利用各种优势,具体的使用方式可以参考官网文档。

简介

Fiddler是一个http协议调试代理工具,它能够记录并检查所有你的电脑和互联网之间的http通讯,设置断点,查看所有的“进出”Fiddler的数据(指cookie,html,js,css等文件)。Fiddler要比其他的网络调试器要更加简单,因为它不仅仅暴露http通讯,还提供了一个用户友好的格式。

支持平台

支持Mac、Windows、Linux三大操作系统。
支持http抓包,通过安装证书还可以支持https协议,支持手机抓包,包括Android和iOS。
下载地址:www.telerik.com/fiddler

Fiddler使用

fiddler

小结

Fiddler目前是Windows上面非常流行的抓包软件,Mac是最近才支持的,所以功能比较弱,但是正常使用也够用了。如果需要更多的功能,推荐Charles抓包软件,可以免费或付费使用。

抓包

通常学习爬虫,第一步就是要抓包,然后分析网络请求的和结果,知道了数据格式之后就可以程序模拟浏览器的行为,从而实现数据采集的过程。所以抓包是非常重要的一个环节,下面我们利用Chrome浏览器自带功能进行抓包。

Chrome开发者模式

打开谷歌开发者模式, 点击“网络”标签页,可以查看Resquest和Response数据。

chrome-debug

小结

Chrome抓包能满足基本需求,但是功能有限,而且有时候Response数据丢失,所以推荐专业的抓包工具Fiddler和Charles。