<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                ## 發布前臺 首先,我們看一下點點的發布界面 ![2015-06-14/557d43946f503](http://box.kancloud.cn/2015-06-14_557d43946f503.png) 基本上他的發布框都是左右結構,左邊主要內容,右邊輔助字段。 主要有3個組件:文本編輯器、標簽、日期選擇器。 ### 文本編輯器 經過我的研究是ueditor。 ![2015-06-14/557d44d0b4bf4](http://box.kancloud.cn/2015-06-14_557d44d0b4bf4.png) 看console,里編輯器按鈕的圖片資源目錄。那么我們也用ueditor。 本人比較喜歡這個編輯器,因為他提供了下圖我看中的三個功能: ![2015-06-14/557d45b3d76a9](http://box.kancloud.cn/2015-06-14_557d45b3d76a9.png) 當然這需要我們去整合到應用里。 這對于新手有點難度,幸好我找到了一個完美的輪子:[Ueditor-thinkphp](https://github.com/Nintendov/Ueditor-thinkphp) ![2015-06-14/557d471050fb6](http://box.kancloud.cn/2015-06-14_557d471050fb6.png) 我就下載了他的資源文件,將編輯器本身放入Public/static/ueditor里。 ![2015-06-14/557d47eab7911](http://box.kancloud.cn/2015-06-14_557d47eab7911.png) 公共項目配置里放上他的配置。 然后UploadController里寫上他的 ueditor方法: ![2015-06-14/557d4820f3702](http://box.kancloud.cn/2015-06-14_557d4820f3702.png) 然后文本編輯器的模板部分,因為不同文章發布的類型要多次使用到編輯器,我就提取成了模板: ![2015-06-14/557d48ca92ec2](http://box.kancloud.cn/2015-06-14_557d48ca92ec2.png) base/editor.html 表單名和表單值讀取了模板引入include的的屬性`form_name`和`form_value`。 并且精簡了按鈕做到和點點的一致。 至于編輯器里的上傳,后面“文件上傳”會講。 ### 標簽 找了許多標簽庫插件,最后還是發現之前自己OneBlog里的 [jquery.tagsinput](https://github.com/xoxco/jQuery-Tags-Input) 好用一些。 bower安裝,引入資源,表單隱藏提交,js代碼區里 ~~~ <div class="form-group"> <textarea name="tags" id="tags" placeholder="添加標簽,用逗號或回車分割" class="form-control hide-data" style="height:90px"></textarea> </div> ~~~ ~~~ //標簽 $('#tags').tagsInput({ 'height':'90px', 'width':'182px', 'defaultText': '添加標簽' }); ~~~ 最后美化一下,就搞定了: ![2015-06-14/557d4bc742035](http://box.kancloud.cn/2015-06-14_557d4bc742035.png) 輸入標簽詞后回車添加上標簽。 ### 日期選擇器 點點可以定時發布,發布時間下拉里選擇定時發布: ![2015-06-14/557d4cac10360](http://box.kancloud.cn/2015-06-14_557d4cac10360.png) 會顯示一個日期+小時+分鐘的 輸入控件: ![2015-06-14/557d4cde02291](http://box.kancloud.cn/2015-06-14_557d4cde02291.png) 由于bootstrap默認沒有日期時間選擇器,我就去找了一個 [bootstrap-datetimepicker](http://www.malot.fr/bootstrap-datetimepicker/) 引入資源后, 先是默認隱藏的表單 ~~~ <div class="form-group input-group hidden"> <input type="datetime" name="deadline" class="form-control hide-data" id="deadline"> <span class="input-group-addon glyphicon glyphicon-calendar" aria-hidden="true" style="top:0;"></span> </div> ~~~ 然后js代碼: ~~~ //發布時間切換 $('#create_time_choose').on('change', function(){ var choosen = this.value; if('choose' == choosen) $('#deadline').parent().removeClass('hidden'); else $('#deadline').parent().addClass('hidden'); }); //定時使用支持 日期 小時 分鐘選擇 $('#deadline').datetimepicker({ format: 'yyyy-mm-dd hh:ii', autoclose: true, language: 'zh-CN' }); ~~~ 這樣,實現了和點點差不多的定時發布字段控件: ![2015-06-14/557d4e9d56263](http://box.kancloud.cn/2015-06-14_557d4e9d56263.png) ![2015-06-14/557d4eb5a0f1a](http://box.kancloud.cn/2015-06-14_557d4eb5a0f1a.png) ## 整體代碼 ### 前臺模板目錄 ![2015-06-14/557d50902eaf9](http://box.kancloud.cn/2015-06-14_557d50902eaf9.png) 前臺主要分為 列表頁、詳情頁、發布頁及用戶個人中心頁。 列表頁主要就是Index目錄下的,base 及其各種子詳情頁。 紅框中的editor是我嘗試之前ueditor的demo寫的demo頁。 然后詳情頁是Detail目錄下的。 發布頁是Post目錄下的base 及其發布類型對應的子模板繼承頁。 ### 模板繼承 觀察了Bootstrap的博客案列,整體來說左右結構,發布頁面變的是左邊。 所以我寫了個base.html 供繼承使用: ~~~ <html> <head> <meta charset="UTF-8"> <title>Freelog - 自由的輕博客</title> <script src="__BOWER__/jquery/dist/jquery.min.js"></script> <script src="__BOWER__/bootstrap/dist/js/bootstrap.min.js"></script> <link href="__BOWER__/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet"> <block name="style"></block> <link rel="stylesheet" href="__CSS__/blog.css"> <script type="text/javascript"> var is_login = '{:is_login()}'; </script> <script type="text/javascript" src="__JS__/common.js"></script> <script type="text/javascript"> // var url = window.location.pathname + window.location.search; // url = url.replace(/(\/(p)\/\d+)|(&p=\d+)|(\/(id)\/\d+)|(&id=\d+)|(\/(group)\/\d+)|(&group=\d+)/, ""); var url = '__SELF__'; var no_pic = '__PUBLIC__/images/no-cover.png'; (function(){ var ThinkPHP = window.Think = { "ROOT" : "__ROOT__", //當前網站地址 "APP" : "__APP__", //當前項目地址 "PUBLIC" : "__PUBLIC__", //項目公共目錄地址 "DEEP" : "{:C('URL_PATHINFO_DEPR')}", //PATHINFO分割符 "MODEL" : ["{:C('URL_MODEL')}", "{:C('URL_CASE_INSENSITIVE')}", "{:C('URL_HTML_SUFFIX')}"], "VAR" : ["{:C('VAR_MODULE')}", "{:C('VAR_CONTROLLER')}", "{:C('VAR_ACTION')}"] } })(); $(function(){ //單頁高亮 $('.navbar-nav li').removeClass('active'); $('a.blog-nav-item[href="'+url+'"]').parent().addClass('active'); }) </script> <link rel="stylesheet" href="__BOWER__/smalot-bootstrap-datetimepicker/css/bootstrap-datetimepicker.min.css"> <script type="text/javascript" src="__BOWER__/smalot-bootstrap-datetimepicker/js/bootstrap-datetimepicker.min.js"></script> <script type="text/javascript" src="__BOWER__/smalot-bootstrap-datetimepicker/js/locales/bootstrap-datetimepicker.zh-CN.js"></script> <link rel="stylesheet" href="__BOWER__/jqnotifybar/css/jquery.notifyBar.css"> <script type="text/javascript" src="__BOWER__/jqnotifybar/jquery.notifyBar.js"></script> <script src="__BOWER__/jquery.tagsinput/jquery.tagsinput.js"></script> <link rel="stylesheet" href="__BOWER__/jquery.tagsinput/jquery.tagsinput.css" /> <script type="text/javascript" src="__STATIC__/ueditor/ueditor.config.js"></script> <!-- 編輯器源碼文件 --> <script type="text/javascript" src="__STATIC__/ueditor/ueditor.all.js"></script> <!-- 實例化編輯器 --> <!-- Your site ends --> </head> <body> <div class="navbar navbar-inverse navbar-fixed-top blog-masthead"> <div class="container"> <div class="navbar-header"> <button class="navbar-toggle collapsed" type="button" data-toggle="collapse" data-target=".navbar-collapse"> <span class="sr-only">Toggle navigation</span> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" href="javascript:;">Freelog</a> </div> <div class="blog-nav collapse navbar-collapse" id="example-navbar-collapse"> <ul class="nav navbar-nav"> <li><a class="blog-nav-item" href="{:U('/')}">首頁</a></li> <?php if (is_login()): ?> <li><a class="blog-nav-item" href="{:U('/mine/')}">我的文章</a></li> <?php endif ?> <li> <form class="navbar-form navbar-right" id="search" method="GET" action="/Search" role="search"> <div class="form-group input-group"> <input type="text" name="kw" class="form-control" placeholder="輸入關鍵字搜索" value="{$kw|default=""}"> <span class="input-group-btn"> <button class="btn btn-default"> <span class="glyphicon glyphicon-search f20" aria-hidden="true"></span> </button> </span> </div> </form> </li> </ul> <ul class="nav navbar-nav navbar-right"> <li><a href="javascript:;" role="button" aria-expanded="false"><if condition="is_login()">{:session('user.nickname')}</if></a></li> <if condition="is_login()"> <li><a class="blog-nav-item" href="{:U('/user/profile')}">個人信息</a></li> <li><a class="blog-nav-item" href="{:U('/user/logout')}" class="ajax-get">退出</a></li> <else/> <li><a class="blog-nav-item" href="{:U('/user/login')}">登錄</a></li> <li><a class="blog-nav-item" href="{:U('/user/reg')}">注冊</a></li> </if> </ul> </div> </div> </div> <div class="container" id="main"> <block name="header"></block> <div class="row"> <form class="post"> <div class="col-sm-8 blog-main"> <block name="main"></block> </div><!-- /.blog-main --> <div class="col-sm-3 col-sm-offset-1 blog-sidebar"> <block name="sidebar"> <include file="Index/post_btn" /> <div class="sidebar-module sidebar-module-inset"> <h4>選項</h4> <div class="form-group"> <label for="title">發布時間</label> <select name="create_time_choose" class="form-control hide-data" id="create_time_choose"> <option value="now">現在發布</option> <option value="choose">定時發布</option> </select> </div> <div class="form-group input-group hidden"> <input type="datetime" name="deadline" class="form-control hide-data" id="deadline"> <span class="input-group-addon glyphicon glyphicon-calendar" aria-hidden="true" style="top:0;"></span> </div> <div class="form-group"> <textarea name="tags" id="tags" placeholder="添加標簽,用逗號或回車分割" class="form-control hide-data" style="height:90px"></textarea> </div> </div> <script type="text/javascript"> $(function(){ //發布時間切換 $('#create_time_choose').on('change', function(){ var choosen = this.value; if('choose' == choosen) $('#deadline').parent().removeClass('hidden'); else $('#deadline').parent().addClass('hidden'); }); //定時使用支持 日期 小時 分鐘選擇 $('#deadline').datetimepicker({ format: 'yyyy-mm-dd hh:ii', autoclose: true, language: 'zh-CN' }); //標簽 $('#tags').tagsInput({ 'height':'90px', 'width':'182px', 'defaultText': '添加標簽' }); }) </script> </block> </div><!-- /.blog-sidebar --> </form> </div><!-- /.row --> </div><!-- /.container --> <footer class="blog-footer"> <p>Blog template built for <a href="http://getbootstrap.com">Bootstrap</a> by <a href="https://twitter.com/mdo">@mdo</a>.Modified by <a href="http://weibo.com/u/1342658313">@黑白世界4648</a></p> <p>? {:date('Y', time())} Freelog. 由 Thinkphp 強力驅動.</p> <p> <a href="#">Back to top</a> </p> </footer> <block name="script"></block> </body> </html> ~~~ ### 模板包含 由于模板繼承里的每個block只是結構上的替換,一些組件級的html代碼和js。還是封裝成小html片段模板,用include 標簽復用才好。 像文字類發布頁、圖片發布頁和其他發布頁,文本編輯器都有,只不過文字類發布頁的內容字段,就和其他類型發布頁的描述字段一樣是文本編輯器,只不過字段名變了。 在text.html 中: `<include file="Post/editor" form_name="content" form_value="" height="286" />` 一句話就完成了文本編輯器的引入。父模板里引入編輯器資源,因為都要用到,封裝js 部分就好了。用include屬性傳參。是不是和最近熱門概念web component 類似,TP早就有了。 ### 整體代碼 文字頁發布Post/text.html的代碼如下: ~~~ <extend name="Post/base" /> <block name="header"> <div class="blog-header"> <h1 class="blog-title">發布文字</h1> </div> </block> <block name="main"> <div class="blog-post" id="text"> <div class="form-group"> <label for="title">標題 <span class="optional">(可不填)</span></label> <input type="text" class="form-control hide-data" id="title" name="title"> </div> <div class="form-group"> <label for="content">內容</label> <include file="Post/editor" form_name="content" form_value="" height="286" /> </div> <div class="form-group"> <input type="hidden" name="type" value="{$type}" class="hide-data"> <input type="hidden" name="member_id" value="{:is_login()}" class="hide-data"> <a class="btn btn-default pull-left" href="{:U('/')}">取消</a> <button type="button" class="btn btn-primary pull-right ajax-post no-refresh" hide-data="true" target-form="post" href="/api.php/post">保存</button> </div> </div><!-- /.blog-post --> <script type="text/javascript"> $(function(){ }) </script> </block> <block name="script"> </block> ~~~ 這時候,整個文字類發布文章頁面的效果就出來了: ![2015-06-14/557d97a6e0a2e](http://box.kancloud.cn/2015-06-14_557d97a6e0a2e.png) 怎么樣和點點很像吧。 ### 等等,還有ajax 在頁面的父模板里,我們只看到一個form標簽,沒有action,也沒有type,卻你那提交數據,表單怎么提交的呢? 別急,我們看看Public里的common.js里有這么一段: ~~~ //ajax post submit請求 $('.ajax-post').on('click', function(){ var target,query,form; var target_form = $(this).attr('target-form'); var that = this; var nead_confirm = false; if( ($(this).attr('type')=='submit') || (target = $(this).attr('href')) || (target = $(this).attr('url')) ){ form = $('.'+target_form); if(form.lenght < 1 ) alert('表單選擇不正確'); if ($(this).attr('hide-data') === 'true'){//無數據時也可以使用的功能 form = $('.hide-data'); query = form.serialize(); }else if (form.get(0)==undefined){ return false; }else if ( form.get(0).nodeName=='FORM' ){ if ( $(this).hasClass('confirm') ) { if(!confirm('確認要執行該操作嗎?')){ return false; } } if($(this).attr('url') !== undefined){ target = $(this).attr('url'); }else{ target = form.get(0).action; } query = form.serialize(); }else if( form.get(0).nodeName=='INPUT' || form.get(0).nodeName=='SELECT' || form.get(0).nodeName=='TEXTAREA') { form.each(function(k,v){ if(v.type=='checkbox' && v.checked==true){ nead_confirm = true; } }) if ( nead_confirm && $(this).hasClass('confirm') ) { if(!confirm('確認要執行該操作嗎?')){ return false; } } query = form.serialize(); }else{ if ( $(this).hasClass('confirm') ) { if(!confirm('確認要執行該操作嗎?')){ return false; } } query = form.find('input,select,textarea').serialize(); } $(that).addClass('disabled').attr('autocomplete','off').prop('disabled',true); $.post(target,query).success(function(data){ if (data.code >= 200 && data.code < 400) { console.log(data); console.log('success'); if (data.url) { notify(data.info + ' 頁面即將自動跳轉~','success'); }else{ notify(data.info ,'success'); } setTimeout(function(){ $(that).removeClass('disabled').prop('disabled',false); if(data.url) location.href = data.url; },1500); }else{ notify(data.info, 'error'); setTimeout(function(){ $(that).removeClass('disabled').prop('disabled',false); if (data.url) { location.href = data.url; } }, 1500); } }).error(function(jqXHR, textStatus, errorThrown) { $(that).removeClass('disabled').prop('disabled',false); var code = jqXHR.status; if(404 == code ){ notify(data.info ,'error'); }else if(412 == code){ notify('記錄已經被刪除了' ,'error'); } }); } return false; }); ~~~ 再看 提交按鈕的代碼: `<button type="button" class="btn btn-primary pull-right ajax-post no-refresh" hide-data="true" target-form="post" href="/api.php/post">保存</button>` 有這ajax-post類名和 target-form屬性。而父模板里有一個post類名的form標簽。 原來用了ajax提交序列化form了。地址是href屬性。 后面代碼了也些了ajax-put和ajax-delete。 這段代碼是我從OneThink里借過來的,修改了部分,添加了自己的提示信息代碼,以及響應碼判斷,以前的都是200。 成功以后的顯示是這樣的: ![2015-06-14/557d99a656d0e](http://box.kancloud.cn/2015-06-14_557d99a656d0e.png) ## 模型 api部分只是提供了新增數據,具體文章數據的添加有什么處理,還得看模型代碼。 我們看Common下的PostModel: ~~~ <?php namespace Common\Model; Use Think\Model; class PostModel extends Model{ protected $_auto = array ( array('status','1'), // 新增的時候把status字段設置為1 array('create_at','datetime', self::MODEL_INSERT, 'function'), // 對create_at字段在更新的時候寫入當前時間戳 array('deadline','getDeadline', self::MODEL_INSERT, 'callback'), // 對name字段在新增的時候回調getName方法 array('update_at','datetime', self::MODEL_BOTH, 'function'), // 對update_at字段在更新的時候寫入當前時間戳 array('content', 'encode', self::MODEL_BOTH, 'callback'), //對內容字段 根據type選擇進行json_encode array('view', 0, self::MODEL_INSERT), array('comment', 0, self::MODEL_INSERT), ); protected $_validate = array( ); //截止日期處理 public function getDeadline($deadline){ if('now' == I('request.create_time_choose')){ return datetime('now'); }else{ return datetime($deadline); } } //內容字段加密 public function encode($content){ if(in_array(I('post.type'), array('picture', 'music', 'video'))) return json_encode($content); else return $content; } protected function _after_find(&$result, $options) { if(in_array($result['type'], array('picture', 'music', 'video'))){ $result['content'] = json_decode($result['content'], 1); } } protected function _after_select(&$result, $options){ foreach($result as &$record){ $this->_after_find($record, $options); } if($result){ $member_ids = array_column($result, 'member_id'); $authors = M('Member')->where(array('id'=>array('in', $member_ids)))->getField('id,nickname'); foreach ($result as &$record) { if(isset($authors[$record['member_id']])) $record['author'] = $authors[$record['member_id']]; else $record['author'] = '系統發布'; } } } // 新增數據前的回調方法 protected function _after_insert($data, $options) { $this->_after_update($data, $options); } // 更新成功后的回調方法 protected function _after_update($data, $options) { //處理標簽 $tags = $data['tags']; $tags = explode(',', $tags); if($tags === FALSE){ $tags = array(); } $tagsModel = M('Tags'); if(!empty($_POST['id'])){ //更新時候先將原有標簽統計減去1 $orignal_tags = $this->getFieldById('tags', $data['id']); if($orignal_tags) $tagsModel->where(array('title'=>array('in', $orignal_tags)))->setDec('count'); } foreach ($tags as $value) { if($tagsModel->where("title = '{$value}'")->find()) $tagsModel->where("title = '{$value}'")->setInc('count'); else if($value) $tagsModel->add(array('title'=>$value, 'count'=>1)); } } } ~~~ 模型做了幾件事: 1.完成字段 status 插入時為1;create_at插入寫入日期時間文本;deadline在為選擇時,是當前時間,選擇了定時時是傳遞過來的文本;更新時間新增和更新時都更新為當前時間文本;content內容,在某些類型里json序列化,那時文本編輯器存的值到description里,content是數組表單;view和comment 查看數和評論數默認為0。 2.后置查詢時反序列化和字段值顯示文本處理 反序列化一看就知道,顯示文本的是用戶名處理。存的member_id 顯示時候顯示昵稱。 ~~~ if($result){ $member_ids = array_column($result, 'member_id'); $authors = M('Member')->where(array('id'=>array('in', $member_ids)))->getField('id,nickname'); foreach ($result as &$record) { if(isset($authors[$record['member_id']])) $record['author'] = $authors[$record['member_id']]; else $record['author'] = '系統發布'; } } ~~~ 這里用了array_column獲取查出來的`member_id` 數組集合,然后查詢該集合贏的用戶數據,并以`member_id`為鍵名。然后拼接作者字段顯示發布者昵稱。 3.后置更新時處理標簽表的統計 ~~~ // 更新成功后的回調方法 protected function _after_update($data, $options) { //處理標簽 $tags = $data['tags']; $tags = explode(',', $tags); if($tags === FALSE){ $tags = array(); } $tagsModel = M('Tags'); if(!empty($_POST['id'])){ //更新時候先將原有標簽統計減去1 $orignal_tags = $this->getFieldById('tags', $data['id']); if($orignal_tags) $tagsModel->where(array('title'=>array('in', $orignal_tags)))->setDec('count'); } foreach ($tags as $value) { if($tagsModel->where("title = '{$value}'")->find()) $tagsModel->where("title = '{$value}'")->setInc('count'); else if($value) $tagsModel->add(array('title'=>$value, 'count'=>1)); } } ~~~ 標簽的處理思路是,先將原有文章的所有標簽數量-1,然后新增或者更新時的標簽遍歷時再去更新統計數,或者新增標簽。這樣統計不會亂。 ## 其他格式 其他格式,之前說了,`'picture', 'music', 'video'`這三個類型 存description。content內容字段是數組序列化json的。 圖片和音樂都可能多數據,視頻只能一種。 ### 圖片 ![2015-06-14/557d9f9786935](http://box.kancloud.cn/2015-06-14_557d9f9786935.png) ![2015-06-14/557d9fb7cd304](http://box.kancloud.cn/2015-06-14_557d9fb7cd304.png) 圖片的content是個數組,每個元素里存圖片的path和alt。 圖片上傳,不說了就是pupload。后js動態添加圖片數組。 ### 音樂 ![2015-06-14/557da02089832](http://box.kancloud.cn/2015-06-14_557da02089832.png) ![搜索](http://box.kancloud.cn/2015-06-14_557da05081bf5.png) ![添加數據](http://box.kancloud.cn/2015-06-14_557da08a43208.png) 音樂比圖片多了一個id,alt換為title了。 音樂支持本地上傳mp3和百度搜索。 百度音樂搜索,其實就是參考了ueditor里的上傳,只不過自己用bootstrap-table拼接了搜索結果,然后選擇后,js處理了返回一個多維數組的格式。其他沒啥。 ### 視頻 視頻支持本地上傳mp4和在線視頻解析。 在線解析用的是云邊輕博客商業版2.0里的類。 然后經過優化了,支持優酷/土豆/酷六/56/搜狐/新浪視頻網站的播放頁面地址解析插入(注意不是FLASH地址)。 ![2015-06-22/5587743fd115a](http://box.kancloud.cn/2015-06-22_5587743fd115a.png) ![2015-06-22/558778da6b572](http://box.kancloud.cn/2015-06-22_558778da6b572.png) mp4本地視頻上傳 ![2015-06-22/5587796d41b6d](http://box.kancloud.cn/2015-06-22_5587796d41b6d.png) #### 在線視頻的地址獲取 我們都知道傳統視頻播放要一個flash播放器,然后播放的一般都是flv文件。 后來html5標準出來后 mp4一般成為了標準格式,因為ios平臺這個格式支持的最好。 我們看一下要分析的視頻 <http://v.youku.com/v_show/id_XMTI2NzQ3NTY2MA==_ev_10.html?from=y1.3-idx-uhome-1519-20887.205985-205986-205830-205987.5-3> ![2015-06-22/55877bae73d90](http://box.kancloud.cn/2015-06-22_55877bae73d90.png) 用chrome看下播放器代碼: ![2015-06-22/55877c466642b](http://box.kancloud.cn/2015-06-22_55877c466642b.png) 然而這里的地址不是我們想要的是個參數給那個播放器object讀取的。 我們要的地址可以通過分享獲取到,視頻網站為例視頻播放量,一般會提供分享功能。 ![2015-06-22/55877d99d8f73](http://box.kancloud.cn/2015-06-22_55877d99d8f73.png) 我們復制flash地址 粘貼在地址欄后訪問 ![2015-06-22/55877e49ba252](http://box.kancloud.cn/2015-06-22_55877e49ba252.png) 怎么樣?出來獨立的播放器了吧。 ![2015-06-22/55877e778315d](http://box.kancloud.cn/2015-06-22_55877e778315d.png) 而我們在線播放的原理就是在當前網頁里嵌入這么一個embed的標簽,地址是在線視頻的真實地址。 `<embed type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" src="http://player.youku.com/player.php/sid/XOTE1NDg4OTE2/v.swf" width="617" height="480" wmode="transparent" play="true" loop="false" menu="false" allowscriptaccess="never" allowfullscreen="true">` 一般來說php程序就是curl請求平播放頁面,然后想辦法解析出這個地址。 具體程序大家可以看我的那個視頻解析類 urlParse.php。 我只展示部分的代碼,以解析優酷視頻地址為例: ~~~ /** * 優酷網 * http://v.youku.com/v_show/id_XMjI4MDM4NDc2.html * http://player.youku.com/player.php/sid/XMjU0NjI2Njg4/v.swf */ private function _parseYouku($url) { preg_match("#id\_(\w+)#", $url, $matches); if (empty($matches)) { preg_match("#v_playlist\/#", $url, $mat); if (!$mat) return false; $html = self::_fget($url); preg_match("#videoId2\s*=\s*\'(\w+)\'#", $html, $matches); if (!$matches) return false; } $link = "http://v.youku.com/player/getPlayList/VideoIDS/{$matches[1]}/timezone/+08/version/5/source/out?password=&ran=2513&n=3"; $retval = self::_cget($link); if ($retval) { $json = json_decode($retval, true); $data['img'] = $json['data'][0]['logo']; $data['title'] = $json['data'][0]['title']; $data['url'] = $url; $data['id'] = "http://player.youku.com/player.php/sid/{$matches[1]}/v.swf"; $data['type'] = 'youku'; return $data; } else { return false; } } ~~~ 前面的部分是獲取vid,然后通過后門地址 拼接getPlayList那個去獲取視頻元數據,也就是標題和封面等信息,每個視頻網站后門地址不一樣,元數據也不一樣,我們只獲得通用的就好。 具體優酷視頻地址原理參見:[優酷真實視頻地址解析](http://my.oschina.net/u/727843/blog/390872)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看