接上篇,在上篇中,我们已经在服务器上搭建好了 Python3 环境以及对应的 virtualenv 虚拟环境了。接下来,我们开始把代码部署到我们的服务器环境并运行。
在部署我们的代码到服务器前,我们来看看我们的代码需要哪些环境
首先,我们的代码是 Python3 开发的,因此,它首先依赖于 Python3 环境。
其次,我们的代码还用到了一此第三方的框架或库,比如 scrapy、pymysql...
当然,最重要的就是我们的代码了,他是我们的项目的核心逻辑和业务。
在上一篇中,我们完成了第一部分的 Python3 的环境的搭建。此文我们将完成第三方库安装以及代码部署这两部分的工作。
一、提交代码
以 gitee.com 作为我们代码托管平台进行示例。
注:
创建项目的步骤正常情况下不应该在项目开发完成以后再进行,但由于此步骤我在前面的文章中忘了介绍,因此在此处补上。事实上,之前开发的项目我已经提交过了,此处再另新建一个项目用作示例。
1 注册一个 gitee.com 账号
此步骤略
2 创建一个项目
此步骤简要描述如下,点击右上角的 "+" 选择 "新建项目",填写项目名称,是否开源可随意选择,此处选择私有。下面的选择语言,添加 .gitignore,使用 Readme 文件初始化项目 等全部不选... 创建一个空白项目(由于我的项目中之前已经创建过了,如果是新项目,则可以选择 python 的 .gitignore 模板与 Readme 模板)
新建一个空白项目
3 安装 git 工具
我的开发环境是 Windows。因此,下载一个 Windows 版本的 git 并安装,下载地址如下所示:
https://git-scm.com/download/win
安装过程略。
4 设置 SSH 公钥
点击头像 -> "设置" -> "SSH公钥" -> 点击右侧 "怎样生成公钥" 可查看生成方式
设置 SSH 公钥
按照公钥生成方式生成公钥并添加到 gitee.com 的 SSH 公钥页面。公钥可以简单理解为密令,比如我们生成的公钥类似于 "天王盖地虎,宝塔镇河妖",然后我们把这个密令给 gitee.com,然后当我们需要与 gitee.com 进行资源操作时,两边一对口令,发现对上了。这事儿就简单了,也不用咱再用户密码验证一遍了。
5 代码提交
为了效果更直观,因此,直接在 PyCharm 中进行代码提交演示。
(1) 初始化项目
初始化 git
(2) 添加 readme.md 与 .gitignore
创建 .gitignore 与 README.md
在项目根目录下创建名为 readme.md 与 .gitignore 的文件,文件内容大致如下:
README.md
# proxy_ip
#### 项目介绍
proxy_ip 是一个从网络上爬取免费 IP 的项目。
#### 项目环境与依赖
python 版本
- python 3.6.1
#### 第三方库
- pywin32==223(windows environment)
- scrapy==1.5.0
- pymysql==0.8.1
- fake-useragent==0.1.10
#### 运行方法
1.运行环境
- 确保具备 ptyhon 3.x 的环境,安装依赖的第三方库
2.数据库配置
- 更改 settings.py 中的 MySQL 数据库连接信息
- 创建 proxy_ip 表,建表脚本位于 scripts/database.sql
3.运行程序
- 进入项目的根目录 proxy_ip,执行 nohup python main.py &
.gitignore
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
# Translations
*.mo
*.pot
# Django stuff:
*.log
.static_storage/
.media/
local_settings.py
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# pyenv
.python-version
# celery beat schedule file
celerybeat-schedule
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
# idea
/.idea/
(3) 添加远程仓库映射
PyCharm -> VCS -> Git -> Remotes -> 点击 "+" -> 将项目首页上代码仓库的 SSH 地址填入 URL 处 -> 点击 OK -> 等待 Checking URL -> 如果前面 SSH 公钥配置正确,此处就完事儿了
项目的代码仓库地址
image.png
(4) 第一次提交
"VCS" -> "Commit..." -> 在 "Commit Message" 下方的文本框中输入提交的备注信息 -> 选择 "Commit and push"
提交
二、拉取代码
1 配置服务器公钥
按照上方的配置方法与步骤将服务器的公钥配置到 gitee.com 平台
2 拉取代码
确定一个目录用于存放项目代码,如 /data 目录,
[root@192 data]# cd /data
[root@192 data]# git clone [email protected]:jzl975/test-proxy-ip.git
Cloning into 'test-proxy-ip'...
The authenticity of host 'gitee.com (116.211.167.14)' can't be established.
RSA key fingerprint is e3:ee:82:78:fb:c0:ca:24:65:69:ba:bc:47:24:6f:d4.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'gitee.com,116.211.167.14' (RSA) to the list of known hosts.
Cloning into 'test-proxy-ip'...
remote: Counting objects: 36, done.
remote: Compressing objects: 100% (34/34), done.
remote: Total 36 (delta 11), reused 0 (delta 0)
Receiving objects: 100% (36/36), 9.27 KiB, done.
Resolving deltas: 100% (11/11), done.
三、安装第三方库
1 创建虚拟环境
[root@192 data]# mkvirtualenv proxy-ip
Using base prefix '/usr/local'
New python executable in /root/.virtualenvs/proxy-ip/bin/python3.6
Also creating executable in /root/.virtualenvs/proxy-ip/bin/python
Installing setuptools, pip, wheel...done.
virtualenvwrapper.user_scripts creating /root/.virtualenvs/proxy-ip/bin/predeactivate
virtualenvwrapper.user_scripts creating /root/.virtualenvs/proxy-ip/bin/postdeactivate
virtualenvwrapper.user_scripts creating /root/.virtualenvs/proxy-ip/bin/preactivate
virtualenvwrapper.user_scripts creating /root/.virtualenvs/proxy-ip/bin/postactivate
virtualenvwrapper.user_scripts creating /root/.virtualenvs/proxy-ip/bin/get_env_details
(proxy-ip) [root@192 data]#
2 安装第三方库
根据我们 README.md 中记录的使用到的第三方库进行安装,如下示例: (省略安装过程)
(proxy-ip) [root@192 data]# pip install scrapy -i https://pypi.douban.com/simple
...
Could not find a version that satisfies the requirement Twisted>=13.1.0 (from scrapy) (from versions: )
No matching distribution found for Twisted>=13.1.0 (from scrapy)
其中,安装 scrapy 报错,报错信息如下,提示找不到匹配的 Twisted,于是手动安装:
(proxy-ip) [root@192 Twisted-17.9.0]# pip install pymysql
(proxy-ip) [root@192 Twisted-17.9.0]# pip install fake-useragent
(proxy-ip) [root@192 ~]# wget https://twistedmatrix.com/Releases/Twisted/17.9/Twisted-17.9.0.tar.bz2
--2018-05-31 11:24:55-- https://twistedmatrix.com/Releases/Twisted/17.9/Twisted-17.9.0.tar.bz2
Resolving twistedmatrix.com... 66.35.39.66
Connecting to twistedmatrix.com|66.35.39.66|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 3019243 (2.9M) [application/x-tar]
Saving to: “Twisted-17.9.0.tar.bz2”
100%[==============================================================>] 3,019,243 217K/s in 15s
2018-05-31 11:25:13 (193 KB/s) - “Twisted-17.9.0.tar.bz2” saved [3019243/3019243]
(proxy-ip) [root@192 ~]# tar -jxf Twisted-17.9.0.tar.bz2
(proxy-ip) [root@192 ~]# cd Twisted-17.9.0
(proxy-ip) [root@192 Twisted-17.9.0]# python setup.py install
再次安装 scrapy
(proxy-ip) [root@192 ~]# pip install scrapy -i https://pypi.douban.com/simple
四、运行
注:
运行前,请确保本机有需要的 mysql 数据库服务以及请确保创建了数据库表(数据库建表语句在代码中的 scripts/database.sql 中),如果想要将数据保存到其他数据库中,请修改 settings.py 中的 MySQL 相关配置。
1 运行方式一
(proxy-ip) [root@192 ~]# cd /data/test-proxy-ip/
(proxy-ip) [root@192 test-proxy-ip]# scrapy list
proxy_ip
(proxy-ip) [root@192 test-proxy-ip]# scrapy crawl proxy_ip
...
insert into proxy_ip(
country, ip, port, server_location,
is_anonymous, protocol_type, speed, connect_time,
survival_time, validate_time, source, create_time
)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
('CN', '120.33.247.127', '25998', '福建莆田', '高匿', 'HTTP', '1.759秒', '1.759秒', '4天', '2018-05-31 17:44:00', 'www.xicidaili.com', '2018-05-31 11:44:39')
(1062, "Duplicate entry '120.33.247.127-25998' for key 'ip'")
第一步,进入我们的项目根目录。
第二步,可以执行 scrapy list 命令查看我们的所有的爬虫,这儿的 "proxy_ip" 就是我们在 spiders 下面的 xicidaili.py 中定义的 name 的值。
第三步,执行 scrapy crawl proxy_ip 运行爬虫。
注:
这种方式只是在前台运行,即当我们的会话结束,程序运行也就结束了。如果我们要想程序在后台运行,可以使用 nohup scrapy crawl proxy_ip & 这样的方式来执行
2 运行方式二
我们的爬虫是每次爬取西刺代理前 5 页的内容,如果我们想隔一段重复爬取一次呢。下面我们可以使用 crontab 的定时任务的方法实现,编辑 crontab -e ,在末尾添加如下命令并保存退出。
(proxy-ip) [root@192 ~]# crontab -e
00 * * * * workon proxy-ip && cd /data/test-proxy-ip/ && nohup scrapy crawl proxy_ip & >> ~/proxy_ip.log
以上命令表示每个小时的整点会执行我们的爬虫程序
3 运行方式三
此方法是我们写一个 python 脚本,在 python 脚本中来调用系统命令 scrapy crawl proxy_ip,然后使用 python 的休眠来控制程序运行。
此 Python 脚本在我们可以创建在项目的根目录下,脚本名称随意,如 main.py 表示这是我们项目的入口文件,脚本内容如下:
# -*- coding:utf-8 -*-
__author__ = 'jiangzhuolin'
import sys
import os
import time
while True:
os.system("scrapy crawl proxy_ip") # scrapy spider 的启动方法 scrapy crawl spider_name
print("程序开始休眠...")
time.sleep(3600) # 休眠一小时后继续爬取
然后我们使用如下方式运行我们的这个 python 脚本在后台即可:
[root@192 ~]# workon proxy-ip
(proxy-ip) [root@192 ~]# cd /data/test-proxy-ip/
(proxy-ip) [root@192 test-proxy-ip]# ls
main.py proxy_ip README.md scrapy.cfg
(proxy-ip) [root@192 test-proxy-ip]# nohup python main.py &
[1] 36449
(proxy-ip) [root@192 test-proxy-ip]# nohup: ignoring input and appending output to `nohup.out'
五、总结
该系统使用一个简单的示例从环境搭建到代码编写到部署运行的完整过程分享了一个 Python Scrapy 爬虫的大致生产流程。以后有机会再分享更多 Python Scrapy 爬虫的知识,包括 Scrapy 分布式爬虫,Scrapyd 监控等等...
六、附录
以下是一个部署脚本,可以实现每次更新代码到仓库之后,执行该脚本自动重启项目运行。
#! /bin/bash
# 使用环境变量生效
source /etc/profile
PROJECT_DIR="/data"
PROJECT_NAME="test-proxy-ip"
PYTHON_ENV="proxy_ip"
EXECUTE_FILE="main.py"
cd ${PROJECT_DIR}
# 拉取项目
if [ ! -d ${PROJECT_NAME} ]
then
git clone [email protected]:jzl975/${PROJECT_NAME}.git
fi
# 进入项目目录
cd $PROJECT_NAME
# 拉取最新代码
git pull
# 切换到虚拟环境
workon ${PYTHON_ENV}
# 停止进程
PID=`ps -ef | grep ${EXECUTE_FILE} | grep -v grep | awk '{print $2}'`
if [ $PID ]
then
`kill -9 ${PID}`
fi
# 运行入口程序
nohup python ${EXECUTE_FILE} &