电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

基于Surprise協(xié)同過濾實現(xiàn)短視頻推薦方法示例

瀏覽:141日期:2022-06-13 17:04:37
目錄前言環(huán)境Surprise介紹協(xié)同過濾數(shù)據(jù)集業(yè)務介紹編碼部分1. PHP請求封裝2. PHP發(fā)起推薦獲取3. 數(shù)據(jù)集生成4. 協(xié)同過濾服務5. 基于用戶推薦6. 基于物品推薦其他寫在最后前言

前面一文介紹了通過基礎的web項目結構實現(xiàn)簡單的內(nèi)容推薦,與其說那個是推薦不如說是一個排序算法。因為熱度計算方式雖然解決了內(nèi)容的時效質(zhì)量動態(tài)化。但是相對用戶而言,大家看到的都是幾乎一致的內(nèi)容(不一樣也可能只是某時間里某視頻的排前或靠后),沒有做到個性化的千人千面。

盡管如此,基于內(nèi)容的熱度推薦依然有他獨特的應用場景——熱門榜單。所以只需要把這個功能換一個模塊就可以了,將個性化推薦留給更擅長做這方面的算法。

當然了,做推薦系統(tǒng)的方法很多,平臺層面的像spark和今天要講的Surprise。方法層面可以用深度學習做,也可以用協(xié)同過濾,或綜合一起等等。大廠可能就更完善了,在召回階段就有很多通道,比如基于卷積截幀識別視頻內(nèi)容,文本相似度計算和現(xiàn)有數(shù)據(jù)支撐,后面又經(jīng)過清洗,粗排,精排,重排等等流程,可能他們更多的是要保證平臺內(nèi)容的多樣性。

那我們這里依然走入門實際使用為主,能讓我們的項目快速對接上個性化推薦,以下就是在原因PHP項目結構上對接Surprise,實現(xiàn)用戶和物品的相似度推薦。

環(huán)境python3.8Flask2.0pandas2.0mysql-connector-python surpriseopenpyxlgunicorn Surprise介紹

Surprise庫是一款用于構建和分析推薦系統(tǒng)的工具庫,他提供了多種推薦算法,包括基線算法、鄰域方法、基于矩陣分解的算法(如SVD、PMF、SVD++、NMF)等。內(nèi)置了多種相似性度量方法,如余弦相似性、均方差(MSD)、皮爾遜相關系數(shù)等。這些相似性度量方法可以用于評估用戶之間的相似性,從而為推薦系統(tǒng)提供重要的數(shù)據(jù)支持。

協(xié)同過濾數(shù)據(jù)集

既然要基于工具庫完成協(xié)同過濾推薦,自然就需要按該庫的標準進行。Surprise也和大多數(shù)協(xié)同過濾框架類似,數(shù)據(jù)集只需要有用戶對某個物品打分分值,如果自己沒有可以在網(wǎng)上下載免費的Movielens或Jester,以下是我根據(jù)業(yè)務創(chuàng)建的表格,自行參考。

