个人主页:个人主页
推荐专栏:小程序开发成神之路 --【这是一个为想要入门和进阶小程序开发专门开启的精品专栏
!从个人到商业的全套开发教程
,实打实的干货分享,确定不来看看? 】
作者简介:从web开发,再到大数据算法,踩过了无数的坑,用心总结经验教训,助你在技术生涯一臂之力!若想获取更多精彩内容,敬请订阅专栏或者关注
⭐️您的小小关注是我持续输出的动力!
⭐️
入门和进阶小程序开发,不可错误的精彩内容 :
- 《微信小程序 | 动手实现双十一红包雨》
- 《来接私活吧?小程序接私活必备功能-婚恋交友【附完整代码】》
最近ChatGPT
火遍全球,把AI
再次推上了高潮。两个月用户就破亿现象,就足以说明这大家对人工智能融入生活的趋势的迫切期待!
国内,作为BAT中的一员的百度,错过了移动互联网时代的浪潮,全身精力投入与AI。这次特意来体会一下百度深耕多年的AI产品的效果究竟能做到什么程度。首先,我们先来感受一下百度的图像识别的能力。为了让这个能力更加具体的表象出来,这次我们要做的是一款结合百度图片识别能力的车辆报价智能识别小程序
!
为什么会有这样的想法呢?在我们的日常生活中,车是越来越多了,现在买车就像以前买摩托车甚至是买自行车那样普及了。都是四个轮子加一个棚子,除了出行的需求,车也是一种身份的象征!所以,我们这次来做一个可以通过拍照就可以一秒钟识别车辆的价钱的神器!看看是谁在裸泳,带你发现身边的土豪!
要实现本文中的图片识别功能,主要有两方面的技术难点:
(1)我们要使用合适的系统api,使得用户可以从手机端拍摄照片或者选择相册中的照片上传。
(2)对于用户选择好的图片数据,我们要对其进行编码设计,将其设置到请求体中。
这里的技术栈我们使用:
vue语法
+uni-app框架
。
- 为什么不使用原生语法?
- 使用微信的原生语法,我们开发出来的程序只能运行在微信平台,如果有一天我们想要迁移到别的平台,我们又要重新按照新平台的语法规则进行重新开发!可复用性基本为零!
- 不会
vue
?不用担心!应为微信的原生语法就是基于vue
语法的基础上进行封装的而已!只要你会原生开发,上手难度基本为零!如果还是觉得有困难,欢迎阅读本号分享的"vue相关知识",为你上手干活保驾护航!
说到后端服务,这可是这个项目的重头戏了!
综合以上说的两点,我们可以很明确的知道:一个web容器用来接收数据以及一个爬虫用来查找数据。这需求就变得极其明确了!
那么问题来了:什么语言可以快准狠地实现并且融合这两点呢?毫无疑问,果断选择
Python大法
!
Flask框架
搭配request爬虫
---- 直接拿下全场!
百度AI的平台现在越来越完善了,他将大量的ai技术都封装出来做了产品化。所以,我们只需要登录 百度智能云官网,用自己的百度账号开通相应的ai产品即可。
关于小程序的开发环境搭建,也就是分为两个方面:
nodejs环境的搭建
这个步骤是老生常谈的问题了,无非就是那么几步:
下载node
–配置环境变量
–测试效果
这一系列的问题基本百度一下都能解决了,但是值得一提的就是,对于那些从windows系统切换到mac系统的用户来说,配置开发环境也是一个不小的挑战。苹果作为生产力神器,建议看一下我整理的: 。让你纵享丝滑!
开发工具的安装和联调
在确定了使用
uniapp框架
的基础上,我们可以好不犹豫的选择HBuilderX
工具作为我们的开发环境。详细可见:
这一块没啥说的,直接上代码:
<template>
<view class="content">
<text class="slogan">拍照、上传你想了解的汽车text>
<image class="image" :src="imageSrc" mode="widthFix">image>
<button type="default" class="getBtn" @tap="upload">选择图片button>
<view class="text-area">
<text class="title">1text>
<text class="title">2text>
<text class="title">3text>
view>
<view class="text-area">
<text class="title">选择图片text>
<text class="title">AI智能识别text>
<text class="title">获取报价text>
view>
<wyb-popup ref="popup" type="bottom" height="400" width="500" radius="6" :showCloseIcon="true">
<view class="popup-content">
<hm-cover-card :options="options">hm-cover-card>
view>
wyb-popup>
view>
template>
这里有两个要点,也是我们在前端开发中经常遇到的问题:
uni.request()
方法!在这个项目中,我们很清楚,我们需要传输的数据中肯定包含了图片。而图片数据的传输往往是以二进制流的数据形式进行传输,所以我们在数据传输的时候都是将数据的请求类型设置为application/x-www-form-urlencode
。很不幸uni.request()
方法并不支持该数据格式的传输,所这个时候我们果断翻阅官方文档,经过一番寻找与思考,可以发现:我们可以直接使用uni.uploadFile()
方法直接将图片设置为参数即可。
process(image) {
var imgObj = {'image': image}
return uni.uploadFile({
url: '/api/upload',
filePath: image,
fileType: 'image',
name: 'image'
});
}
upload() {
let _this = this;
uni.chooseImage({
count: 1, //默认9
sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
sourceType: ['album'], //从相册选择
success: function(res) {
uni.showLoading({
title: "AI努力生成中"
})
var result = process(res.tempFilePaths[0])
uni.getImageInfo({
src: res.tempFilePaths[0],
success: (path) => {
pathToBase64(path.path).then(base64 => {
_this.imageSrc = base64
_this.options.entryPic = base64
})
.catch(err => {
console.error(err);
})
}
})
result.then((res)=>{
console.log('--result--',JSON.parse(res[1].data))
uni.hideLoading();
_this.options.title = JSON.parse(res[1].data).name[0]
_this.options.text = JSON.parse(res[1].data).price[0]
_this.$refs.popup.show() // 显示
})
}
});
},
针对前后端分离的项目而言,抛开实现语言的差异,前端是一个服务,后端又是另外的一个服务。按照浏览器的请求规则,从前端发出的请求数据往往存在需要处理的跨域请求的问题。就像现在这个服务所发生的情况一样,前端的运行地址是:localhost:81
,服务端的运行地址是:localhost:8099
,尽管两端的域名一致,但是端口并不一致,按照跨域请求的规则,就需要处理这个跨域请求的限制问题。
一般处理跨域请求通常有两种方式(这两种方式的选择需要依赖于特定的业务场景来自我判断):
- 前端处理:为前端所发出的请求设置代理,让所有的请求都通过前端代理转发,从而避免跨域的问题。【这种方法适用于后端服务地址我们无法修改的情况(如接入什么第三方地址、后端服务已部署好的情况)】
- 后端处理:后端处理的原理是在前端过来的请求头中将跨域限制的k-v字段设置成允许即可【这种也特别常用,通常在全局添加一个过滤器用于过滤相应请求的请求头即可】。
本项目使用的是前端设置代理的方法,对于vue项目来说,可直接在manifest.json
文件中设置如下配置:
"port" : 80,
"disableHostCheck" : true,
"proxy" : {
"/api" : {
"target" : "http://127.0.0.1:8099",
"changeOrigin" : true,
"secure" : false,
"pathRewrite":{"^/api":""}
},
"/data" : {
"target" : "https://www.autohome.com.cn/grade/carhtml",
"changeOrigin" : true,
"secure" : false,
"pathRewrite":{"^/data":""}
}
}
在本项目中,对于后台接口的编写方面,选择的是Python
语言,框架使用的是python的轻量级框架Flask
.
那么问题来了:对于熟悉前后端开发的小伙伴来说,为什么后端没有选择主流的
Java
然后搭配SpringBoot
框架呢?
- 就本项目的功能接口来说,主要的功能就只是围绕在:
- 前端图片数据的接收
- 获取百度AI接口返回数据
- 根据百度云获取到的识别结果去车库动态查询到目标车辆的报价信息
- 按照前两点的功能来说,用
SpringBoot
框架直接代码生成一下分分钟就搞完了!但是对于第三点功能,就需要想办法如何获取到实时的、完整的车辆信息。这个也是本项目的难点和重头戏! 所以,对于这个需求,可以毫不犹豫地选择爬虫。而Python
对于爬虫的实现终究还是比Java
来的更快、更准、更狠!- 所以我们需要一个可以集成这个爬虫功能的后台接口程序,于是乎我们自然而然的就选择到了
Flask
web框架。通过Flask
来写接收请求,然后再通过Request
爬虫获取车辆报价信息。
from flask import Flask, jsonify, request
import re,os
from aip import AipImageClassify
import RecognizeCar.CrawleCarHome as carhome
from difflib import SequenceMatcher
basedir = os.path.abspath(os.path.dirname(__file__)) # 定义一个根目录 用于保存图片用
""" 你的 APPID AK SK """
APP_ID = '填入你的账号信息'
API_KEY = '填入你的账号信息'
SECRET_KEY = '填入你的账号信息'
client = AipImageClassify(APP_ID, API_KEY, SECRET_KEY)
app = Flask(__name__)
# 使通过jsonify返回的中文显示正常,否则显示为ASCII码
app.config["JSON_AS_ASCII"] = False
@app.route('/upload', methods=['GET', 'POST'])
def editorData():
# 获取图片文件 name = upload
img = request.files.get('image')
# 定义一个图片存放的位置 存放在static下面
path = basedir + "\\"
# 图片名称
imgName = img.filename
# 图片path和名称组成图片的保存路径
file_path = path + imgName
# 保存图片
img.save(file_path)
""" 读取图片 """
def get_file_content(filePath):
with open(filePath, 'rb') as fp:
return fp.read()
image = get_file_content(file_path)
""" 调用车辆识别 """
result = client.carDetect(image)
print(result['result'][0]['name'])
print(result['result'][0]['name'].replace('_',''))
recognized_name = result['result'][0]['name'].replace('_','')
print(single_get_first(result['result'][0]['name'].replace('_','')))
car_list = carhome.doSpider(single_get_first(result['result'][0]['name'].replace('_','')))
print(car_list)
for item in car_list:
# print(item['name'][0])
similarity_ratio = SequenceMatcher(None, recognized_name, item['name'][0]).ratio()
if similarity_ratio > 0.7 :
print(item)
return item
return result
def single_get_first(unicode1):
str1 = unicode1.encode('gbk')
try:
ord(str1)
return str1.decode('gbk')
except:
asc = str1[0] * 256 + str1[1] - 65536
if asc >= -20319 and asc <= -20284:
return 'A'
if asc >= -20283 and asc <= -19776:
return 'B'
if asc >= -19775 and asc <= -19219:
return 'C'
if asc >= -19218 and asc <= -18711:
return 'D'
if asc >= -18710 and asc <= -18527:
return 'E'
if asc >= -18526 and asc <= -18240:
return 'F'
if asc >= -18239 and asc <= -17923:
return 'G'
if asc >= -17922 and asc <= -17418:
return 'H'
if asc >= -17417 and asc <= -16475:
return 'J'
if asc >= -16474 and asc <= -16213:
return 'K'
if asc >= -16212 and asc <= -15641:
return 'L'
if asc >= -15640 and asc <= -15166:
return 'M'
if asc >= -15165 and asc <= -14923:
return 'N'
if asc >= -14922 and asc <= -14915:
return 'O'
if asc >= -14914 and asc <= -14631:
return 'P'
if asc >= -14630 and asc <= -14150:
return 'Q'
if asc >= -14149 and asc <= -14091:
return 'R'
if asc >= -14090 and asc <= -13119:
return 'S'
if asc >= -13118 and asc <= -12839:
return 'T'
if asc >= -12838 and asc <= -12557:
return 'W'
if asc >= -12556 and asc <= -11848:
return 'X'
if asc >= -11847 and asc <= -11056:
return 'Y'
if asc >= -11055 and asc <= -10247:
return 'Z'
return ''
if __name__ == '__main__':
app.run(host="0.0.0.0", port=int("8099"), debug=True)
import requests,json,re
import pandas as pd
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column
from sqlalchemy.types import Integer,String,Date,DateTime,Float,Text
from lxml import etree
import time
from difflib import SequenceMatcher
def doSpider(first_tag):
url = 'https://www.autohome.com.cn/grade/carhtml/{0}.html'.format(first_tag)
resp = requests.get(url)
# html文档
resp = requests.get(url, headers={
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.26 Safari/537.36 Core/1.63.6776.400 QQBrowser/10.3.2601.400',
})
# resp.encoding = 'utf-8'
rest = resp.text
html = etree.HTML(rest)
list = html.xpath('//dd/ul[@class="rank-list-ul"]')
result = []
for item in list:
for el in item:
name = el.xpath('./h4/a/text()')
price = el.xpath('./div/a[@class="red"]/text()')
if len(name) > 0:
result.append({'name':name,'price':price})
return result
#
# if __name__ == '__main__':
# run()
AppId
,SecrectId
,ApiId
登录到百度智能云平台,然后选择人工智能产品中的图像识别模块。
图像识别 Python SDK目录结构
├── README.md
├── aip //SDK目录
│ ├── __init__.py //导出类
│ ├── base.py //aip基类
│ ├── http.py //http请求
│ └── imageclassify.py //图像识别
└── setup.py //setuptools安装
支持Python版本:2.7.+ ,3.+
安装使用Python SDK有如下方式:
pip install baidu-aip
即可。python setup.py install
即可。