最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501
当前位置: 首页 - 科技 - 知识百科 - 正文

flask完成一个小应用方法

来源:懂视网 责编:小采 时间:2020-11-27 14:13:54
文档

flask完成一个小应用方法

flask完成一个小应用方法:上周 @萍姐 问我如何抓取天猫上面店铺的评分,看了下挺简单的,于是花了点时间写了个Python脚本,加上web.py做成一个web服务,使用起来还不错,今天来看的时候发现当时为了方便直接用web.py开发有点简陋,自己也好久没用flask写过东西了,打算用flask再
推荐度:
导读flask完成一个小应用方法:上周 @萍姐 问我如何抓取天猫上面店铺的评分,看了下挺简单的,于是花了点时间写了个Python脚本,加上web.py做成一个web服务,使用起来还不错,今天来看的时候发现当时为了方便直接用web.py开发有点简陋,自己也好久没用flask写过东西了,打算用flask再
上周 @萍姐 问我如何抓取天猫上面店铺的评分,看了下挺简单的,于是花了点时间写了个Python脚本,加上web.py做成一个web服务,使用起来还不错,今天来看的时候发现当时为了方便直接用web.py开发有点简陋,自己也好久没用flask写过东西了,打算用flask再写一遍,顺便复习下旧的知识,如果你是flask初学者,可以参考这个例子。

提示:博主默认你已经具备了Python的基础知识,已经能够很顺畅的编写一些Python脚本,否则接下来你会比较难看懂。

旧版

这里先给出旧版本的一些使用截图,初始化的时候的样子

火狐截图_2016-10-30t01-27-00.009z.png - 大小: 14.18 KB - 尺寸: 529 x 199 - 点击打开新窗口浏览全图

模糊查询

火狐截图_2016-10-30t01-28-39.825z.png - 大小: 49.02 KB - 尺寸: 420 x 648 - 点击打开新窗口浏览全图

精确查询

火狐截图_2016-10-30t01-29-34.543z.png - 大小: 16.66 KB - 尺寸: 517 x 195 - 点击打开新窗口浏览全图

技术