CREATE TABLE `short_video_rating` ( `id` int(11) NOT NULL AUTO_INCREMENT, `user_id` varchar(120) DEFAULT '', `item_id` int(11) DEFAULT '0', `rating` int(11) unsigned DEFAULT '0' COMMENT '評分', `scoring_set` json DEFAULT NULL COMMENT '行為集合', `create_time` int(11) DEFAULT '0', `action_day_time` int(11) DEFAULT '0' COMMENT '更新當天時間', `update_time` int(11) DEFAULT '0' COMMENT '更新時間', `delete_time` int(11) DEFAULT '0' COMMENT '刪除時間', PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=107 DEFAULT CHARSET=utf8mb4 COMMENT='用戶對視頻評分表';業(yè)務介紹

Web業(yè)務端通過接口或埋點,在用戶操作的地方根據(jù)預設的標準記錄評分記錄。當打分表有數(shù)據(jù)后,用python將SQL記錄轉為表格再導入Surprise,根據(jù)不同的算法訓練,最后根據(jù)接收的參數(shù)返回對應的推薦top列表。python部分由Flask啟動的服務,與php進行http交互,后面將以片段代碼說明。

編碼部分1. PHP請求封裝<?php/** * Created by ZERO開發(fā). * User: 北橋蘇 * Date: 2023/6/26 0026 * Time: 14:43 */namespace app\common\service;class Recommend{ private $condition; private $cfRecommends = []; private $output = []; public function __construct($flag = 1, $lastRecommendIds = [], $userId = '') {$this->condition['flag'] = $flag;$this->condition['last_recommend_ids'] = $lastRecommendIds;$this->condition['user_id'] = $userId; } public function addObserver($cfRecommend) {$this->cfRecommends[] = $cfRecommend; } public function startRecommend() {foreach ($this->cfRecommends as $cfRecommend) { $res = $cfRecommend->recommend($this->condition); $this->output = array_merge($res, $this->output);}$this->output = array_values(array_unique($this->output));return $this->output; }}abstract class cfRecommendBase{ protected $cfGatewayUrl = '127.0.0.1:6016'; protected $limit = 15; public function __construct($limit = 15) {$this->limit = $limit;$this->cfGatewayUrl = config('api.video_recommend.gateway_url'); } abstract public function recommend($condition);}class mcf extends cfRecommendBase{ public function recommend($condition) {//echo 'mcf\n';$videoIdArr = [];$flag = $condition['flag'] ?? 1;$userId = $condition['user_id'] ?? '';$url = '{$this->cfGatewayUrl}/mcf_recommend';if ($flag == 1 && $userId) { //echo 'mcf2\n'; $param['raw_uid'] = (string)$userId; $param['top_k'] = $this->limit; $list = httpRequest($url, $param, 'json'); $videoIdArr = json_decode($list, true) ?? [];}return $videoIdArr; }}class icf extends cfRecommendBase{ public function recommend($condition) {//echo 'icf\n';$videoIdArr = [];$flag = $condition['flag'] ?? 1;$userId = $condition['user_id'] ?? '';$lastRecommendIds = $condition['last_recommend_ids'] ?? [];$url = '{$this->cfGatewayUrl}/icf_recommend';if ($flag > 1 && $lastRecommendIds && $userId) { //echo 'icf2\n'; $itemId = $lastRecommendIds[0] ?? 0; $param['raw_item_id'] = $itemId; $param['top_k'] = $this->limit; $list = httpRequest($url, $param, 'json'); $videoIdArr = json_decode($list, true) ?? [];}return $videoIdArr; }}2. PHP發(fā)起推薦獲取

由于考慮到前期視頻存量不足,是采用協(xié)同過濾加熱度榜單結合的方式,前端獲取視頻推薦,接口返回視頻推薦列表的同時也帶了下次請求的標識(分頁碼)。這個分頁碼用于當協(xié)同過濾服務掛了或沒有推薦時,放在榜單列表的分頁。但是又要保證分頁數(shù)是否實際有效,所以當頁碼太大沒有數(shù)據(jù)返回就通過遞歸重置為第一頁,也把頁碼返回前端讓數(shù)據(jù)獲取更流暢。

public static function recommend($flag, $videoIds, $userId) {$nexFlag = $flag + 1;$formatterVideoList = [];try { // 協(xié)同過濾推薦 $isOpen = config('api.video_recommend.is_open'); $cfVideoIds = []; if ($isOpen == 1) {$recommend = new Recommend($flag, $videoIds, $userId);$recommend->addObserver(new mcf(15));$recommend->addObserver(new icf(15));$cfVideoIds = $recommend->startRecommend(); } // 已讀視頻 $nowTime = strtotime(date('Ymd')); $timeBefore = $nowTime - 60 * 60 * 24 * 100; $videoIdsFilter = self::getUserVideoRatingByTime($userId, $timeBefore); $cfVideoIds = array_diff($cfVideoIds, $videoIdsFilter); // 違規(guī)視頻過濾 $videoPool = []; $cfVideoIds && $videoPool = ShortVideoModel::listByOrderRaw($cfVideoIds, $flag); // 冷啟動推薦 !$videoPool && $videoPool = self::hotRank($userId, $videoIdsFilter, $flag); if ($videoPool) {list($nexFlag, $videoList) = $videoPool;$formatterVideoList = self::formatterVideoList($videoList, $userId); }} catch (\Exception $e) { $preFileName = str::snake(__FUNCTION__); $path = self::getClassName(); write_log('msg:' . $e->getMessage(), $preFileName . '_error', $path);}return [$nexFlag, $formatterVideoList]; }3. 數(shù)據(jù)集生成import osimport mysql.connectorimport datetimeimport pandas as pdnow = datetime.datetime.now()year = now.yearmonth = now.monthday = now.dayfullDate = str(year) + str(month) + str(day)dir_data = './collaborative_filtering/cf_excel'file_path = '{}/dataset_{}.xlsx'.format(dir_data, fullDate)db_config = { 'host': '127.0.0.1', 'database': 'database', 'user': 'user', 'password': 'password'}if not os.path.exists(file_path): cnx = mysql.connector.connect(user=db_config['user'], password=db_config['password'], host=db_config['host'], database=db_config['database']) df = pd.read_sql_query('SELECT user_id, item_id, rating FROM short_video_rating', cnx) print('---------------插入數(shù)據(jù)集----------------') # 將數(shù)據(jù)幀寫入Excel文件 df.to_excel(file_path, index=False)if not os.path.exists(file_path): raise IOError('Dataset file is not exists!')4. 協(xié)同過濾服務from flask import Flask, request, json, Response, abortfrom collaborative_filtering import cf_itemfrom collaborative_filtering import cf_userfrom collaborative_filtering import cf_mixfrom werkzeug.middleware.proxy_fix import ProxyFixapp = Flask(__name__)@app.route('/')def hello_world(): return abort(404)@app.route('/mcf_recommend', methods=['POST', 'GET'])def get_mcf_recommendation(): json_data = request.get_json() raw_uid = json_data.get('raw_uid') top_k = json_data.get('top_k') recommend_result = cf_mix.collaborative_fitlering(raw_uid, top_k) return Response(json.dumps(recommend_result), mimetype='application/json')@app.route('/ucf_recommend', methods=['POST', 'GET'])def get_ucf_recommendation(): json_data = request.get_json() raw_uid = json_data.get('raw_uid') top_k = json_data.get('top_k') recommend_result = cf_user.collaborative_fitlering(raw_uid, top_k) return Response(json.dumps(recommend_result), mimetype='application/json')@app.route('/icf_recommend', methods=['POST', 'GET'])def get_icf_recommendation(): json_data = request.get_json() raw_item_id = json_data.get('raw_item_id') top_k = json_data.get('top_k') recommend_result = cf_item.collaborative_fitlering(raw_item_id, top_k) return Response(json.dumps(recommend_result), mimetype='application/json')if __name__ == '__main__': app.run(host='0.0.0.0', debug=True, port=6016 )5. 基于用戶推薦# -*- coding: utf-8 -*-# @File : cf_recommendation.pyfrom __future__ import (absolute_import, division, print_function,unicode_literals)from collections import defaultdictimport osfrom surprise import Datasetfrom surprise import Readerfrom surprise import BaselineOnlyfrom surprise import KNNBasicfrom surprise import KNNBaselinefrom heapq import nlargestimport pandas as pdimport datetimeimport timedef get_top_n(predictions, n=10): top_n = defaultdict(list) for uid, iid, true_r, est, _ in predictions:top_n[uid].append((iid, est)) for uid, user_ratings in top_n.items():top_n[uid] = nlargest(n, user_ratings, key=lambda s: s[1]) return top_nclass PredictionSet(): def __init__(self, algo, trainset, user_raw_id=None, k=40):self.algo = algoself.trainset = trainsetself.k = kif user_raw_id is not None: self.r_uid = user_raw_id self.i_uid = trainset.to_inner_uid(user_raw_id) self.knn_userset = self.algo.get_neighbors(self.i_uid, self.k) user_items = set([j for (j, _) in self.trainset.ur[self.i_uid]]) self.neighbor_items = set() for nnu in self.knn_userset:for (j, _) in trainset.ur[nnu]: if j not in user_items:self.neighbor_items.add(j) def user_build_anti_testset(self, fill=None):fill = self.trainset.global_mean if fill is None else float(fill)anti_testset = []user_items = set([j for (j, _) in self.trainset.ur[self.i_uid]])anti_testset += [(self.r_uid, self.trainset.to_raw_iid(i), fill) for i in self.neighbor_items if i not in user_items]return anti_testsetdef user_build_anti_testset(trainset, user_raw_id, fill=None): fill = trainset.global_mean if fill is None else float(fill) i_uid = trainset.to_inner_uid(user_raw_id) anti_testset = [] user_items = set([j for (j, _) in trainset.ur[i_uid]]) anti_testset += [(user_raw_id, trainset.to_raw_iid(i), fill) for i in trainset.all_items() if i not in user_items] return anti_testset# ================= surprise 推薦部分 ====================def collaborative_fitlering(raw_uid, top_k): now = datetime.datetime.now() year = now.year month = now.month day = now.day fullDate = str(year) + str(month) + str(day) dir_data = './collaborative_filtering/cf_excel' file_path = '{}/dataset_{}.xlsx'.format(dir_data, fullDate) if not os.path.exists(file_path):raise IOError('Dataset file is not exists!') # 讀取數(shù)據(jù)集##################### alldata = pd.read_excel(file_path) reader = Reader(line_format='user item rating') dataset = Dataset.load_from_df(alldata, reader=reader) # 所有數(shù)據(jù)生成訓練集 trainset = dataset.build_full_trainset() # ================= BaselineOnly ================== bsl_options = {'method': 'sgd', 'learning_rate': 0.0005} algo_BaselineOnly = BaselineOnly(bsl_options=bsl_options) algo_BaselineOnly.fit(trainset) # 獲得推薦結果 rset = user_build_anti_testset(trainset, raw_uid) # 測試休眠5秒,讓客戶端超時 # time.sleep(5) # print(rset) # exit() predictions = algo_BaselineOnly.test(rset) top_n_baselineonly = get_top_n(predictions, n=5) # ================= KNNBasic ================== sim_options = {'name': 'pearson', 'user_based': True} algo_KNNBasic = KNNBasic(sim_options=sim_options) algo_KNNBasic.fit(trainset) # 獲得推薦結果 --- 只考慮 knn 用戶的 predictor = PredictionSet(algo_KNNBasic, trainset, raw_uid) knn_anti_set = predictor.user_build_anti_testset() predictions = algo_KNNBasic.test(knn_anti_set) top_n_knnbasic = get_top_n(predictions, n=top_k) # ================= KNNBaseline ================== sim_options = {'name': 'pearson_baseline', 'user_based': True} algo_KNNBaseline = KNNBaseline(sim_options=sim_options) algo_KNNBaseline.fit(trainset) # 獲得推薦結果 --- 只考慮 knn 用戶的 predictor = PredictionSet(algo_KNNBaseline, trainset, raw_uid) knn_anti_set = predictor.user_build_anti_testset() predictions = algo_KNNBaseline.test(knn_anti_set) top_n_knnbaseline = get_top_n(predictions, n=top_k) # =============== 按比例生成推薦結果 ================== recommendset = set() for results in [top_n_baselineonly, top_n_knnbasic, top_n_knnbaseline]:for key in results.keys(): for recommendations in results[key]:iid, rating = recommendationsrecommendset.add(iid) items_baselineonly = set() for key in top_n_baselineonly.keys():for recommendations in top_n_baselineonly[key]: iid, rating = recommendations items_baselineonly.add(iid) items_knnbasic = set() for key in top_n_knnbasic.keys():for recommendations in top_n_knnbasic[key]: iid, rating = recommendations items_knnbasic.add(iid) items_knnbaseline = set() for key in top_n_knnbaseline.keys():for recommendations in top_n_knnbaseline[key]: iid, rating = recommendations items_knnbaseline.add(iid) rank = dict() for recommendation in recommendset:if recommendation not in rank: rank[recommendation] = 0if recommendation in items_baselineonly: rank[recommendation] += 1if recommendation in items_knnbasic: rank[recommendation] += 1if recommendation in items_knnbaseline: rank[recommendation] += 1 max_rank = max(rank, key=lambda s: rank[s]) if max_rank == 1:return list(items_baselineonly) else:result = nlargest(top_k, rank, key=lambda s: rank[s])return list(result)# print('排名結果: {}'.format(result))6. 基于物品推薦-*- coding: utf-8 -*-from __future__ import (absolute_import, division, print_function,unicode_literals)from collections import defaultdictimport ioimport osfrom surprise import SVD, KNNBaseline, Reader, Datasetimport pandas as pdimport datetimeimport mysql.connectorimport pickle# ================= surprise 推薦部分 ====================def collaborative_fitlering(raw_item_id, top_k): now = datetime.datetime.now() year = now.year month = now.month day = now.day fullDate = str(year) + str(month) + str(day) # dir_data = './collaborative_filtering/cf_excel' dir_data = './cf_excel' file_path = '{}/dataset_{}.xlsx'.format(dir_data, fullDate) if not os.path.exists(file_path):raise IOError('Dataset file is not exists!') # 讀取數(shù)據(jù)集##################### alldata = pd.read_excel(file_path) reader = Reader(line_format='user item rating') dataset = Dataset.load_from_df(alldata, reader=reader) # 使用協(xié)同過濾必須有這行,將我們的算法運用于整個數(shù)據(jù)集,而不進行交叉驗證,構建了新的矩陣 trainset = dataset.build_full_trainset() # print(pd.DataFrame(list(trainset.global_mean()))) # exit() # 度量準則:pearson距離,協(xié)同過濾:基于item sim_options = {'name': 'pearson_baseline', 'user_based': False} algo = KNNBaseline(sim_options=sim_options) algo.fit(trainset) # 將訓練好的模型序列化到磁盤上 # with open('./cf_models/cf_item_model.pkl', 'wb') as f: # pickle.dump(algo, f) #從磁盤中讀取訓練好的模型 # with open('cf_item_model.pkl', 'rb') as f: # algo = pickle.load(f) # 轉換為內(nèi)部id toy_story_inner_id = algo.trainset.to_inner_iid(raw_item_id) # 根據(jù)內(nèi)部id找到最近的10個鄰居 toy_story_neighbors = algo.get_neighbors(toy_story_inner_id, k=top_k) # 將10個鄰居的內(nèi)部id轉換為item id也就是raw toy_story_neighbors_rids = (algo.trainset.to_raw_iid(inner_id) for inner_id in toy_story_neighbors) result = list(toy_story_neighbors_rids) return result # print(list(toy_story_neighbors_rids))if __name__ == '__main__': res = collaborative_fitlering(15, 20) print(res)其他

推薦服務生產(chǎn)部署開發(fā)環(huán)境下可以通過python recommend_service.py啟動,后面部署環(huán)境需要用到gunicorn,方式是安裝后配置環(huán)境變量。代碼里導入werkzeug.middleware.proxy_fix, 修改以下的啟動部分以下內(nèi)容,啟動改為gunicorn -w 5 -b 0.0.0.0:6016 app:appapp.wsgi_app = ProxyFix(app.wsgi_app)app.run()

模型本地保存隨著業(yè)務數(shù)據(jù)的累計,自然需要訓練的數(shù)據(jù)集也越來越大,所以后期關于模型訓練周期,可以縮短。也就是定時訓練模型后保存到本地,然后根據(jù)線上的數(shù)據(jù)做出推薦,模型存儲與讀取方法如下。2.1. 模型存儲

sim_options = {'name': 'pearson_baseline', 'user_based': False} algo = KNNBaseline(sim_options=sim_options) algo.fit(trainset) # 將訓練好的模型序列化到磁盤上 with open('./cf_models/cf_item_model.pkl', 'wb') as f: pickle.dump(algo, f)

2.2. 模型讀取

with open('cf_item_model.pkl', 'rb') as f:algo = pickle.load(f) # 轉換為內(nèi)部id toy_story_inner_id = algo.trainset.to_inner_iid(raw_item_id) # 根據(jù)內(nèi)部id找到最近的10個鄰居 toy_story_neighbors = algo.get_neighbors(toy_story_inner_id, k=top_k) # 將10個鄰居的內(nèi)部id轉換為item id也就是raw toy_story_neighbors_rids = (algo.trainset.to_raw_iid(inner_id) for inner_id in toy_story_neighbors) result = list(toy_story_neighbors_rids) return result寫在最后

上面的依然只是實現(xiàn)了推薦系統(tǒng)的一小部分,在做數(shù)據(jù)召回不管可以對視頻截幀還可以分離音頻,通過卷積神經(jīng)網(wǎng)絡識別音頻種類和視頻大致內(nèi)容。再根據(jù)用戶以往瀏覽記錄形成的標簽實現(xiàn)內(nèi)容匹配等等,這個還要后期不斷學習和完善的。?

以上就是基于Surprise協(xié)同過濾實現(xiàn)短視頻推薦方法示例的詳細內(nèi)容,更多關于Surprise短視頻推薦的資料請關注好吧啦網(wǎng)其它相關文章!

標簽: PHP
主站蜘蛛池模板: 深圳市宏康仪器科技有限公司-模拟高空低压试验箱-高温防爆试验箱-温控短路试验箱【官网】 | 讲师宝经纪-专业培训机构师资供应商_培训机构找讲师、培训师、讲师经纪就上讲师宝经纪 | 蜘蛛车-高空作业平台-升降机-高空作业车租赁-臂式伸缩臂叉装车-登高车出租厂家 - 普雷斯特机械设备(北京)有限公司 | 有源电力滤波装置-电力有源滤波器-低压穿排电流互感器|安科瑞 | 上海物流公司,上海货运公司,上海物流专线-优骐物流公司 | 深圳市宏康仪器科技有限公司-模拟高空低压试验箱-高温防爆试验箱-温控短路试验箱【官网】 | 恒温恒湿试验箱_高低温试验箱_恒温恒湿箱-东莞市高天试验设备有限公司 | 常州减速机_减速机厂家_常州市减速机厂有限公司 | 不锈钢螺丝,不锈钢螺栓,不锈钢标准件-江苏百德特种合金有限公司 交变/复合盐雾试验箱-高低温冲击试验箱_安奈设备产品供应杭州/江苏南京/安徽马鞍山合肥等全国各地 | 粉末包装机-给袋式包装机-全自动包装机-颗粒-液体-食品-酱腌菜包装机生产线【润立机械】 | 电缆接头_防水接头_电缆防水接头_防水电缆接头_上海闵彬 | 全自动不干胶贴标机_套标机-上海今昂贴标机生产厂家 | 皮带机_移动皮带机_大倾角皮带机_皮带机厂家 - 新乡市国盛机械设备有限公司 | PC构件-PC预制构件-构件设计-建筑预制构件-PC构件厂-锦萧新材料科技(浙江)股份有限公司 | 气动|电动调节阀|球阀|蝶阀-自力式调节阀-上海渠工阀门管道工程有限公司 | 球磨机 选矿球磨机 棒磨机 浮选机 分级机 选矿设备厂家 | 杜甫仪器官网|实验室平行反应器|升降水浴锅|台式低温循环泵 | 天津暖气片厂家_钢制散热器_天津铜铝复合暖气片_维尼罗散热器 | 缓蚀除垢剂_循环水阻垢剂_反渗透锅炉阻垢剂_有机硫化物-郑州威大水处理材料有限公司 | 济南品牌设计-济南品牌策划-即合品牌策划设计-山东即合官网 | 喷砂机厂家_自动喷砂机生产_新瑞自动化喷砂除锈设备 | 二维运动混料机,加热型混料机,干粉混料机-南京腾阳干燥设备厂 | 成都离婚律师|成都结婚律师|成都离婚财产分割律师|成都律师-成都离婚律师网 | 根系分析仪,大米外观品质检测仪,考种仪,藻类鉴定计数仪,叶面积仪,菌落计数仪,抑菌圈测量仪,抗生素效价测定仪,植物表型仪,冠层分析仪-杭州万深检测仪器网 | 防爆暖风机_防爆电暖器_防爆电暖风机_防爆电热油汀_南阳市中通智能科技集团有限公司 | 合肥礼品公司-合肥礼品定制-商务礼品定制公司-安徽柏榽商贸有限公司 | 便携式XPDM露点仪-在线式防爆露点仪-增强型烟气分析仪-约克仪器 冰雕-冰雪世界-大型冰雕展制作公司-赛北冰雕官网 | 搜活动房网—活动房_集装箱活动房_集成房屋_活动房屋 | 运动木地板价格,篮球馆体育运动木地板生产厂家_欧氏地板 | 五轴加工中心_数控加工中心_铝型材加工中心-罗威斯 | 收录网| 直读光谱仪,光谱分析仪,手持式光谱仪,碳硫分析仪,创想仪器官网 | 振动筛,震动筛,圆形振动筛,振动筛价格,振动筛厂家-新乡巨宝机电 蒸汽热收缩机_蒸汽发生器_塑封机_包膜机_封切收缩机_热收缩包装机_真空机_全自动打包机_捆扎机_封箱机-东莞市中堡智能科技有限公司 | 网站建设-高端品牌网站设计制作一站式定制_杭州APP/微信小程序开发运营-鼎易科技 | 工业车间焊接-整体|集中除尘设备-激光|等离子切割机配套除尘-粉尘烟尘净化治理厂家-山东美蓝环保科技有限公司 | 鲁尔圆锥接头多功能测试仪-留置针测试仪-上海威夏环保科技有限公司 | 山东风淋室_201/304不锈钢风淋室净化设备厂家-盛之源风淋室厂家 翻斗式矿车|固定式矿车|曲轨侧卸式矿车|梭式矿车|矿车配件-山东卓力矿车生产厂家 | 高防护蠕动泵-多通道灌装系统-高防护蠕动泵-www.bjhuiyufluid.com慧宇伟业(北京)流体设备有限公司 | 烟台游艇培训,威海游艇培训-烟台市邮轮游艇行业协会 | 上海租车公司_上海包车_奔驰租赁_上海商务租车_上海谐焕租车 | 福尔卡(北京)新型材料技术股份有限公司 |