一个小型的Python flask项目,实现搜索张大妈关键字+筛选商品,符合规则商品推送。
#前言
如果说Java算我的主语言,那当了这么久的程序猿,不学习一门副语言说不过去。近几年趋势下,Python和Go是目前最火的选择。目前状态下,我学习Go这种高并发语言可能没有什么使用场景,所以选了Python,入门简单,可玩性很高。
17年(才)学习了Python,后面就一直寻找写点什么代码的机会。
1.先是写了些很简单的脚本,配合正则表达式实现简单修改里面的文件内容。
2.爬虫这么好玩的东西怎么能不玩,学习了python scrapy框架。爬了什么值得买《python scrapy 入门爬虫 「什么值得买」关键字搜索》。可以根据关键字搜索和按照条件筛选出商品。
微博问题也是个好东西,里面的问题是超过一定时间可以免费围观的。由于每次进入微博从几百条问题中找到当前阅读进度的那条问题很不容易,所以写了份爬取问答列表的代码。试过爬取里面的内容,发现微博验证机制很厉害。请了个前端大哥帮忙尝试**都搞不定所以放弃了。有这样一份问题列表看起来就很方便了。
3.工作需要又用 Python 进行了很多数据统计,为同事们提供了无数份 excel 数据统计。还爬了下某眼的票房和观影人次数据,这数据对公司的参考意义实在是很大。
#项目实现
1.python scrapy爬虫,爬什么值得买。
2.使用 python flask 实现小型 web 服务。(后悔没用 django,遇到很多问题搜索不到)
3.接入微信公众号后台,可以收到用户向这个公众号发送的消息,制定被动回复用户消息内容。主动发送客户消息。
4.微信主动发送客服消息接口,只有在用户发消息来的48小时内,才能发出客服消息。超过48小时候无法发送。所以引入钉钉机器人。
5.写个前端项目——花不少时间,写个Android应用——会懒得打开,所以还是在微信中发送特定指令,后台识别指令来完成功能。但是正则表达式写的我很难受。
6.简单的使用 linux crontab 实现定时任务。
项目数据库设计
列名 | 数据类型 | 字段类型 | 长度 | 是否为空 | 默认值 | 备注 |
wx_user | 微信用户表 | |||||
id | int(11) | int | NULL | NO | NULL | 自增id |
wx_openid | varchar(255) | varchar | 255 | NO | 微信openid | |
dd_webhook | varchar(255) | varchar | 255 | YES | NULL | 钉钉机器人webhook网址 |
create_time | datetime | datetime | NULL | NO | NULL | 创建时间 |
update_time | datetime | datetime | NULL | NO | NULL | 更新时间 |
status | tinyint(1) | tinyint | NULL | NO | 0 | 0默认 1关注 2取关 |
zdm_item | 商品表 | |||||
id | int(11) | int | NULL | NO | NULL | 商品id |
title | varchar(255) | varchar | 255 | NO | 商品标题 | |
price | varchar(255) | varchar | 255 | NO | 价格 | |
desc | text | text | 65535 | NO | NULL | 描述 |
zhi_yes | int(11) | int | NULL | NO | NULL | 点值数 |
zhi_no | int(11) | int | NULL | NO | NULL | 点不值数 |
star | int(11) | int | NULL | NO | NULL | 收藏数 |
comment | int(11) | int | NULL | NO | NULL | 评论数 |
time | datetime | datetime | NULL | NO | NULL | 商品发布时间 |
channel | varchar(255) | varchar | 255 | NO | 商品渠道(淘宝、京东等) | |
detail_url | varchar(255) | varchar | 255 | NO | 值得买商品详情连接 | |
url | varchar(255) | varchar | 255 | NO | 商品购买了链接 | |
img | varchar(255) | varchar | 255 | NO | 商品图片 | |
scrapy_record | 搜索记录 | |||||
id | int(11) | int | NULL | NO | NULL | 自增id |
wx_openid | varchar(255) | varchar | 255 | NO | 微信openid | |
params | varchar(255) | varchar | 255 | NO | 此次搜索参数 | |
type | tinyint(1) | tinyint | NULL | NO | 0 | 0主动搜索,1推送 |
result | text | text | 65535 | YES | NULL | 搜索结果商品id列表 |
send | text | text | 65535 | YES | NULL | 需要发送到用户的商品id列表 |
time | datetime | datetime | NULL | NO | NULL | 爬取时间 |
wx_message | 微信消息记录 | |||||
id | int(11) | int | NULL | NO | NULL | 自增id |
msg_id | bigint(20) unsigned | bigint | NULL | NO | NULL | 微信msg_id |
msg_type | varchar(11) | varchar | 11 | NO | 微信msg类型 | |
from_user | varchar(255) | varchar | 255 | NO | 发送者微信openid | |
to_user | varchar(255) | varchar | 255 | NO | 接受者微信openid | |
create_time | bigint(20) unsigned | bigint | NULL | NO | NULL | 创建时间 |
content | text | text | 65535 | NO | NULL | 消息内容 |
config |
存一直配置字段 比如微信access_token |
|||||
alembic_version | sqlalchemy创建的 |
#使用说明
关注公众号发特定命令。
因为微信的主动客服消息需要认证,需要公司营业执照之类的。搞不定只好用测试号。
1.主动搜索
h 表示help
『bind_webhook』{url} 和 『unbind_webhook』 表示绑定钉钉机器人
参照钉钉文档《钉钉-自定义机器人》,毕竟微信客户消息只有48小时内可以发出,而且钉钉支持md风格消息,所以可以看图片。
「小米」「谷物」「80:10:-1:-1:-1」
第一个直角引号是搜索关键字
第二个直角引号是排除关键字
第三个直角引号是筛选条件,里面分号分隔,分别是「点值比率需要≥x:点值数≥x:点不值数≤x:收藏数≥x:评论数≥x」-1表示不使用该筛选条件
2.设定推送
前3个命令就是操作 linux crontab 文件的增删查功能。
『push_immediately』{笔记本} 这个的使用场景是,比如我设定了早10点-晚22点的整点推送,然后早上起来9点50分,目前刚好有时间看下商品推送,等下就要挤公交没时间看了。就可以发送这条命令立即让服务搜索+推送一遍。
#遇到的问题
1.flask中执行scrapy爬虫方法会异步
改为命令行执行,同步完成后去数据库搜索该用户的最新记录(这方法有点山寨)
os.system('scrapy crawl concrete_search -a search_item=%s -a exclude=%s -o smzdm.json' % (search_item, exclude))
2.scrapy的pipelines.py中无法使用flask_alchemy操作数据库,因为不在flask上下文环境内。
使用原生pymysql进行添加数据操作
3.有外键关联的,两个表删除一并删除
改数据库表实现级联删除
4.执行os.system('scrapy crawl concrete_search -a search_item=%s -a exclude=%s -o smzdm.json' % (search_item, exclude))时报错,No module named _sqlite3
yum install sqlite-devel 然后重装python(进入python安装目录,make,然后make install)
5.微信出现「该公众号提供的服务出现故障,请稍后再试」
一开始以为是5秒内未能返回,折腾多线程多进程,想临时返回「爬取中...」。再使用微信客服客服消息发送。各种折腾捣鼓了大半天,后面发现其实是微信返回的消息长度过长。所以最后改成在微信中只返回7条商品信息。
6.使用 threading.Thread 新建线程,异步请求钉钉webhook发送机器人消息。发现一直卡住。
浪费了我两天时间,期间还去找 python 程序员兄弟问了下,他说他也没啥头绪。持续摸索,发现flask框架对于一个请求返回后,这次请求启动的线程全部都停止了,直到下一个请求过来才会执行。
#项目源码
非专业的写的太烂,而且还不怎么整理。不好意思放了。
还没做输入参数的验证。如果破坏性的输入各种奇奇怪怪的值,估计服务器还会报错。
引用程序猿经典用语「先实现功能,其他的再慢慢迭代」