爬取某家乐数据并部署到Linux ,实现自动爬取,定期发送邮件

15 篇文章 4 订阅

一、selenium获取网站数据

背景介绍
这篇文章主要包含以下几个内容

  1. 使用selenium进行网站登录签到并获取积分数据
  2. 基于QQ邮箱发送邮件
  3. linux安装google-chromeselenium ,并上传代码到linux(centos 8)
  4. 使用crontab 实现定时执行爬虫

环境说明

  • selenium 4.1.3
  • python3.8.5
  • CentOS 8

默认已安装python解释器,selenium的使用方法和对应的浏览器驱动看我的另一篇文章:selenium知识大全-传送门

  • 查看Chrome版本
    设置 – 关于Chrome 即可查看你的浏览器版本
  • 下载对应的浏览器驱动
    在这里插入图片描述

Chrome驱动下载地址:http://chromedriver.storage.googleapis.com/index.html
火狐驱动下载地址:http://ftp.mozilla.org/pub/firefox/releases/

1. 准备环境

  • 安装selenium
pip install selenium

2. 分析网站

  1. 网站登录是一个input标签,通过ID可以确定对应的输入框来输入用户名和密码
账号id='account' ,密码id='password'

在这里插入图片描述

# 两种定位方式都可以,self.account表示你的账号,self.password表示你的密码
# account = WebDriverWait(driver,10).until(EC.presence_of_element_located((By.ID,"account"))).send_keys(self.account)
account = driver.find_element(By.ID,"account").send_keys(self.account)
# 点击账号
# password = WebDriverWait(driver,10).until(EC.presence_of_element_located((By.ID,"password"))).send_keys(self.password)
password = driver.find_element(By.ID, "password").send_keys(self.password)
# 点击密码
  1. 再定位登录按钮,你会发现按钮的class属性,每次刷新页面,有的值不一样,有的值一样。
    在这里插入图片描述
  2. 我们可以通过标签的文字内容来定位标签,页面只有一个按钮的文字为登录,所以我们可以这样写
WebDriverWait(driver,10).until(EC.presence_of_element_located((By.XPATH,'//button[text()="登录"]'))).click()
  1. 注册的时候会出现要求同意的按钮,但是我们再次登录时不会出现。我们把代码进行整理一下
import datetime
from selenium import webdriver
import time
import random
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait

driver = webdriver.Chrome(self.chromedriver)
driver.get('url')
time.sleep(random.uniform(1,2))		# 防止网页出现渲染意外
account = WebDriverWait(driver,10).until(EC.presence_of_element_located((By.ID,"account"))).send_keys(self.account)
# 点击账号
password = WebDriverWait(driver,10).until(EC.presence_of_element_located((By.ID,"password"))).send_keys(self.password)
# 点击密码
login = WebDriverWait(driver,10).until(EC.presence_of_element_located((By.XPATH,'//button[text()="登录"]'))).click()
# 点击登录 ,开始登录

5.登录成功后,我们直接打开个人中心,通过xpath语法直接定位标签
在这里插入图片描述

3. 网页代码整理

我们的数据已经获取,这是网页的所需的所有代码,做了异常处理

import datetime
from selenium import webdriver
import time
import random
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

