开篇:
于实践中学习.
1. 想法
本程序的开发主要经历了以下几个阶段(我是一个python初学者):
页面的下载->满减信息的查找->从首页动态寻找图书品类的入口->实现微信的通知.
2. 初衷与问题
页面下载用到了urllib模块,使用这个模块的过程中,又一次深入了解了关于http协议的工作细节.并且对前端的一些工作原理也有了了解.
因为自己对于amazon网站情有独钟,自己也喜欢看书,因此经常登录Amazon看一些关于图书打折的信息,正好最近学了点python,就想着做一个可以在服务器上全天候运行的程序,每天微信通知我关于亚马逊图书满减的信息(因为图书一般都是满减而不是打折,我也不知道这是为什么.).
(1)开发第一阶段:
问了一下我的导师,基本确定图书品类主页的地址一般是固定的.因此第一步就是下载图书品类的页面,然后分析页面代码,使用正则匹配相关信息并发送到微信.
(2)第二阶段修改
截止到目前实现了图书品类的搜索并发送到自己的微信,但是存在好多问题.第一个问题就是,图书品类主页的地址到底是固定还是不固定的.这点我存在疑问.但是我确定的是,www.amazon.cn这个域名是不会改的.而首页是存在图书品类的入口url的.为何不提取出来呢.于是各方面的更改,增加了首页动态获取图书入口的功能.
(3)第三阶段:增加给好友发送的功能
第二个大问题就是,目前实现的功能是用自己的微信登录,然后给登录的微信发送信息.由于微信登录模块模拟的是网页登录,如果平时自己对网页微信有需要的话,就会把服务器上的账号挤掉.因此最好是用一个第三方的微信账号以好友的身份给自己发送信息.于是乎使用wx模块增加该功能.
(4)第四阶段:增加定时任务
以好友身份发送的功能实现了,现在想要增加一个每天早上8点通知的功能.于是乎增加一个apschedule框架使用.
小结: 谷歌是个好东西.
3. 程序实现
以下是完整的代码实现,可能有点乱,不过尽可能的都加了注释:
import urllib.request
from wechat_sender import Sender
from html.parser import HTMLParser
import re
from wxpy import *
from apscheduler.schedulers.blocking import BlockingScheduler
import time
# 对程序将要使用到的常量进行初始化
ISOTIMEFORMAT = r'%Y-%m-%d %X'
# 获取当前时间
current_time = time.strftime(ISOTIMEFORMAT, time.localtime(time.time()))
# 获取amazon首页,目的是通过首页获取图书入口
base = r'https://www.amazon.cn'
user_agent = 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'
headers = {'User-Agent': user_agent}
data = {}
req = urllib.request.Request(base, data, headers)
source = urllib.request.urlopen(req)
b_content = source.read()
content = b_content.decode('utf-8')
source.close()
# 从亚马逊首页对图书品类的url进行提取
bookurl_pattern = re.compile(r'图书","url1":"(.*?)"', re.S)
entireurl = base + re.search(bookurl_pattern, content).group(1)
print(entireurl)
# 获取图书品类的首页
req_book = urllib.request.Request(entireurl, data, headers)
source_book = urllib.request.urlopen(req_book)
b_book_content = source_book.read()
book_content = b_book_content.decode('utf-8')
source_book.close()
# 正则表达式匹配想要的满减信息
def match(value):
model = r'.*满200元减.*'
return re.match(model, value)
# 向登陆的微信号发送消息(该方法不建议启用):因为程序在服务器端的运行会影响到自己平时在微信网页端的登录.
# 该方法未启用
def sendmessage(value):
Sender().send(value)
# 定时任务:实现对好友的通知.
def pro(friend, messages):
if result is None:
return
for word in messages:
friend.send(word)
print(current_time, word)
# 网页解析类.
class AMZparser(HTMLParser):
def __init__(self):
HTMLParser.__init__(self)
self.keyword = []
def handle_starttag(self, tag, attrs):
if tag == 'span':
if len(attrs) == 0:
pass
else:
for (varible, value) in attrs:
if varible == 'title':
if match(value) is not None:
self.keyword.append(value)
print("in parser: ", value)
# sendmessage(value)
# 主程序
if __name__ == '__main__':
# 试用解析类解析图书品类页面
parser = AMZparser()
parser.feed(book_content)
result = parser.keyword
parser.close()
# 登录
bot = Bot()
gao = bot.friends().search('xxx')[0] # xxx是你好友的名字
scheduler = BlockingScheduler()
# 设置定时任务并启动
scheduler.add_job(pro, 'cron', day_of_week='mon-fri', hour=11, minute=33, args=[gao, result])
scheduler.start()
print("check end")
备注:以上实现了满200减…的通知.大家可以按照自己的需求更改这个正则.