sentemail.py    发邮件

import os
import smtplib
from email.header import Header
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText


def sentemail(list_email):
    # 设置发件服务器地址
    host = 'mail.shunwang.com'
    # 设置发件服务器端口号。注意,这里有SSL和非SSL两种形式
    port = 25
    # 设置发件邮箱,一定要自己注册的邮箱
    sender = 'opengl@shunwang.com'
    # 设置发件邮箱的密码,163邮箱的授权码,等会登陆会用到
    pwd = 'Kol90120'
    # 设置邮件接收人,可以是扣扣邮箱
    receiver0 = []
    for i in list_email:
        receiver0.append(i)
    # 设置邮件正文,这里是支持HTML的
    body = '<h1> 请扫描二维码 登入 WeGame </h1>'
    # 设置正文为符合邮件格式的HTML内容
    msg = MIMEText(body, 'html')
    message = MIMEMultipart()
    # 设置邮件标题
    message['subject'] = Header('请扫描二维码 登入 WeGame', 'utf-8')
    # 设置发送人
    message['from'] = Header(sender, 'utf-8')
    # 设置接收人
    message['to'] = Header(sender, 'utf-8')
    message.attach(msg)
    # 构造附件1,传送当前目录下的 filename 文件
    path = os.path.dirname(os.path.abspath(__file__))
    filename = '{}/images/erweima.png'.format(path)
    att1 = MIMEImage(open(filename, 'rb').read(), 'utf-8')
    att1["Content-Type"] = 'application/octet-stream'
    # 这里的filename可以任意写,写什么名字,邮件中显示什么名字
    att1["Content-Disposition"] = 'attachment; filename="{}"'.format('ewm.png')  # ewm.png
    message.attach(att1)
    try:
        # 注意!如果是使用SSL端口,这里就要改为SMTP_SSL
        s = smtplib.SMTP(host, port)
        # 登陆邮箱
        s.login(sender, pwd)
        # 发送邮件!
        s.sendmail(sender, receiver0, message.as_string())
        # print('邮件发送成功')
        return 'ok'
    except Exception as e:
        # print('邮件发送失败:{}'.format(e))
        return e


if __name__ == '__main__':
    sentemail(['1064145110@qq.com'])

QQCookies.py

# 添加日志
import logging
import os
import random
import sys
import time

import cv2
import numpy as np
import pymysql
from PIL import Image
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.support.ui import WebDriverWait
from sentemail import sentemail

path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
sys.path.append(path)
from spider_setting import MYSQL_HOST, MYSQL_POST, MYSQL_DATABASE, MYSQL_PASSWORD, MYSQL_USER

logging.basicConfig(
    level=logging.INFO,  # 定义输出到文件的log级别,大于此级别的都被输出
    format='%(asctime)s  %(filename)s  %(levelname)s : %(message)s',  # 定义输出log的格式
    datefmt='%Y-%m-%d %H:%M:%S',  # 时间
    filename="{}/logs/{}qq_account.log".format(path, time.strftime('%Y%m%d')),
    filemode='a')  # 写入模式“w”或“a”
console = logging.StreamHandler()
console.setLevel(logging.INFO)
# 设置格式
formatter = logging.Formatter('%(asctime)s  %(filename)s  %(levelname)s : %(message)s')
# 告诉handler使用这个格式
console.setFormatter(formatter)
# 为root logger添加handler
logging.getLogger('').addHandler(console)