class KuJiaLe(object):
    """
    酷家乐签到并获取一些数据
    """
    def __init__(self):
        self.url = 'https://www.kujiale.cn/signin?'
        self.chromedriver = './chromedriver.exe'		# 注意驱动与浏览器版本对应。
        self.account = '666666666'	  # 网站的账号
        self.password = '666666'	  # 网站的密码
        self.isSuccess = None		  # 是否爬取成功
        self.integral = None          # 积分
        self.flag = None              # 0 表示失败,1表示成功
        self.start_time = time.time() # 统计爬取时间
        self.failedCount = 0		  # 统计失败次数
        self.failedList = []		  # 失败信息加入列表中

    def get_result(self):
        try:
            driver = webdriver.Chrome(self.chromedriver)
            driver.get(self.url)
            time.sleep(random.uniform(1,2))
            print('开始爬取某*乐 {}'.format(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S %A')))
            account = WebDriverWait(driver,10).until(EC.presence_of_element_located((By.ID,"account"))).send_keys(self.account)
            # 点击账号
            password = WebDriverWait(driver,10).until(EC.presence_of_element_located((By.ID,"password"))).send_keys(self.password)
            # 点击密码
            login = WebDriverWait(driver,10).until(EC.presence_of_element_located((By.XPATH,'//button[text()="登录"]'))).click()
            # 点击登录 ,开始登录
            time.sleep(random.uniform(1,2))
            driver.get('https://www.kujiale.cn/activities/jifengonglue')
            # 跳转到签到页面
            WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, "//*[@class='single-image']/div[3]"))).click()
            # 点击签到
            time.sleep(random.uniform(1,2))
            driver.get('https://www.kujiale.cn/pcenter')
            # 跳转到个人主页
            integral = WebDriverWait(driver,10).until(EC.presence_of_element_located((By.XPATH,'//*[@id="up-site-dash-board"]/div[1]/div/div[2]/div[1]/a/div/span'))).text
            # 获取用户积分
            self.flag = 1
            self.isSuccess = '签到成功'
            self.integral = integral
            print('爬取成功..............')
        except Exception as e:
            print(e)
            self.flag = 0
            self.isSuccess = '签到失败'
            self.failedList.append("签到失败,时间:" + datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S %A'))
            self.failedCount += 1
            if self.failedCount == 5:
                self.flag = 1
                return self.flag
            print('爬取失败..............')
        return self.flag

    def start(self):
        flag = self.get_result()
        # print(flag)
        if flag == 0:           # 0 表示失败了
            print('爬取失败 {} 次'.format(self.failedCount))
            while True:
                time.sleep(60)		# 过60秒再次尝试登录
                ret = self.get_result()
                if ret == 1:		# 5次后默认跳出
                    break
        data = {
            "now_time": datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S %A'),
            "website": "某*乐 ",
            "isSuccess": self.isSuccess,
            "integral": str(self.integral),
            "useTime":round(time.time() - self.start_time,2),
            "failedInfo":{
                "failedCount": self.failedCount,
                "failedList":self.failedList
            }
        }
        print('数据整理完成...........')
        return data

if __name__ == '__main__':
    kjl = KuJiaLe()
    data = kjl.start()
    print(data)

运行结果如下
在这里插入图片描述

二、QQ邮箱发送邮件

1. 开启QQ邮箱 POP/SMTP

  1. 登录QQ网页邮箱,点击 设置账户
    在这里插入图片描述
    找到POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务 ,开启POP/SMTP 服务,点击生存授权码

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LCOC1z4S-1647704804044)(Z:\Study Note\Typora笔记图库\image-20210813111904056.png)]

2. 使用smtp实现发送QQ邮件

import smtplib
from email.mime.text import MIMEText
from email.header import Header

