张三的困境
张三和如花是一对恩爱恋人。每天早上的问候是恋人的浪漫起点。从罗老师的课程中我们也知道三儿没啥文化(犯了那么多事,没时间学习呀~),那可苦了三儿了,情话不会说。哥劝他找度娘。
可是张三琐事缠身,无法准时回复,这不,如花又"无理取闹"了(抗议,仙女的事能是无理取闹吗?)
这不张三找上我来了,那我可得好好帮忙,毕竟从张三身上我也学会了很多。
需求划分
爬取情话
为了让我们的张三不再苦于寻找情话,秉着客户的需求就是我的目标这一原则,使用爬虫技术爬取情话网部分浪漫的情话。使用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)
情话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
,随机获取一句情话:
定时发送
咱不能让如花等呀,说好了每天早上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('结束消息发送')

张三的后续
完整代码
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()
版权属于:带翅膀的猫
本文链接:https://www.chengpengper.cn/archives/146/
转载时须注明出处及本声明
想想你的文章写的特别好https://www.ea55.com/