这个应用比较简单,所使用的技术也比较少,主要有以下技术要点

  • requests模拟请求

  • 正则匹配关键字

  • web.py搭建web环境

  • vue.js做数据自动绑定

  • 是不是很简单?

    Flask Web开发基于Python的Web应用开发实战pdf

    在这个小应用中使用web.py的时候目录结构是这样的

    2016-10-30 09-55-46屏幕截图.png - 大小: 16.82 KB - 尺寸: 766 x 107 - 点击打开新窗口浏览全图

    其中static目录里面存放的是静态资源

    2016-10-30 09-57-18屏幕截图.png - 大小: 26.57 KB - 尺寸: 694 x 166 - 点击打开新窗口浏览全图

    结构相当简单

    python代码

    这里给出全部的Python代码

    #!/usr/bin/env python# coding=utf-8import requestsimport jsonimport webimport sysimport re
    
    reload(sys)
    sys.setdefaultencoding('utf8')
    
    urls = ("/", "index","/query", "Query")
    
    
    render = web.template.render('static', cache=False)class index:def GET(self):return render.index('static')class Query:def POST(self):
     keywords = str(web.input().get('shopname'))
     url_base = ""+keywords
     headers = {"User-Agent": "iphone7"}try:
     result_base = requests.get(url=url_base, headers=headers, timeout=15).content.replace('
    ', '').replace(' ','')
     infostr = re.findall(r'j_shop_moreshop_more">(.+?)</div>', result_base)
     shoplist = []for item in infostr:
     scorelist = re.findall(r'">(.+?)</span><iclass="', item)
     thisShopname = re.findall(r'<span>(.+?)</span>', item)[0]
     shoplist.append('{"shopname": "'+ thisShopname +'" , "dsr": "'+scorelist[0]+'", "service": "'+scorelist[1].split('">')[1]+'","ship": "'+scorelist[2].split('">')[1]+'"}')return json.dumps({"code": 0, "rows":list(set(shoplist))})except Exception, e:print ereturn json.dumps({"code": -1, "msg": "没查询到相关店铺"})if __name__ == "__main__":
     app = web.application(urls, globals())
     app.run()

    前端HTML代码

    $def with (urlbase)<!DOCTYPE html>
    <html lang="zh-CN">
     <head>
     <meta charset="utf-8">
     <meta http-equiv="X-UA-Compatible" content="IE=edge">
     <meta name="renderer" content="webkit">
     <meta name="viewport" content="width=device-width, initial-scale=1">
     <title>Hello world</title>
     </head>
     <body>
     <input type="text" name="shopname">
     <input type="button" value="提交" @click="query">
     <div class="info" v-for="item in shopes" style="border-bottom: #ccc 1px dashed">
     <p>店铺:{{ item.shopname }}</p>
     <p>描述相符:{{ item.dsr }}<br>服务态度:{{ item.service }}<br>物流服务:{{ item.ship }}</p>
     </div>
     <script type="text/javascript" src="$urlbase/jquery.min.js"></script>
     <script type="text/javascript" src="$urlbase/vue.js"></script>
     <script type="text/javascript" src="$urlbase/index.js"></script>
     </body>
    </html>

    js代码

    var mainVM = new Vue({
     el: 'body',
     data: {
     shopes:[
     {
     shopname:'未查询',
     dsr:'未查询',
     service:'未查询',
     ship:'未查询'}
     ]
     },
     methods:{
     query:function(){
     var _self = this,keyword = $('input[name="shopname"]').val();
     $.post('/query',{"shopname":keyword},function (data) {if(data.code == 0){
     _self.shopes = [];for(var k in data.rows){
     var thisdata = JSON.parse(data.rows[k]);
     _self.shopes.push({
     shopname:thisdata.shopname,
     dsr:thisdata.dsr,
     service:thisdata.service,
     ship:thisdata.ship
     })
     }
     }else{
     alert('查询出错,错误信息:'+data.msg);
     }
     },"json");
     }
     }
    });

      可以说代码部分也是相当简单,前端HTML和js的代码就不解释了,很容易看懂,这里只对app.py做简单的解释。

      观察天猫的搜索页面,发现天猫pc端跟手机端页面都可以轻松抓取,但是使用手机端页面会更加快速方便,因为结构上更加清晰,而且数据量少,抓取速度更快

      如何实现只抓取手机端页面的数据呢?很简单,这里我们只需要定义以下HTTP的请求头信息就可以了,也就是headers,如下定义

      headers={"User-Agent":"iphone7"}

      天猫的搜索链接是使用的get请求,地址为

      "https://list.tmall.com/search_product.htm?q="+keywords

      参数只需要传入一个关键字就可以了,前端使用ajax把数据POST给服务端,服务端接收使用下面的这句话

      keywords=str(web.input().get('shopname'))

      是不是马上就搞定了关键的几步了?接下来发起请求拿到数据就可以了

      result_base=requests.get(url=url_base,headers=headers,timeout=15).content.replace(' ','').replace('','')

      注意,这里我把返回的结果中的换行跟空格都去掉了,因为我这里所需要的数据很简单,为了匹配方便我直接给替换成可空,也就是后面的这个

      .replace(' ','').replace('','')

      然后根据正则匹配的字符串进行遍历组合成结果返回给前端就好了,前端直接使用vue.js进行数据的绑定,几乎不需要DOM操作就可以完成结果列表的渲染,棒!(这里强行安利一波vue.js)

      前后端通信使用json进行数据交互,友好而且方便。

    重写

    上面给出了所需要的技术要点和关键代码,那么现在我需要使用flask重写一遍,当然了,关键部分还是不用变动,只是处理方式上稍微有些差异,如果会用web.py,那么使用flask上手应该是很快的。

    1、web.py的处理方式

    在使用web.py的时候我们启动一个web服务很简单,通常执行以下命令

    python app.py

    这样我们就启动了一个web服务,但是这样的话会有很多问题,主要有以下几点

  • 不能关闭终端窗口,否则应用结束,一般用于调试

  • 多个应用的时候公用Python环境会引起冲突

  • 注意:

    web.py并不适合高并发的应用,但是作为一般应用还是可以轻松应对的。

    以上命令执行后web.py会在8080端口绑定一个web服务,如果你想创建多个应用,那么你应该在后面加上端口号

    如果你使用了多个域名指向一台机器的多个应用,那么你应该使用nginx来转发请求,而不是直接输入域名加端口号

    在远程vps上运行开发完成的应用时,你可以执行以下命令把web以后台服务的形式运行

    nohup python app.py

    这种方式简单粗暴,但是仅仅作为临时方案是可行的,运行上述命令后你可以安心的关掉终端,而且web服务依然在运行,但是一旦重启了服务器,那么就得重新登录vps再次执行命令,不是很方便。

    2、flask的处理方式

    flask和web.py类似,它自带了一个web服务器,默认绑定在5000端口,但是它本身自带的web服务器并不是很好,安全性也不高,作为开发使用还是足够的,正式生产环境中不太建议直接使用flask自带的web服务。

    好了,现在可以开始了,为了解决上面提到几个问题,这里咱们来使用一个新东西,上面说了多应用环境冲突的问题,在这儿可以使用一个叫做“虚拟环境”的东西解决。

    “虚拟环境”就是直接复制一个Python的全局环境,但是是独立出来的,你可以在这个环境里面安装各种模块,而且不会影响到Python的全局环境,也就是说如果你把其中的一个“虚拟环境”给玩坏了,起不来了,那么你只需要删掉坏的“虚拟环境”重新创建一个就可以了,这些操作都不会对Python全局环境有任何的影响,安全又方便,下面咱们就来创建一个“虚拟环境”。

    博主使用的开发环境是Ubuntu 16.04 并没有自带这个软件,使用下面的命令安装

    sudo apt-get install python-virtualenv -y

    安装完之后测试下是否安装成功

    ~$ virtualenv --version
    15.0.1

    接下来咱们创建一个叫 tmall 虚拟环境用于运行我们的应用

    ~$ virtualenv tmall
    Running virtualenv with interpreter /usr/bin/python2
    New python executable in /home/kbdancer/tmall/bin/python2
    Also creating executable in /home/kbdancer/tmall/bin/python
    Installing setuptools, pkg_resources, pip, wheel...done.

    创建的时候会给出创建的位置,如果你需要在指定的目录下面创建虚拟环境,那么你得切换到目标目录,然后执行创建命令,博主这里直接在自己的用户目录下面执行的创建命令,自然就是在用户目录下面生成的一个 tmall 文件夹,文件夹下面自动生成了Python环境

    2016-10-30 10-39-57屏幕截图.png - 大小: 36.01 KB - 尺寸: 768 x 243 - 点击打开新窗口浏览全图

    安装完之后需要将这个环境激活才能使用,执行下面的命令进行激活

    ~$ source tmall/bin/activate
    (tmall) :~$

    接着在虚拟环境中安装flask环境(博主默认你的Python全局环境中已经有了easy_install或者pip),博主这里使用pip进行安装

    ~$ pip install flask

    好了,所需要的环境配置完成,接下来就可以开始写小应用了。

    3、开始编码

    编码这个环节应该是快速而且高效的,上面我们已经给出了旧代码,关键部分直接复制过来就能用,稍微改改就可以跑起来了。

    flask默认使用Jinja2作为模板引擎,Jinja2在进行模板渲染的时候通常会识别{{}}中的内容进行填充,但是这里博主遇到了一个尴尬的问题,Vue.js也是使用的{{}}作为标识符进行渲染,这就导致了冲突,访问页面的时候就会出现如图所示的错误

    火狐截图_2016-10-30t03-27-29.227z.png - 大小: 123.67 KB - 尺寸: x - 点击打开新窗口浏览全图

    当然,解决方法还是有的,参考这篇文章进行配置 解决Jinja2与Vue.js的模板冲突 解决思路也比较简单,就是在需要Jinja2渲染的时候添加一个空格,而vue.js渲染的时候则不需要空格,python脚本如下

    from flask import Flask, render_template
    
    app = Flask(__name__)
    app.jinja_env.variable_start_string = '{{ '
    app.jinja_env.variable_end_string = ' }}'

    前端HTML代码修改后就成了这样

    <!DOCTYPE html><html lang="zh-CN"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="renderer" content="webkit"><meta name="viewport" content="width=device-width, initial-scale=1"><title>Hello world</title></head><body><input type="text" name="shopname"><input type="button" value="提交" @click="query"><div class="info" v-for="item in shopes" style="border-bottom: #ccc 1px dashed"><p>店铺:{{item.shopname}}</p><p>描述相符:{{item.dsr}}<br>服务态度:{{item.service}}<br>物流服务:{{item.ship}}</p></div><script type="text/javascript" src="{{ url_for('static', filename='jquery.min.js') }}"></script><script type="text/javascript" src="{{ url_for('static', filename='vue.js') }}"></script><script type="text/javascript" src="{{ url_for('static', filename='index.js') }}"></script></body></html>

    Jinja2默认会在templates目录下面寻找模板文件,而静态文件比如css,js之类的默认存储在static目录下面,这里我们按照Jinja2的默认设置稍微进行修改,当然,如果你想自定义模板目录或者静态文件的目录也是可以的,只需要稍微的配置下就行了,博主这里按照默认的规则来设置。

    很快,我们的小应用就跑起来了

    2016-10-30 11-34-42屏幕截图.png - 大小: 19.03 KB - 尺寸: 565 x 309 - 点击打开新窗口浏览全图

    这里还是需要提到几个关键点:

    flask中接收前端传递过来的参数用到的是request对象,前端使用json把数据post到后端,后端使用下面这句进行接收

    request.form.get('shopname')

    更多详细使用方法参考这个地址 浅入浅出Flask框架:处理客户端通过POST方法传送的数据 接着测试下小应用能不能正常运行

    2016-10-30 11-56-46屏幕截图.png - 大小: 54.49 KB - 尺寸: 587 x 686 - 点击打开新窗口浏览全图2016-10-30 11-58-39屏幕截图.png - 大小: 44.3 KB - 尺寸: 579 x 565 - 点击打开新窗口浏览全图

    OK,测试通过。

    4、关于部署

    由于这个小应用比较简单,部署起来可以按照常规的部署方式进行,但是并不适合生产环境,所以这里暂时不写如何部署,下次有大型网站案例的时候再详细写如何部署以及优化。

    5、完整代码

    python部分

    #!/usr/bin/env python# coding=utf-8from flask import Flask, render_template, requestimport requestsimport jsonimport re
    
    app = Flask(__name__)
    app.jinja_env.variable_start_string = '{{ '
    app.jinja_env.variable_end_string = ' }}'@app.route('/')def index():return render_template('index.html')@app.route('/query', methods=['POST'])def query():
     keywords = request.form.get('shopname')
     url_base = "https://list.tmall.com/search_product.htm?q=" + keywords
     headers = {"User-Agent": "iphone7"}try:
     result_base = requests.get(url=url_base, headers=headers, timeout=15).content.replace('
    ', '').replace(' ', '')
     infostr = re.findall(r'j_shop_moreshop_more">(.+?)</div>', result_base)
     shoplist = []for item in infostr:
     scorelist = re.findall(r'">(.+?)</span><iclass="', item)
     thisShopname = re.findall(r'<span>(.+?)</span>', item)[0]
     shoplist.append('{"shopname": "' + thisShopname + '" , "dsr": "' + scorelist[0] + '", "service": "' + scorelist[1].split('">')[1] + '","ship": "' + scorelist[2].split('">')[1] + '"}')return json.dumps({"code": 0, "rows": list(set(shoplist))})except Exception, e:print ereturn json.dumps({"code": -1, "msg": "没查询到相关店铺"})if __name__ == "__main__":
     app.run(debug=True)

    HTML部分

    <!DOCTYPE html><html lang="zh-CN"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="renderer" content="webkit"><meta name="viewport" content="width=device-width, initial-scale=1"><title>Hello world</title></head><body><input type="text" name="shopname"><input type="button" value="提交" @click="query"><div class="info" v-for="item in shopes" style="border-bottom: #ccc 1px dashed"><p>店铺:{{item.shopname}}</p><p>描述相符:{{item.dsr}}<br>服务态度:{{item.service}}<br>物流服务:{{item.ship}}</p></div><script type="text/javascript" src="{{ url_for('static', filename='jquery.min.js') }}"></script><script type="text/javascript" src="{{ url_for('static', filename='vue.js') }}"></script><script type="text/javascript" src="{{ url_for('static', filename='index.js') }}"></script></body></html>

    JS部分

    没有做任何改动,就不贴出来了

    总结

    写这篇文章的目的一来是复习下flask的一些知识,二来是与web.py做个对比,再者就是给入门的朋友提供一个实战的例子,方便参考。

    声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

    文档

    flask完成一个小应用方法

    flask完成一个小应用方法:上周 @萍姐 问我如何抓取天猫上面店铺的评分,看了下挺简单的,于是花了点时间写了个Python脚本,加上web.py做成一个web服务,使用起来还不错,今天来看的时候发现当时为了方便直接用web.py开发有点简陋,自己也好久没用flask写过东西了,打算用flask再
    推荐度:
    标签: 一个 方法 应用
    • 热门焦点

    最新推荐

    猜你喜欢

    热门推荐

    专题
    Top