class QQEmail():
    def __init__(self):
        self.email_host = "smtp.qq.com"                   # 设置的邮件服务器host必须是发送邮箱的服务器,与接收邮箱无关。
        self.sender_email = "123456@qq.com"            # 发送方qq邮箱
        self.receiver_email = "123456@qq.com"          # 接收方qq邮箱
        self.email_authorization = "ag*********ac"     # 开启stmp服务的时候并返回的授权码,是接收方QQ的授权码。

    def send_email(self,email_theme,email_content):
        """
        发送邮件函数
        email_theme: 接收一个字符串,用于设置邮件的主题
        email_content: 接收一个字符串,用于设置邮件的内容
        """
        print('开始发送邮件至: {}'.format(self.sender_email))
        message = MIMEText(email_content, 'plain', 'utf-8') # 邮件内容,三个参数:第一个为文本内容,第二个设置文本格式 plain表示字符内容, ,第三个设置编码 utf-8
        message['Subject'] = email_theme			 # 设置邮件的主题,即邮件标题
        message['From'] = Header("ZanSan", 'utf-8')  # 设置显示在邮件里的发件人名称
        message['To'] = Header("LiSi", 'utf-8')      # 设置显示在邮件里的收件人名称
        try:
            smtpobj = smtplib.SMTP_SSL(self.email_host, 465)  # 本地如果有本地服务器,则用localhost ,默认端口25,腾讯的(端口465或587)
            smtpobj.set_debuglevel(1)   # 设置调试输出级别。 如果 level 的值为 1 或 True ,就会产生连接的调试信息,以及所有发送和接收服务器的信息。 如果 level 的值为 2 ,则这些信息会被加上时间戳。
            smtpobj.login(self.receiver_email, self.email_authorization)                   # 登陆QQ邮箱服务器
            smtpobj.sendmail(self.sender_email, [self.receiver_email], message.as_string())  # 发送邮件。这里要注意一下第三个参数,msg是字符串,表示邮件。我们知道邮件一般由标题,发信人,收件人,邮件内容,
            print("邮件发送成功")
            smtpobj.quit()  # 退出
        except smtplib.SMTPException as e:
            print("邮件发送失败,Error: {}".format(e))

if __name__ == '__main__':
    email_theme = 'QQ邮件发送--我是主题'
    email_content = '我是内容,我是内容,我是内容'
    q = QQEmail()
    q.send_email(email_theme,email_content)

运行效果如下:
在这里插入图片描述
注意:现在QQ在进行发送和接收时,发送方和接收方的QQ必须相同了,不相同会报错
在这里插入图片描述

三、Linux 安装谷歌浏览器及驱动并测试

3.1 使用阿里源

因为现在centos8 不再进行维护了,阿里更换的centos8的repo源地址。

1. 备份

mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup

2. 更换新的阿里源

wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-vault-8.5.2111.repo

3. 删除缓存,重新生成新缓存

yum clean all
yum makecache

在这里插入图片描述
如果出现 Couldn’t resolve host ‘mirrors.cloud.aliyuncs.com’ 信息,不影响使用。用户也可自行修改相关配置: eg:

sed -i -e '/mirrors.cloud.aliyuncs.com/d' -e '/mirrors.aliyuncs.com/d' /etc/yum.repos.d/CentOS-Base.repo

3.2 安装谷歌浏览器

1. yum 安装谷歌浏览器

yum install https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm

