【Python实战】是的,我在公众号上面实现了“1024搜索”功
此文包含:
- WeRoBot微信公众号自动回复机器人
- 同一个需求,两个版本不同变化的分析
- mongoengine库的使用
- tornado如何给前端传值
- request.session()的使用
- 以上几点全部包含,还有一些杂七杂八的知识点在文章里
上一篇文章横空出世之后,在微信公众号里面添加了查看每日技术讨论区的帖子,有一位同学和我说,他没有账号。虽然只是随口一提,但是对信息敏感的我,立刻发觉到,没有账号,就不能够搜索,但是搜索这是个刚需啊。苦恼的肯定不止这一个人,肯定还有好多人都有这样的烦扰。
所以这回,我就尝试着在公众号里面加入搜索功能。先说一下目前的情况,搜索功能还在开发中,先后尝试了两种方案,这里我主要从技术的角度来说一下整体的开发流程,和大家分享一下。
先明确一点,开发这个东西,就是从技术出发,为了提升技术而做的。
废话不多说,先来看一下效果图吧。
这个是旧版本的效果:
旧版本这个是新版本的效果:
新版本为什么会有新旧两个版本呢?我这里就把我整个的开发思路和大家说一下。
首先,就是拿到需求,有位同学说没有账号。没有账号就不能搜索,那么我能不能将搜索功能添加进来。
然后,就考虑怎么添加搜索功能。社区是自带搜索的,我首先想到的就是通过借助社区的搜索功能来做我自己的搜索,也就是,将用户的搜多信息,通过我提交到社区,然后社区会返回给我结果,我在将结果编辑一下,返回给用户。这样,在用户看来,就实现了搜索功能。其实在里面,我的公众号是做了一层代理商而已。这就是旧版本的思路。
有了思路,我就开始开发,最后,开发出来一个逻辑能跑通的版本,发现这个版本的限制比较多。所以,就开始研究有没有其他办法能够实现搜索。
搜索的本质,就是从数据库里面拿到我要找的数据。所以,我这里需要:第一,数据库的容量足够大;第二,我能够操作数据库,执行查找操作。第一个条件,数据库容量足够大,我这里肯定是可以做到,无非就是爬虫不停地爬,然后将爬下来的结果塞到数据库中呗。第二个,代码要能够支持MongoDB的查找操作。由于之前一直使用的都是PyMongo库,经过仔细检查,我发现这个库不支持数据库的查找功能,而另一个mongoengine库是可以支持查找的,果断将库换成了mongoengine,这下就可以执行查找功能了。
依照新版本的思路,同样,我也开发出来一个能跑通逻辑的版本,效果就如同上面的效果图展示的一样。但是,新版本的搜索还是有很多硬伤。蛋疼。
首先,先扯一会儿微信公众号这个自动回复机器人的事儿。
闲扯自动回复机器人
这里用到的自动回复机器人,是用WeRoBot框架开发的,并且是将WeRoBot嵌入了Tornado框架中。大家一听到这里可能觉得很高深,其实这个是WeRoBot框架提供的一种功能而已。
具体做法就是,将WeRoBot新建出来的Robot,作为一个Tornado的Handler处理就可以,然后,通过annotation的方式,来编写回复函数即可。
标准的信息回复,即Text回复长这个样子:
@robot.filter('呵呵')
def replyDaGaier(message):
reply = """欢迎你来到皮克啪的铲屎官"""
return reply
看到上面用到了filter()
,这个就是过滤器,指当客户端发送过来“呵呵”固定的两个字的时候,我们的公众号会自动回复上面的内容,并且是按照文字形式回复。
如果是想回复成文章形式,就像上面的效果图中展示的那样,那么应该这么写:
@robot.filter('Daily')
def replyDaily(message):
time = datetime.datetime.now()
cur_time = str(time.year) + "-" + str(time.month) + "-" + str(time.day)
return [
[
"这里是标题",
"这里面写的是描述信息",
"图片URL",
"跳转的URL"
]
]
这个就是,客户端发送“Daily”,然后公众号回复一个网页的入口。点击那个文章,就会自动跳转到“跳转的URL”里面。我就是靠这样的方法来实现查看社区技术讨论区每日资讯的。
最后补充一句:个人的微信公众号,不支持自定义菜单的开发!不支持自定义菜单的开发!不支持自定义菜单的开发!
也就是说,一旦你打开的这个自动回复机器人了,那么,你公众号最下面一行的快捷菜单将会消失。这一点真的很不爽啊,个人的灵活性大大的降低了。开发热情一下子下来不少。但是企业公众号是可以开发自定义菜单的,但是企业公众号,一个月只能发4篇文章。所以,个人和企业之间,酌情选择吧。
如果自动机器人还有什么问题,可以给我留言,也可以进群交流。我都会为大家解答的。
好了,接下来我们就说今天的正事儿。
下面就详细的来聊聊两个版本的开发过程吧。
旧版本研发故事 v0.1
这个版本的基本思想是:用已有的账号,通过社区提供的搜索功能,来做搜索。
所以,这里就涉及到几个环节:账号,登录,查询搜索,返回结果处理,展示结果这几个环节。我们一个一个的来说。
账号
这个不是问题。只有有了账号,才能用社区的搜索功能。大家不要问了,我的账号买不起邀请码。
登录
登录这块,我之前写过一篇文章『【Python实战】用代码在1024论坛实现自动回贴』,这里用到的是,request的session,因为我们要保存cookie。即要保存账号的登录状态。
登录,就是自己模拟出来一个表头,然后,将登录需要传入的数据,自己拼凑出来,然后通过session.post()方法去执行登录操作,看返回的结果。如果返回结果成功,就说明登录成功。如果不成功,那就得看具体什么地方出现问题了。
这里简单谈一下,由于社区是有二次验证的功能存在,即每次登录的时候,在输入完账号密码之后,还会有个页面,要求输入一个动态密码,有点像将军令,或者Steam的登录方式。这个没办法用程序来破解,只能找到相对应的绑定设备,来手动输入号码,继续登录。
主语怎么在程序中间等待输入,Python提供了一个很好的函数input()
。
input_num = input("Input the f***** number:")
就这么简单的一行,就可以将输入的数字赋值给input_num
变量。
搜索查询
搜索查询的思路就是:在登录成功之后,进入社区的搜索页面,然后填入相对应的变量,执行一个HTTP POST请求,就可以了。
这里我们得需要拆开来说一下。
首先,是如何能够拿到我们需要搜索的关键字,即搜索的key_word
。因为,我们的远端服务器,在通过客户端访问那个url的时候,是一个HTTP GET请求,这个问题就变成了如何在GET请求中传递参数的问题了。
其实不难,tornado框架给了我们方法:
key_word = self.get_argument("key", "")
直接调用self.get_argument()
方法即可。第一个参数是在URL中的变量名,即URL中等号前面的那个部分,第二个参数是默认值,这里默认值填写成空。
至于,如何在URL中加入变量,这里简单说一下,就是在URL后面,先加一个?
,然后通过键值对的形式,用=
号连接键值对,填写在?
后面即可,键值对与键值对之间,通过&
号来做连接。
http://www.google.com?usr=root&psd=toor
上面这个URL中,就有两个变量,一个是usr
,它的值是root
,另一个是psd
,它的值是toor
。URL的传值就是这么写就好。
拿到关键字key_word
之后,我们需要来到搜索页面。这里,我们需要通过Charles来抓一个POST请求的包,来分析一下,当搜索按钮按下的时候,到底发生了什么。
其实,POST请求就是把搜索页面的表格数据,直接传了上去。那这里就简单了,我们只需要拼凑出来一个表格数据就可以。但是!这里有个问题,就是,社区为了防止机器人,在表格的最下面添加了一个验证码
。通过分析网页的源码,发现,那个输入验证码的数字,是页面已经传给我们的。我们只需要将页面用BeautifulSoup来解析一下,然后找到对应的值,塞到我们拼凑的数据里面,在传一个POST请求就可以了。
返回结果 和 数据展示
当上面讨论的POST请求传送成功之后,我们会拿到社区返回来的结果。
这是个页面,同样用BeautifulSoup来解析页面,找到每一条帖子的link,然后拼凑出来帖子的URL。
将结果放到一个列表里面,通过tornado提供的方法
self.render("search.html", key_word=key_word, result_info="成功", info=search_result_list, count=len(search_result_list))
将结果给到前端的html页面即可。
不要小看这里,这里是一种后端传值给前端的方法。在前端,只需要通过{{result_info}}
就可以显示传入的值,即成功
。
旧版本小结
旧版本是通过社区提供的功能来进行搜索的。搜索功能虽然强大,但是限制很多:
- 必须得有账号
- 2秒刷新限制,两次刷新不得小于2秒
- 两次搜索之间也有限制
- 搜搜板块也死板
- 这样的模块架设起来,会服务器的要求很高,并发性不是很好解决
所以,我尝试着研发一下新版本。
新版本研发故事 v0.2
新版本的思路:用庞大的数据库作为搜索的支撑,通过对数据库的操作,来实现搜索。
强大的数据库支撑的数据,就是要爬取更多的社区论坛的页面,然后把帖子信息整合到数据库中。这点不是很难,难点就在,社区的国内地址总是在换,以前的地址一旦失效,那么之前爬的数据都失效了。这点很蛋疼。
在有了大量数据作为支撑之后,我们就开始寻找能够通过代码来操作数据库的东西了。
之前我一直用的都是PyMongo,因为这个封装的分好,用起来非常简单,ORM性特别强,但是!这个库他不支持查找操作!!准确的说,不支持数据库的查找。若是强行查找也是可以的,你一次取出所有数据,然后for循环找符合条件的。这样做太慢了。经过网上搜索,发现另一个Python的MongoDB的库叫mongoengine。这个库是支持查找操作的。
使用起来也是非常的方便。感觉,这个库的开发,有些部分是借鉴了其他MySql库的操作方法。这里简单说一下使用。
首先是连接你的MongoDB,直接全局调用connect()
方法就可以:
connect("DBName", host="XX.XX.XX.XX", port=27017)
然后,你得对应到你的每一张表里。这里,一张表的数据,就是一个类。表名要和类名一一对应,而且里面的colume也要一一对应。
class table16(Document): # 父类是mongoengine的Document
post_title = StringField(required=True)
post_url = StringField(required=True)
上面的信息就是,表table16
里面,有两列,一个是post_title
另一个是post_url
。
如果要搜索,只需要调用:
search_result = table16.objects(post_title__contains=key_word)
直接调用post_title__contains
就可以。非常好用。
接下来,就是拿到数据,然后展示给前段了,和旧版本中的一样。这里就不多说了。
新版本小结
新版本,虽然速度要比旧版本快,但是也是有不少问题的:
- 数据量太少
- 一旦URL变了,地址就失效了
- 数据库的I/O操作消耗太高
就在刚才写文章的时候,我脑子里又出现了一个新的想法,停下手中的笔,试了试,应该是出来了搜索v0.3的版本了。
此文的精华
最后来给大家说一下在这次项目中,我是如何开展的。其实,我和大家也是一样的,好多知识点并不熟悉。但是有时候,项目开发中会遇到,遇到那种让人头大的,怎么办?
其实这个很简单。就是硬着头皮查,分析,然后学习,再动手实战,解决问题。大家不要觉得这样子会很麻烦,我估计,80%的人,遇到问题第一时间都是退缩,而我不一样,遇到问题第一时间就撸起袖子来分析问题,然后去网上查。说道网上查,这个该怎么查,是个学问。
我这里举个简单的例子,就比如新版本的开发中,需要在数据库中查找。我给大家来捋一下我是如何搞的:
首先,我的项目中,一直使用的是pymongo库。这个库,其实我也就是使用了大概30%不到。好多地方还不是很熟。既然要查找,首先看库里面的方法,有个find(),还有个find_one()方法,没有提供search或者其他类似的方法。那么,点find()方法进去,看里面的文档说明是怎样的。最后看到,这个库其实是不支持数据库搜索操作的。如果要用pymongo做查找,得先找到所有的结果,然后for循环来找。我自己试了一下,几千条数据,查找一下,太特么的慢了。果断放弃pymongo。这个时候,我就在网上查:python mongodb 查找。看看有没有别人写的博客总结。结果,就发现了一个人写的,用到了mongoengine这个库。看到这里,我是先研究他写的例子,是什么个套路:connect()连接数据库,然后用一个Class来做表的结构,直接调用class的方法,传入参数就可以查找。分析到这里,我认为,我需要的东西我已经找到了。那么下一步就是在我的项目里面先简单的写一个demo,测试一下,看看能不能跑出来预期的结果。果然,结果正确。这下,我就找到了解决问题的办法。接下来,就是完善我的代码了,将真正的逻辑写入到正式的代码里面。这样,一个问题就解决了。继续去解决下一个遇到的问题。。。。
解决问题的思路就是这个样子。当遇到问题,不会的,查百度,查谷歌,看官方文档,看代码的源码注释,都是很好的思路。甚至,在做出来一个东西之后,要想着迭代这个东西,优化他,就像我一样,做了个v0.1版本,太卡,就想换一个思路来做,搞出来一个v0.2版本。就在写文章的时候,其实v0.3版本已经出来了。效果目前不错。这里就不多说了。想了解的,可以关注我的公众号『皮克啪的铲屎官』,公众号下方有个『进群交流』的按钮,里面有入群的方式,完全免费。我会在群里和大家交流技术问题。你如果有疑问,也可以在里面提出来,大家一起讨论,共同进步。
至于服务器的代码,我已经分享出来,关注『皮克啪的铲屎官』,回复『服务器代码』,就可以获取到下载地址了。
推荐阅读
【Python实战】手把手超详细教程教你Scrapy爬达盖尔社区,有彩蛋
【Python实战】用Scrapy编写“1024网站种子吞噬爬虫”,送福利
【Python实战】用代码来访问1024网站,送福利
【Python实战】用Scrapyd把Scrapy爬虫一步一步部署到腾讯云上
这么硬货的公众号,你们不关注一下啊?
底部二维码.png