class QQCookie(object):
    def __init__(self):
        self.db = pymysql.connect(host=MYSQL_HOST, port=MYSQL_POST, database=MYSQL_DATABASE, user=MYSQL_USER,
                                  password=MYSQL_PASSWORD,
                                  charset='utf8', autocommit=True)
        self.cursor = self.db.cursor()
        self.cursor.execute('SELECT user_name, password from spider_qq_account WHERE id=2')
        self.data = self.cursor.fetchone()
        os.makedirs('./images/', exist_ok=True)
        logging.info('开始:{}'.format(self.data))
        self.user_name = self.data[0]
        self.password = self.data[1]
        self.chrome_options = webdriver.ChromeOptions()
        # # 使用headless无界面浏览器模式
        self.chrome_options.add_argument('--headless')
        self.chrome_options.add_argument('--no-sandbox')
        self.chrome_options.add_argument("--proxy-server=http://183.131.14.78:8118")
        # 谷歌文档提到需要加上这个属性来规避bug
        self.chrome_options.add_argument('--disable-gpu')
        # 设置默认编码为utf-8
        self.chrome_options.add_argument('lang=zh_CN.UTF-8')
        ## 隐藏滚动条, 应对一些特殊页面
        self.chrome_options.add_argument('--hide-scrollbars')
        # 禁止加载图片
        # chrome_options.add_argument('blink-settings=imagesEnabled=false')
        # 指定浏览器分辨率
        self.chrome_options.add_argument('window-size=1440x900')
        self.driver = webdriver.Chrome(chrome_options=self.chrome_options)
        # try:
        self.get_cookie()
        self.delete_log_file()
        # except:
        #     self.driver.quit()
        #     time.sleep(5)
        #     self.cursor.close()
        #     self.db.close()

    def get_cookie(self):
        self.driver.get('https://www.wegame.com.cn/store/games')
        # driver.maximize_window()
        ac = self.driver.find_element_by_xpath('//*[@id="header_wrapper"]/div/div[3]/div[1]/a/span')
        ActionChains(self.driver).move_to_element(ac).click(ac).perform()
        time.sleep(1)
        iframe = self.driver.find_element_by_xpath(
            '/html/body/div[4]/div/div/div[2]/div[3]/iframe')  # 切换到这个iframe  不切换获取不到xpath坐标
        self.driver.switch_to.frame(iframe)
        time.sleep(2)
        ac = self.driver.find_element_by_xpath('//*[@id="switcher_plogin"]')
        ActionChains(self.driver).move_to_element(ac).click(ac).perform()
        time.sleep(1)
        self.driver.find_element_by_xpath('//input[@id="u"]').clear()
        for i in self.user_name:
            self.driver.find_element_by_xpath('//input[@id="u"]').send_keys(i)
            time.sleep(0.2)
        self.driver.find_element_by_xpath('//input[@id="p"]').clear()
        for i in self.password:
            self.driver.find_element_by_xpath('//input[@id="p"]').send_keys(i)
            time.sleep(0.2)
        ac = self.driver.find_element_by_xpath('//*[@id="login_button"]')
        print(1)
        ActionChains(self.driver).move_to_element(ac).click(ac).perform()
        print(2)
        time.sleep(2)
        print(2.2)
        html = self.driver.page_source
        print(html)
        print('*' * 100)
        time.sleep(2)
        path = os.path.dirname(os.path.abspath(__file__))
        self.driver.save_screenshot('{}/images/page.png'.format(path))  # 数据保存为图片
        if '安全验证' in html and "tcaptcha_iframe" not in html:
            print("安全验证")
            imgelement = self.driver.find_element_by_xpath('//*[@id="qrlogin_img"]')
            locations = imgelement.location  # 获取当前位置坐标  定点
            sizes = imgelement.size  # 获取xpath取到的图片大小
            self.driver.switch_to.default_content()  # 切换到主页
            iframe_l = self.driver.find_element_by_xpath('/html/body/div[4]/div/div/div[2]/div[3]/iframe')
            locations_l = iframe_l.location
            rangle = (locations['x'] + locations_l['x'], locations['y'] + locations_l['y'],
                      locations['x'] + sizes['width'] + locations_l['x'],
                      locations['y'] + sizes['height'] + locations_l[
                          'y'])  # 要切图片的坐标(x, y, x, y) 第一个是 第一点坐标    后面xy 是第二点坐标   两点获取一个面
            # 打开截图切割
            img = Image.open('{}/images/page.png'.format(path))  # 读取要切割的图片
            jpg = img.crop(rangle)
            jpg.save('{}/images/pages.png'.format(path))  # 保存切割下的图片
            jpgzoom = Image.open('{}/images/pages.png'.format(path))
            (x, y) = jpgzoom.size
            x_s = x * 3
            y_s = y * 3
            out = jpgzoom.resize((x_s, y_s), Image.ANTIALIAS)
            out.save('{}/images/erweima.png'.format(path), quality=95)  # 保存放大后的图片
            # driver.quit()
            logging.info('请快速扫码登入')
            response = sentemail(['1064145110@qq.com'])  # 收件人邮箱,可以写多个 放在列表里面
            if response == 'ok':
                logging.info('邮件发送成功')
            else:
                logging.info('邮件发送失败:{}'.format(response))
            time.sleep(60)
            # time.sleep(2)
        elif '安全验证' in html and "tcaptcha_iframe" in html:
            print("有图片")
            self.driver.switch_to.frame(self.driver.find_element_by_id('tcaptcha_iframe'))  # switch 到 滑块frame
            print(4)
            time.sleep(0.5)
            self.driver.page_source
            # iframe = self.driver.find_element_by_xpath('//*[@id="tcaptcha_iframe"]')  # 切换到这个iframe  不切换获取不到xpath坐标
            # self.driver.switch_to.frame(iframe)
            print(4.1)
            time.sleep(0.5)
            bk_block = self.driver.find_element_by_xpath('//*[@id="slideBg"]')  # 大图
            print(5)
            web_image_width = bk_block.size
            print(6)
            web_image_width = web_image_width['width']
            print(7)
            bk_block_x = bk_block.location['x']
            print(8)

            slide_block = self.driver.find_element_by_xpath('//img[@id="slideBlock"]')  # 小滑块
            print(9)
            slide_block_x = slide_block.location['x']
            print(10)

            bk_block = self.driver.find_element_by_xpath('//img[@id="slideBg"]').get_attribute('src')  # 大图 url
            print(11)
            slide_block = self.driver.find_element_by_xpath('//img[@id="slideBlock"]').get_attribute('src')  # 小滑块 图片url
            print(12)
            slid_ing = self.driver.find_element_by_xpath('//div[@id="tcaptcha_drag_thumb"]')  # 滑块
            print(13)

            os.makedirs('./images/', exist_ok=True)
            print("下载图片")
            self.urllib_download(bk_block, './images/bkBlock.png')
            print(14)
            self.urllib_download(slide_block, './images/slideBlock.png')
            print(15)
            time.sleep(0.5)
            img_bkblock = Image.open('./images/bkBlock.png')
            real_width = img_bkblock.size[0]
            print(16)
            width_scale = float(real_width) / float(web_image_width)
            print("判断缺口位置")
            position = self.get_postion('./images/bkBlock.png', './images/slideBlock.png')
            print(17)
            real_position = position[1] / width_scale
            real_position = real_position - (slide_block_x - bk_block_x)
            print(18)
            print("模拟轨迹 假装是人在操作")
            track_list = self.get_track(real_position + 4)

            ActionChains(self.driver).click_and_hold(on_element=slid_ing).perform()  # 点击鼠标左键,按住不放
            print(19)
            time.sleep(0.2)
            # print('第二步,拖动元素')
            for track in track_list:
                ActionChains(self.driver).move_by_offset(xoffset=track, yoffset=0).perform()  # 鼠标移动到距离当前位置(x,y)
                print(20)
                time.sleep(0.002)
            # ActionChains(driver).move_by_offset(xoffset=-random.randint(0, 1), yoffset=0).perform()   # 微调,根据实际情况微调
            time.sleep(1)
            # print('第三步,释放鼠标')
            ActionChains(self.driver).release(on_element=slid_ing).perform()
            print(21)
            time.sleep(1)

            print('登录成功')

        logging.info('-' * 1000)
        # driver.switch_to.default_content()
        time.sleep(2)
        aa_cookie = self.driver.get_cookies()  # 获取cookie
        cookie = {}
        cookies = []  # 拼cookie
        for i in aa_cookie:
            cookie[i["name"]] = i["value"]
            cookies.append('{}={}'.format(i["name"], i["value"]))
        qq_cookie = '; '.join(cookies)
        if 'p_uin' in qq_cookie:
            self.cursor.execute(
                'UPDATE spider_cookies set cookies="{}", update_time="{}" WHERE platform="wegame"'.format(
                    qq_cookie, time.strftime('%Y-%m-%d %X')))
            logging.info(
                'UPDATE spider_cookies set cookies="{}", update_time="{}" WHERE platform="wegame"'.format(
                    qq_cookie, time.strftime('%Y-%m-%d %X')))
        logging.info('cookies:{}'.format(qq_cookie))
        time.sleep(2)

    def show(self, name):
        print("show  name:{}".format(name))
        cv2.imshow('Show', name)
        cv2.waitKey(0)
        cv2.destroyAllWindows()

    def webdriverwait_send_keys(self, dri, element, value):  # 显示等待输入
        print("webdriverwait_send_keys   dri:{}  element:{}   value:{}".format(dri, element, value))
        WebDriverWait(dri, 10, 5).until(lambda dr: element).send_keys(value)

    def webdriverwait_click(self, dri, element):  # 显示等待 click
        print("webdriverwait_click  dri:{}   element:{}".format(dri, element))
        WebDriverWait(dri, 10, 5).until(lambda dr: element).click()

    def get_postion(self, chunk, canves):  # 判断缺口位置  chunk: 缺口图片是原图   位置 x, y
        print("get_postion  chunk:{}   canves:{}".format(chunk, canves))
        otemp = chunk
        oblk = canves
        target = cv2.imread(otemp, 0)
        template = cv2.imread(oblk, 0)
        w, h = target.shape[::-1]
        temp = 'temp.jpg'
        targ = 'targ.jpg'
        cv2.imwrite(temp, template)
        cv2.imwrite(targ, target)
        target = cv2.imread(targ)
        target = cv2.cvtColor(target, cv2.COLOR_BGR2GRAY)
        target = abs(255 - target)
        cv2.imwrite(targ, target)
        target = cv2.imread(targ)
        template = cv2.imread(temp)
        result = cv2.matchTemplate(target, template, cv2.TM_CCOEFF_NORMED)
        x, y = np.unravel_index(result.argmax(), result.shape)
        # # 展示圈出来的区域
        cv2.rectangle(template, (y, x), (y + w, x + h), (7, 249, 151), 2)
        cv2.imwrite("yuantu.jpg", template)
        self.show(template)
        return x, y

    def get_track(self, distance):  # 模拟轨迹 假装是人在操作
        print("get_track  distance:{}".format(distance))
        # 初速度
        v = 0
        # 单位时间为0.2s来统计轨迹,轨迹即0.2内的位移
        t = 0.2
        # 位移/轨迹列表,列表内的一个元素代表0.2s的位移
        tracks = []
        # 当前的位移
        current = 0
        # 到达mid值开始减速
        mid = distance * 7 / 8

        distance += 10  # 先滑过一点,最后再反着滑动回来
        # a = random.randint(1,3)
        while current < distance:
            if current < mid:
                # 加速度越小,单位时间的位移越小,模拟的轨迹就越多越详细
                a = random.randint(2, 4)  # 加速运动
            else:
                a = -random.randint(3, 5)  # 减速运动

            # 初速度
            v0 = v
            # 0.2秒时间内的位移
            s = v0 * t + 0.5 * a * (t ** 2)
            # 当前的位置
            current += s
            # 添加到轨迹列表
            tracks.append(round(s))

            # 速度已经达到v,该速度作为下次的初速度
            v = v0 + a * t

        # 反着滑动到大概准确位置
        for i in range(4):
            tracks.append(-random.randint(2, 3))
        for i in range(4):
            tracks.append(-random.randint(1, 3))
        return tracks

    def urllib_download(self, imgurl, imgsavepath):
        print("urllib_download  imgurl:{}    imgsavepath:{}".format(imgurl, imgsavepath))
        from urllib.request import urlretrieve  # 下载图片  imgurl: 图片url     imgsavepath: 存放地址
        urlretrieve(imgurl, imgsavepath)

    def delete_log_file(self):
        self.driver.quit()
        time.sleep(5)
        self.cursor.close()
        self.db.close()
        path = os.path.dirname(os.path.abspath(__file__))
        delete_file_list = []
        for file_name in os.listdir(path):
            if 'logs' in file_name:
                delete_file_list.append(file_name)
        if len(delete_file_list) > 5:
            for delete_name in delete_file_list[:-5]:
                os.remove(path + '/' + delete_name)


if __name__ == '__main__':
    QQCookie()