注意:
如果出现如下error ,把/etc/yum.repos.d/* 所有的文件移动到其他地方,然后重新执行更换阿里云源【3.1 小节 - 第二小点】
在这里插入图片描述
2. 查看谷歌浏览器版本

google-chrome-stable --version

在这里插入图片描述

3.3 下载谷歌浏览器驱动

谷歌浏览器驱动下载网址:http://chromedriver.storage.googleapis.com/index.html

1. 找到与谷歌浏览器对应的驱动版本,右键复制链接
在这里插入图片描述
2. 下载驱动

wget http://chromedriver.storage.googleapis.com/99.0.4844.51/chromedriver_linux64.zip

3. 解压文件

unzip chromedriver_linux64.zip

# 如果没有unzip命令,直接安装即可
# yum install unzip

在这里插入图片描述

4. 把驱动文件移动到/usr/bin/ 目录下

mv chromedriver /usr/bin/

3.4 创建爬虫专业虚拟环境 (Linux环境)

为了更好的隔离本地环境与虚拟环境,使程序运行更稳定,推荐每个项目之间使用虚拟环境相互隔离。
1. 安装 virutalenvwrapper 虚拟环境工具

# 
pip3 install virtualenvwrapper

2. 配置.bashrc 文件

# 1.打开文件
vim ~/.bashrc

# 2.添加内容
VIRTUALENVWRAPPER_PYTHON=/usr/local/bin/python3.8		# 设置python解释器环境路径
export WORKON_HOME=/home/pythonCode/virtualSet/			# 创建的虚拟环境所在那个目录下
source /usr/local/bin/virtualenvwrapper.sh				# 执行文件

退出vim后,执行 source ~/.bashrc

3. virutalenvwrapper 介绍

操作命令
切换到摸个虚拟环境workon [virutalenv name]
退出虚拟环境deactivate
列出所有虚拟环境lsvirtualenv = workon
删除某个虚拟环境rmvirtualenv [virutalenv name]
指定python解释器mkvirtualenv -p python3.8 test
创建虚拟环境mkvirtualenv env_name

4. 创建selenium虚拟环境

mkvirtualenv seleniumEnv

在创建成功后,该工具会默认进入虚拟环境中
在这里插入图片描述
我们也可以使用 workon 指令来进入不同的环境
在这里插入图片描述
5. 安装selenium

一定是在虚拟环境下安装哦

(seleniumEnv) [root@centos8-106 home]# pip install selenium

3.5 整合代码并复制到Linux

我们需要整合爬虫代码和发送QQ邮件的代码,来实现爬取信息发送邮件的效果。
QQ邮箱的代码不需要改动,只需要改动一下爬虫代码即可
linux下需要设置为无头模式,驱动方式使用Service
1. 整合代码
爬虫代码命名为 kjl.py

# kjl.py
import datetime
from selenium import webdriver
import time
import random

from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import qq_email

class KuJiaLe(object):
    """
    酷家乐签到并获取一些数据
    """
    def __init__(self):
        self.url = 'https://www.kujiale.cn/signin?'
        self.chromedriver = r'/home/pythonCode/codeDemo/chromedriver'	
        self.account = '666666'	 	    # 网站的账号
        self.password = '666666'	    # 网站的密码
        self.isSuccess = None		    # 是否爬取成功
        self.integral = None            # 积分
        self.flag = None                # 0 表示失败,1表示成功
        self.start_time = time.time()   # 统计爬取时间
        self.failedCount = 0		    # 统计失败次数
        self.failedList = []		    # 失败信息加入列表中

    def get_result(self):
        try:
            s = Service(self.chromedriver)
            chrome_options = Options()
            chrome_options.add_argument("--headless")  # => 为Chrome配置无头模式
            chrome_options.add_argument('--no-sandbox')	# 
            chrome_options.add_argument('--disable-gpu')	# 禁用GPU加速
            chrome_options.add_argument('--disable-dev-shm-usage')
            driver = webdriver.Chrome(service=s,options=chrome_options)
            driver.get(self.url)
            time.sleep(random.uniform(1,2))
            print('开始爬取某*乐  {}'.format(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S %A')))
            account = WebDriverWait(driver,10).until(EC.presence_of_element_located((By.ID,"account"))).send_keys(self.account)
            # 点击账号
            password = WebDriverWait(driver,10).until(EC.presence_of_element_located((By.ID,"password"))).send_keys(self.password)
            # 点击密码
            login = WebDriverWait(driver,10).until(EC.presence_of_element_located((By.XPATH,'//button[text()="登录"]'))).click()
            # 点击登录 ,开始登录
            time.sleep(random.uniform(1,2))
            driver.get('https://www.kujiale.cn/activities/jifengonglue')
            # 跳转到签到
            WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, "//*[@class='single-image']/div[3]"))).click()
            # 点击签到
            time.sleep(random.uniform(1,2))
            driver.get('https://www.kujiale.cn/pcenter')
            integral = WebDriverWait(driver,10).until(EC.presence_of_element_located((By.XPATH,'//*[@id="up-site-dash-board"]/div[1]/div/div[2]/div[1]/a/div/span'))).text
            # 获取用户积分
            self.flag = 1
            self.isSuccess = '签到成功'
            self.integral = integral
            print('爬取成功..............')
        except Exception as e:
            print(e)
            self.flag = 0
            self.isSuccess = '签到失败'
            self.failedList.append("签到失败,时间:" + datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S %A'))
            self.failedCount += 1
            if self.failedCount == 5:
                self.flag = 1
                return self.flag
            print('爬取失败..............')
        return self.flag

    def start(self):
        flag = self.get_result()
        # print(flag)
        if flag == 0:           # 0 表示失败了
            print('爬取失败 {} 次'.format(self.failedCount))
            while True:
                time.sleep(60)		# 过60秒再次尝试登录
                ret = self.get_result()
                if ret == 1:		# 5次后默认跳出
                    break
        data = {
            "now_time": datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S %A'),
            "website": "某*乐 ",
            "isSuccess": self.isSuccess,
            "integral": str(self.integral),
            "useTime":round(time.time() - self.start_time,2),
            "failedInfo":{
                "failedCount": self.failedCount,
                "failedList":self.failedList
            }
        }
        print(data)
        print('数据整理完成...........')
        return data

if __name__ == '__main__':
    kjl = KuJiaLe()
    data = kjl.start()
    send_email_content = "时间:{} \n网站:{} \n是否成功: {} \n当前积分:{}\n获取积分用时:{}\n失败次数:{}\n失败详情:{}".format(data['now_time'],data['website'],data['isSuccess'],data['integral'],data['useTime'],data['failedInfo']['failedCount'],data['failedInfo']['failedList'])
    email_theme = data['website'] + data['now_time']
    e = qq_email.QQEmail()
    e.send_email(email_theme,send_email_content)

2. 复制代码到linux
安装远程文件工具

yum install lrzsz

安装好后,将文件上传至服务器中。也可以直接将文件拖拽至 xshell中。Xshell使用教程

rz:表示上传文件  注意:上传只能一个一个,不能多选!!!!
sz: 表示将文件下载到本地  使用: sz + filename

在这里插入图片描述
当前文件结构

(seleniumEnv) [root@centos8-106 crawlCode]# tree
.
├── kjl.py
└── qq_email.py

0 directories, 2 files

3.6 Linux环境整体测试

在填好了邮箱等信息后,在linux环境进行测试

python kjl.py 

运行结果如下
在这里插入图片描述

四、设置定时任务

4.1 编辑shell脚本来执行python 代码

1. 创建shell脚本

vim kjl.sh

2. 输入内容

#!/bin/bash
export PATH=$PATH:/usr/local/bin		# 将/usr/local/bin/的环境导入系统变量中			
source /home/pythonCode/virtualSet/seleniumEnv/bin/activate	# 启动虚拟环境
python /home/pythonCode/crawlCode/kjl.py		# 运行爬虫代码

3. 添加执行权限

chmod +x kjl.sh

4. 编写任务计划 crontab

Linux crontab是用来定期执行程序的命令。
当安装完成操作系统之后,默认便会启动此任务调度命令。

详细学习crontab:https://www.runoob.com/linux/linux-comm-crontab.html

5. 定制爬虫计划
终端输入命令,输入计划任务

crontab -e  # 以当前用户添加任务计划,所以需要注意权限

# 输入内容 表示每隔2分钟执行一次
*/2 * * * * /home/pythonCode/crawlCode/kjl.sh >> /home/pythonCode/crawlCode/kjl.log 2>&1

也可以使用以下的任务计划

# 每天早上8点执行一次
00 08 * * * /home/pythonCode/crawlCode/kjl.sh >> /home/pythonCode/crawlCode/kjl.log 2>&1

6. 查看结果
使用tail -f /var/log/cron命令查看crontab的运行结果,或者看日志也可以

tail -f /var/log/cron
(seleniumEnv) [root@centos8-106 crawlCode]# cat kjl.log 
开始爬取某*2022-03-19 14:08:05 Saturday
爬取成功..............
数据整理完成...........
开始发送邮件至: 920728039@qq.com
邮件发送成功
开始爬取某*2022-03-19 14:10:05 Saturday
爬取成功..............
数据整理完成...........
开始发送邮件至: 920728039@qq.com
邮件发送成功
......

好了,本章完成了,欢迎大家在评论区留言,讨论。
请添加图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值