背景架空现实,如有雷同,不胜荣幸!

张三的困境

聊天1.png

      张三和如花是一对恩爱恋人。每天早上的问候是恋人的浪漫起点。从罗老师的课程中我们也知道三儿没啥文化(犯了那么多事,没时间学习呀~),那可苦了三儿了,情话不会说。哥劝他找度娘。
      可是张三琐事缠身,无法准时回复,这不,如花又"无理取闹"了(抗议,仙女的事能是无理取闹吗?)

聊天2.png

      这不张三找上我来了,那我可得好好帮忙,毕竟从张三身上我也学会了很多。

聊天3.png

需求划分

爬取情话

      为了让我们的张三不再苦于寻找情话,秉着客户的需求就是我的目标这一原则,使用爬虫技术爬取情话网部分浪漫的情话。使用Xpath解析网页数据,将数据保存至MySql数据库中。

创建数据表

CREATE TABLE `qinghua`  (
  `id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '情话ID',
  `love_words` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NULL DEFAULT NULL COMMENT '情话',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = MyISAM AUTO_INCREMENT = 40948 CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Dynamic;

爬虫实现

      前置知识:Python操作MySql数据库;Xpath解析Html。

from lxml import etree
import requests
import pymysql
import logging

logging.captureWarnings(True)
# 打开数据库连接
db = pymysql.connect("localhost", "root", "zu3.141592653", "qinghua")
# Xpath规则
xpath_pat = "/html/body/div[5]/div[1]/div[2]/div[2]/div/a/p/text()"

# 爬虫
def spider(urls=[]):
    for i in range(len(urls)):
        resp = requests.get(urls[i])
        if resp.status_code != 200:
            print("爬取出错")
            continue
        # 获取网页数据
        html = etree.HTML(resp.text)
        # 使用Xpath解析数据
        qinghua = html.xpath(xpath_pat)
        insert2DB(qinghua)
    # 关闭数据库连接
    db.close()

# 往数据库中插入数据
def insert2DB(data=[]):
    print(data)
    # 使用 cursor() 方法创建一个游标对象 cursor
    cursor = db.cursor()
    sql = "INSERT INTO qinghua(love_words) VALUES(%s)"
    try:
        for i in range(len(data)):
            cursor.execute(sql, (data[i]))
        db.commit()
    except:
        print('出异常,回滚')
        db.rollback()


if __name__ == '__main__':
    # 情话网页链接
    urls = []
    urls.append('http://www.ainicr.cn/qh/653.html')
    urls.append('http://www.ainicr.cn/qh/654.html')
    urls.append('http://www.ainicr.cn/qh/655.html')
    spider(urls)

data.png

情话API

      我希望能提供个API接口随机返回数据,而不使用Python获取数据库数据。如此可以在其他系统中使用这些数据。
      直接使用世界上最好的语言——Php:

<?php
    function get_lovewords($isjson=true){
        //连接数据库
        $db = new mysqli('localhost', 'root', 'zu3.141592653', 'qinghua');
        if ($db->connect_errno) {
            printf("Connect failed: %s\n", $db->connect_error);
            exit();
        }
        $db->set_charset('utf8');//设置字符集
                # 随机获取一条数据
        $sql = "select id,love_words from qinghua a join (select round(rand()*(select max(id) from qinghua)) as idd) as b on a.id>b.idd limit 1;";
        $query = $db->query($sql);
        $row = $query->fetch_row();

        //判断返回格式
        if ($isjson) {
            // var_dump($row[1]);
            return json(['id'=>$row[0], 'love_words'=>$row[1]]);
        }else{
            // var_dump($row[1]);
            return $row[1];
        }
        $db->close();//关闭数据库连接
        
    }

    // 默认返回json格式
    // 如需返回文本格式请填写false
    echo get_lovewords(true);

    function json($data) {
        header('content-type:application/json;charset=utf-8');
        return stripslashes(json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT));
    }
?>

      调用接口:http://localhost/lovewords.php,随机获取一句情话:

接口.png

定时发送

      咱不能让如花等呀,说好了每天早上8点请安:

  • 需要一款Python任务调度框架。它允许你像Cron那样安排定期执行的任务——Apscheduler
  • 控制QQ/微信发送消息——Win32

Apscheduler

# 安装:pip install apscheduler

from apscheduler.schedulers.blocking import BlockingScheduler

# 具体执行的任务
def start_job():
    print("start job")


def main():
    sched = BlockingScheduler()
    # 周一至周五每天早上8点执行任务
    sched.add_job(start_job,'cron',day_of_week='0-4',hour='8')
    # 周末每天早上9点执行任务
    sched.add_job(start_job,'cron',day_of_week='5-6',hour='9')
    sched.start()

if __name__ == '__main__':
    main()

Win32

      pywin32是一个第三方模块库,主要的作用是方便python开发者快速调用windows API的一个模块库。我使用Win32获取聊天窗口,将剪切板中的数据发送出去。

def sendMsg(name, msg):
    # 打开剪贴板
    w.OpenClipboard()
    # 清空剪贴板
    w.EmptyClipboard()
    # 设置剪贴板内容
    w.SetClipboardData(win32con.CF_UNICODETEXT, msg)
    # 获取剪贴板内容
    date = w.GetClipboardData()
    # 关闭剪贴板
    w.CloseClipboard()
    # 获取窗口句柄
    handle = win32gui.FindWindow(None, name)
    if handle != 0:
        win32gui.ShowWindow(handle, win32con.SW_SHOWMINIMIZED)
        win32gui.ShowWindow(handle, win32con.SW_SHOWNORMAL)
        win32gui.ShowWindow(handle, win32con.SW_SHOW)
        win32gui.SetWindowPos(handle, win32con.HWND_TOPMOST, 100, 100, 500, 500,win32con.SWP_SHOWWINDOW) 
        win32gui.SetForegroundWindow(handle)  # 获取控制
    else:
        print('找不到该窗口,保证其是一个单独的窗口')
        return
    # 显示窗口
    win32gui.ShowWindow(handle, win32con.SW_SHOW)
    # 把剪切板内容粘贴到窗口
    win32gui.SendMessage(handle, win32con.WM_PASTE, 0, 0)
    # 发送消息
    win32api.keybd_event(17, 0, 0, 0)  # ctrl键位码是17
    win32api.keybd_event(86, 0, 0, 0)  # v键位码是86
    win32api.keybd_event(86, 0, win32con.KEYEVENTF_KEYUP, 0)  # 释放按键
    win32api.keybd_event(17, 0, win32con.KEYEVENTF_KEYUP, 0)
    win32api.keybd_event(18, 0, 0, 0)  # Alt键位码
    win32api.keybd_event(83, 0, 0, 0)  # s键位码
    win32api.keybd_event(18, 0, win32con.KEYEVENTF_KEYUP, 0)  # 释放按键
    win32api.keybd_event(83, 0, win32con.KEYEVENTF_KEYUP, 0)

调用API接口

def job(name=''):
    # name: 窗口名称
    print('开始发送消息')
    # 调用接口获取数据
    resp = requests.get(api)
    if resp.status_code != 200:
        print("API调用出错")
    else:
        content = json.loads(resp.content)
        msg = content['love_words']
        sendMsg(name, msg)
        print(msg)
    print('结束消息发送')

完美~

result.png

张三的后续

聊天4.png

撒狗粮呀!这不能再帮了~

完整代码

import json
from lxml import etree
import requests
import pymysql
import logging
import win32gui
import win32con
import win32clipboard as w
from apscheduler.schedulers.blocking import BlockingScheduler


logging.captureWarnings(True)
# 打开数据库连接
db = pymysql.connect("localhost", "root", "***", "qinghua")
# Xpath规则
xpath_pat = "/html/body/div[5]/div[1]/div[2]/div[2]/div/a/p/text()"
# 情话接口API
api = "http://localhost/lovewords.php"

def sendMsg(name, msg):
    # 打开剪贴板
    w.OpenClipboard()
    # 清空剪贴板
    w.EmptyClipboard()
    # 设置剪贴板内容
    w.SetClipboardData(win32con.CF_UNICODETEXT, msg)
    # 获取剪贴板内容
    date = w.GetClipboardData()
    # 关闭剪贴板
    w.CloseClipboard()
    # 获取窗口句柄
    handle = win32gui.FindWindow(None, name)
    if handle != 0:
        win32gui.ShowWindow(handle, win32con.SW_SHOWMINIMIZED)
        win32gui.ShowWindow(handle, win32con.SW_SHOWNORMAL)
        win32gui.ShowWindow(handle, win32con.SW_SHOW)
        win32gui.SetWindowPos(handle, win32con.HWND_TOPMOST, 100, 100, 500, 500,win32con.SWP_SHOWWINDOW)  
        win32gui.SetForegroundWindow(handle)  # 获取控制
    else:
        print('找不到该窗口,保证其是一个单独的窗口')
        return
    # 显示窗口
    win32gui.ShowWindow(handle, win32con.SW_SHOW)
    # 把剪切板内容粘贴到窗口
    win32gui.SendMessage(handle, win32con.WM_PASTE, 0, 0)
    # 发送消息
    win32api.keybd_event(17, 0, 0, 0)  # ctrl键位码是17
    win32api.keybd_event(86, 0, 0, 0)  # v键位码是86
    win32api.keybd_event(86, 0, win32con.KEYEVENTF_KEYUP, 0)  # 释放按键
    win32api.keybd_event(17, 0, win32con.KEYEVENTF_KEYUP, 0)
    win32api.keybd_event(18, 0, 0, 0)  # Alt键位码
    win32api.keybd_event(83, 0, 0, 0)  # s键位码
    win32api.keybd_event(18, 0, win32con.KEYEVENTF_KEYUP, 0)  # 释放按键
    win32api.keybd_event(83, 0, win32con.KEYEVENTF_KEYUP, 0)

def job(name=''):
    # name: 窗口名称
    print('开始发送消息')
    # 调用接口获取数据
    resp = requests.get(api)
    if resp.status_code != 200:
        print("API调用出错")
    else:
        content = json.loads(resp.content)
        msg = content['love_words']
        sendMsg(name, msg)
        print(msg)
    print('结束消息发送')

# 爬取数据
def doSpider(urls=[]):
    for i in range(len(urls)):
        resp = requests.get(urls[i])
        if resp.status_code != 200:
            print("爬取出错")
            continue
        # 获取网页数据
        html = etree.HTML(resp.text)
        # 使用Xpath解析数据
        qinghua = html.xpath(xpath_pat)
        insert2DB(qinghua)
    # 关闭数据库连接
    db.close()

# 往数据库中插入数据
def insert2DB(data=[]):
    print(data)
    # 使用 cursor() 方法创建一个游标对象 cursor
    cursor = db.cursor()
    sql = "INSERT INTO qinghua(love_words) VALUES(%s)"
    try:
        for i in range(len(data)):
            cursor.execute(sql, (data[i]))
        db.commit()
    except:
        print('出异常,回滚')
        db.rollback()

# 爬虫
def spider():
    # 情话网页链接
    urls = []
    urls.append('http://www.ainicr.cn/qh/653.html')
    urls.append('http://www.ainicr.cn/qh/654.html')
    urls.append('http://www.ainicr.cn/qh/655.html')
    doSpider(urls)

def start_job():
    job('小号')

def main():
    sched = BlockingScheduler()
    sched.add_job(start_job,'cron',day_of_week='0-4',hour='18',minute='51')
    sched.add_job(start_job,'cron',day_of_week='0-4',hour='18',minute='52')
    sched.start()

if __name__ == '__main__':
    main()
Last modification:December 23rd, 2020 at 08:04 pm
如果觉得我的文章对你有用,请随意赞赏