酷狗krc歌词解析并转换为lrc歌词php版

 更新时间:2016年11月25日 15:40  点击:1903
在这里我们介绍使用php来实现酷狗krc歌词解析并转换为lrc歌词了,文章是转一站长的希望对各位朋友会有所帮助。

最近在进行一次对酷狗音乐歌词采集时发现酷狗音乐的歌词直接浏览都是“乱码”,自己平时所见的歌词都是lrc格式的文本,这种酷狗专用的krc格式的显然是经过特别处理过的,平时用酷狗听音乐也没仔细看他的歌词有什么不同,只是与天天静听等不同的是可以逐字高亮显示歌词。

于是搜索了下发现有个java版的半成品解密代码,测试了下竟然还是“乱码”,巨坑!于是只有采用最原始的办法,对酷狗的flash播放器进行反编译,发现这段krc解密的ActionScript代码:

 代码如下 复制代码

public function loaderCompleteHandler(param1:ByteArray) : void{
 this.newkeyBytes = [64, 71, 97, 119, 94, 50, 116, 71, 81, 54, 49, 45, 206, 210, 110, 105];
 var result:* = param1;
 var krcBytes:* = new ByteArray();
 result.position = 4;
 result.readBytes(krcBytes);
 var l:* = krcBytes.length;
 var i:int;
 while (i < l) {
  krcBytes[i] = krcBytes[i] ^ this.newkeyBytes[i % this.newkeyBytes.length];
  i = (i + 1);
 }
 try {
  krcBytes.uncompress();
 } catch (error:SecurityError) {
  errorfun("uncompressError");
  return;
 }
 krcBytes.position = 0;
 this.myLyric.dataStr = krcBytes.readUTFBytes(krcBytes.length);
 this.successfun();
 return;
}

根据这段代码可以很快转换成php解析代码:

 代码如下 复制代码

$enKey = array(64, 71, 97, 119, 94, 50, 116, 71, 81, 54, 49, 45, 206, 210, 110, 105);
$krc_content = substr($krc_content,4);
$len = strlen($krc_content);
$krc_compress = '';
for ($k = 0; $k < $len; $k++){
 $krc_compress .= chr(ord($krc_content[$k]) ^ $enKey[$k % 16]);
}
$krc_text = gzuncompress($krc_compress);

上面的$krc_content为krc歌词压缩加密的文本内容,得到了解析后的krc明文文本歌词$krc_text,然后就可以很容易的转换成lrc歌词了,如下:

 代码如下 复制代码

/**
 * krc歌词解析并转换为lrc歌词
 * $Name: krc2lrc  2014-4-18  qaulau<qaulau@hotmail.com>$
 *
 * @param string $krc_content 加密的krc歌词内容
 * @param string $glue   处理后的lrc歌词连接字符,默认为换行符n
 */
function krc2lrc($krc_content,$glue = "n"){
    $enKey = array(64, 71, 97, 119, 94, 50, 116, 71, 81, 54, 49, 45, 206, 210, 110, 105);
 $krc_content = substr($krc_content,4);
 $len = strlen($krc_content);
 $krc_compress = '';
 for ($k = 0; $k < $len; $k++){
  $krc_compress .= chr(ord($krc_content[$k]) ^ $enKey[$k % 16]);
 }
 $krc_text = gzuncompress($krc_compress);

 preg_match_all("/[(ar|ti|offset):(.+)]/",$krc_text,$matches);
 $lrc_text = implode($glue,$matches[0]).$glue;
 preg_match_all("/[(d{0,8}),(d{0,8})](.+)/",$krc_text,$matches);
 unset($krc_text,$krc_compress,$krc_content,$enKey);
 if(!empty($matches[1])){
  foreach($matches[1] as $k=>$v){
   list($seconds, $millis) = explode('.', $v / 1000);
   $lrc_time = date('i:s',1388534400 + $seconds).'.'.substr($millis,0,2);
   $lrc_cont = preg_replace("/<d{1,8},d{1,8},d{1,8}>/",'',$matches[3][$k]);
   $lrc_text .= "[{$lrc_time}]{$lrc_cont}{$glue}";
  }
 }
 return $lrc_text;
}

简单的示例:

 代码如下 复制代码

$content = file_get_contents('1.krc');
echo krc2lrc($content,'<br/>');

分享一下,方便日后有类似需要的人查询!

如果你希望你的php可以使用$_SERVER[PATH_INFO]我们需要让Apache支持pathinfo才可以了,当然大部份apache默认就是支持pathinfo的哦。


最后总结测试环境:

Ubuntu Server 14.04

PHP Version 5.5.9-1ubuntu4

Apache/2.4.7 (Ubuntu)


PATH_INFO是服务器状态中的一个参数,通过$_SERVER['PATH_INFO']可以查看内容。$_SERVER数组中除了PATH_INFO外,还有非常多的数据,比如REQUEST_URI包含了更多的信息。

还有容易混淆的概念:pathinfo指的是PHP4(4.0.3)的一个功能,用于返回一个文件的路径信息。

Apache默认支持PATH_INFO功能,网上的很多教程不是需要修改apache的配置文件,就是要修改php的配置文件,其实完全不用修改任何文件,可以采用以下两种方式来验证PATH_INFO功能。

方式一:原生代码测试
在一个全新的系统上,比如新建一个Ubuntu 14.04 Server虚拟机,仅安装OpenSSH和LAMP软件包。

在Apache的主路径/var/www/html目录下新建测试文件pathinfo.php,内容为

<?php
 echo $_SERVER['PATH_INFO'];
?>
假设虚拟机的IP是192.168.1.106,访问http://192.168.1.106/pathinfo.php,会得到一个空白的页面。因为这个URL没有包含PATH_INFO信息。

更换网址测试http://192.168.1.106/pathinfo.php/year/2014/,页面上会显示/year/2014/,说明可以识别PATH_INFO信息。

方法二:用ThinkPHP测试
很多的PHP框架都需要获取PATH_INFO的值,以ThinkPHP为例,基本的步骤是:

下载最新的ThinkPHP到/var/www/html/目录,并解压,修改文件的权限为www-data
访问网址http://192.168.1.106/index.php,会自动生成Application下的文件列表
编辑文件Application/Home/Controller/IndexController.class.php,内容为
<?php
namespace HomeController;
use ThinkController;
class IndexController extends Controller {
    public function index(){
        $this->show('Hi,All','utf-8');
    }
    public function test(){
        $this->show('test');
    }
}
当访问http://192.168.1.106/index.php的时候,本质上是访问了http://192.168.1.106/index.php/Home/Index/index,如果后面这个长的可以访问,说明PATH_INFO是正常的。

如果存在异常,ThinkPHP可以能报错为无法加载模块/控制器或非法操作,可以通过访问test方法来验证。

输入网址http://192.168.1.106/index.php/Home/Index/test测试,页面会正常显示test

补充:Apache2.2.22开启PathInfo模式支持

在配置文件中加入

<Files *.php>

AcceptPathInfo On

</Files>

这样 Apache 就可以支持针对 php 文件的 PathInfo 了。
于是,小柒又充满希望的试了一下,可惜,还是没有成功。
我想,这PathInfo跟URL有关,那会不会是因为Apache服务器没有开启mod_rewrite模块的关系呢?于是,我在Apache的配置文件(Apache安装目录的conf文件夹下的httpd.conf文件)里找到:
#LoadModule rewrite_module modules/mod_rewrite.so
将前面的#去掉,改为:
LoadModule rewrite_module modules/mod_rewrite.so
保存,重启服务器后,项目终于可以使用PathInfo模式访问了

php时区是一个非常有意思的问题,安装好apache+php环境之后会发现我们使用date函数获取的日期都与中国时间有8小时区别了,那么这个时区问题要如何解决呢?下面本人整理了一些关于php时区设置方法,有需要的朋友可进入参考。

时区划分

整个地球分为24个时区,每个时序都有自己的本地时间。同一时间,每个时区的本地时间相差1到23个小时,例如,英国伦敦本地时间与北京本地时间相差8个小时。在国际无线电通信领域,使用一个统一的时间,称为通用协调时间(UTC,Universal Time Coordinated),UTC与格林威治标准时间(GMT,Greenwich Mean Time)相同,都与英国伦敦的本地时间相同

时区设置

由于PHP5.0对data()函数进行了重写,因此,目前的日期时间函数比系统时间少8个小时。在PHP语言中默认设置的是标准的格林威治时间(即采用的是零时区),所以要获取本地当前的时间必须更改PHP语言中的时区设置。

更改PHP语言中的时区设置有两种方法:

(1)修改php.ini文件中的设置,找到[date]下的“;date.timezone=”选项,将其修改为“date.timezone=Asia/Hong_Kong”,然后重新启动Apache服务器。


修改PHP.ini这个文件

找到date.timezone这行,去掉前面的分号,改成:

 代码如下 复制代码

date.timezone = Asia/Shanghai

修改 .htaccess文件

修改.htaccess文件有两种办法,下面的两条语句只要有一条即可

 代码如下 复制代码

php_value date.timezone Asia/Shanghai
SetEnv TZ Asia/Shanghai


(2)在应用程序中,在使用时间日期函数之前添加如下函数:

在代码中设置时区

 代码如下 复制代码

1 date_default_timezone_set('Asia/Shanghai');//'Asia/Shanghai'   亚洲/上海

2 date_default_timezone_set('Asia/Chongqing');//其中Asia/Chongqing'为“亚洲/重庆”

3 date_default_timezone_set('PRC');//其中PRC为“中华人民共和国”

4i ni_set('date.timezone','Etc/GMT-8');

5 ini_set('date.timezone','PRC');

6 ini_set('date.timezone','Asia/Shanghai');

7 ini_set('date.timezone','Asia/Chongqing');

date_default_timezone_set('PRC');

//PRC为中华人民共和国时区

或者

 代码如下 复制代码

<?php
    date_default_timezone_set("Asia/Kolkata");
    echo date('d-m-Y H:i:s'); //Returns IST
?>

参数为PHP可识别的时区名称,如果时区名称PHP无法识别,则系统采用UTC时区。在PHP手册中提供了各个时区名称列表,其中,设置我国北京时间可以使用的时区包括:PRC(中华人民共和国)、Asia/Chongqing(重庆)、Asia/Shanghai(上海)或者Asia/Urumqi(乌鲁木齐),这几个时区名称等效的。


设置完成后,date()函数便可以正常使用,不会再出现时差问题。

输出系统的当前时间

上面是一种设置系统当前时间的方法,在这里将采用另外一种方式设置系统当前的时间,即直接在date()函数之前通过date_default_timezone_set()函数设置系统的时区,并输出系统当前的日期和时间。代码如下

 代码如下 复制代码

<?php
echo "UTC时间:".date("Y-m-d H:i:s");  //显示默认的UTC时间
date_default_timezone_set("PRC");      //使用中华人民共和国的时区
echo "<br>";
echo "北京时间:".date("Y-m-d H:i:s");  //输出北京时间
echo "<br>";
echo "中文时间:".date("Y年m月d日 H时i分s秒");  //输出中文格式时间
echo "<br>";
echo "当前时区:".date_default_timezone_get();   //获取当前时区
?>

测试:

 代码如下 复制代码

代码
date_default_timezone_set(‘Etc/GMT’);
//在输出时间之前设置时区,Etc/GMT为时间标准时间
echo(time());
echo(‘
’);
echo date(‘Y-m-d H:i:s’, time());
echo(‘
’);
echo gmdate (“Y-m-d H:i:s”, time());
echo(‘
’);
date_default_timezone_set(‘PRC’);
//在输出时间之前设置时区,PRC为中华人民共和国
echo(time());
echo(‘
’);
echo date(‘Y-m-d H:i:s’, time());
echo(‘
’);
echo gmdate (“Y-m-d H:i:s”, time());
?>
结果:
1276257131
2010-06-11 11:52:11
2010-06-11 11:52:11
1276257131
2010-06-11 19:52:11
2010-06-11 11:52:11
结论:
time() :标准时间戳
指返回自从 Unix 纪元(格林威治时间 1970 年 1 月 1 日 00:00:00)到当前时间(指的是当前GMT标准时间)的秒数,它的值跟php系统设置的时区无关。
date():返回的是当前 GMT标准时间的本地化时间的“自定义格式”时间,跟php系统设置的时区有关。
gmdate():返回的是当前 GMT标准时间的“自定义格式”时间,跟php系统设置的时区无关

unix时间戳:指的是当前(GMT标准)时间离unix纪元时间(1970-01-01 00:00:00)的秒数;
代码
date_default_timezone_set(‘Etc/GMT’);
//在输出时间之前设置时区,Etc/GMT为时间标准时间
echo(strtotime(’1970-01-01 08:00:00′));
echo(‘
’);
date_default_timezone_set(‘PRC’);
//在输出时间之前设置时区,PRC为中华人民共和国
echo(strtotime(’1970-01-01 08:00:00′));
?>
测试结果:
28800
0

strtotime(a):当前时间的GMT标准时间的unix时间戳,如果当前php系统的设置的时区不是GMT标准时区,则在应用strtotime(a)时,系统会自动把时间a折算成相应的GMT标准时间,然后计算这个时间的unix时间戳。跟php系统设置的时区有关

curl来抓取网页内容是一个性能比较好的函数了,我们通常会使用它来快速模仿用户去访问我们要抓取的网页了,下面看一个例子有兴趣的朋友可进入参考。

早上想写了一个抓取是京东618魅族专题页的抓取,然后想着自动下单购买,尼玛,算了,太多了,写到判断是否开始了,商品价格进行了变化,后边工程量有点大就懒的写了,如果要完善的话就需要写模拟登陆(这个不难)加入购物车,下单,下单的时候判断一下价格,如果价格个官方优惠价格相同就下单,不同就接着去抓。算了,懒的写了。下边是部分代码

 代码如下 复制代码

<?php
$cookie_file = dirname(__FILE__)."/jd.cookie";
//专题首页url
$indexurl = 'http://sale.jd.com/act/BOxFsKPGNZwpet4.html';
//获取专题页到产品详情的地址
$indexstr = get($indexurl);
//var_dump($indexstr);exit;
preg_match_all('/<area shape="rect" coords="802,199,941,244" href="(.*?)"/is',$indexstr,$data);

$tmp = pathinfo($data[1][0]);
$pinfo['id'] = $tmp['filename'];
$pinfo['url'] = $data[1][0];
unset($tmp,$data);
$pinfo = getPrice($pinfo['id']);
if($pinfo['mainproduct']['price'] == 1799){
addcar();
}else{
echo "还没有开始抢购";
}

function get($url,$flag=true){
global $cookie_file;
$headerArray = array(
"content-type: application/x-www-form-urlencoded;charset=UTF-8",


);
//echo $cookie_file;exit;
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,$url);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch,CURLOPT_USERAGENT,'"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:30.0) Gecko/20100101 Firefox/30.0"');
curl_setopt($ch,CURLOPT_HTTPHEADER,$headerArray);//设置头信息
curl_setopt($ch,CURLOPT_COOKIEFILE,$cookie_file);
curl_setopt($ch,CURLOPT_COOKIEJAR,$cookie_file);

$return = curl_exec($ch);
curl_close($ch);
if($flag)$return = gzdecode($return);
return $return;
}

function getPrice($id){
$priceUrl = "http://rs.jd.com/accessorie/newServiceWhite.jsonp?sku=".$id;

$data = json_decode(get($priceUrl,false),true);
return $data;
}
function addcar(){
global $pinfo;
$addurl = "http://gate.jd.com/InitCart.aspx?pid=".$pinfo['mainproduct']['sku']."&pcount=1&ptype=1";

echo get($addurl,false);
}

php 在curl抓取的时候出现乱码

用站长工具查看我们抓取的网而不是使用了gzip压缩了,如果有返回"Accept-Encoding:gzip, deflate" 就是打开了gzip了,我们只要如下操作

 代码如下 复制代码

$res=curl_exec($ch1);
if(!empty($res)){ //save capcha
echo gzdecode($res);
}

GBK或者UTF8汉字之类的乱码

 代码如下 复制代码

mb_convert_encoding($str, 'utf-8', 'GBK,UTF-8,ASCII');就行了

我们设置页面为GBK兼容GB2312,GB2312是GBK的子集,所有GB2312编码的用GBK都能正确解出来

在php中碰到乱码多半是编码问题了,在这里我们分析了很久得出了下面fgetcsv读取csv文件乱码原因所在与解决办法。

例子

 

 代码如下 复制代码

function get_csv_contents( $file_target ){

 $handle  = fopen( $file_target, 'r');

 while ($data = fgetcsv($handle, 1000, ",")) {
 
  $num = count($data);
  echo "<p> $num fields in line $row: <br>n";
  $row++;
  for ($c=0; $c < $num; $c++) {
   echo $data[$c]. "<br>n";;
   /*echo getUTFString($data[$c])*/
  }
 }

 fclose($handle);
}

导入的csv文件是以ansi编码保存的,对于中文操作系统环境对应的应该就是gbk编码了,通过手动更改浏览器字符编码为gbk,乱码的情况消失了,于时进行了下面调整。

 代码如下 复制代码

$data = eval(‘return ‘.iconv(‘gbk’,'utf-8′,var_export($data,true)).’;');

$data为需要转换编码的数组。

补充:LINUX FGETCSV读取GBK数据乱码

当Linux系统是使用的默认设置,则在该Linux服务器上对gbk的csv格式文件进行处理的时候,就会出现乱码现象。
解决方法是:
使用 setlocale 函数设置环境变量。比如要设置使用gb 的区域设置可以在fgetcsv前使用下面的语句。

 代码如下 复制代码

setlocale(LC_ALL,array('zh_CN.gbk','zh_CN.gb2312','zh_CN.gb18030'));

具体使用哪些locale 可以使用linux 命令 locale -a 查看系统支持哪些

[!--infotagslink--]

相关文章

  • 使用PHP+JavaScript将HTML页面转换为图片的实例分享

    这篇文章主要介绍了使用PHP+JavaScript将HTML元素转换为图片的实例分享,文后结果的截图只能体现出替换的字体,也不能说将静态页面转为图片可以加快加载,只是这种做法比较interesting XD需要的朋友可以参考下...2016-04-19
  • 源码分析系列之json_encode()如何转化一个对象

    这篇文章主要介绍了源码分析系列之json_encode()如何转化一个对象,对json_encode()感兴趣的同学,可以参考下...2021-04-22
  • 在数据库里将毫秒转换成date格式的方法

    在开发过程中,我们经常会将日期时间的毫秒数存放到数据库,但是它对应的时间看起来就十分不方便,我们可以使用一些函数将毫秒转换成date格式。 一、 在MySQL中,有内置的函数from_unixtime()来做相应的转换,使用如下: 复制...2014-05-31
  • php中去除文字内容中所有html代码

    PHP去除html、css样式、js格式的方法很多,但发现,它们基本都有一个弊端:空格往往清除不了 经过不断的研究,最终找到了一个理想的去除html包括空格css样式、js 的PHP函数。...2013-08-02
  • JavaScript预解析,对象详解

    这篇文章主要介绍了JavaScript预解析,对象的的相关资料,小编觉得这篇文章写的还不错,需要的朋友可以参考下,希望能够给你带来帮助...2021-11-10
  • php常量详细解析

    一、常量常量是一个简单值的标识符(名字)。如同其名称所暗示的,在脚本执行期间该值不能改变(除了所谓的魔术常量,它们其实不是常量)。常量默认为大小写敏感。按照惯例常量标识符总是大写的。 常量名和其它任何 PHP 标签遵循...2015-10-30
  • 美图秀秀把普通照片快速转换成卡通效果教程

    今天小编在这里就来给美图秀秀的这一款软件的使用者们来说下把普通照片快速转换成卡通效果的教程,各位想知道具体制作步骤的使用者们,那么下面就快阿里跟着小编一起看一...2016-09-14
  • Javascript类型转换的规则实例解析

    这篇文章主要介绍了Javascript类型转换的规则实例解析,涉及到javascript类型转换相关知识,对本文感兴趣的朋友一起学习吧...2016-02-27
  • index.php怎么打开?如何打开index.php?

    index.php怎么打开?初学者可能不知道如何打开index.php,不会的同学可以参考一下本篇教程 打开编辑:右键->打开方式->经文本方式打开打开运行:首先你要有个支持运行PH...2017-07-06
  • PHP中func_get_args(),func_get_arg(),func_num_args()的区别

    复制代码 代码如下:<?php function jb51(){ print_r(func_get_args()); echo "<br>"; echo func_get_arg(1); echo "<br>"; echo func_num_args(); } jb51("www","j...2013-10-04
  • 浅析C#数据类型转换的几种形式

    本篇文章是对C#中数据类型转换的几种形式进行了详细的分析介绍,需要的朋友参考下...2020-06-25
  • JavaScript实现数据类型的相互转换

    这篇文章主要为大家详细介绍了JavaScript实现数据类型的相互转换,感兴趣的朋友可以参考一下...2016-03-09
  • PHP编程 SSO详细介绍及简单实例

    这篇文章主要介绍了PHP编程 SSO详细介绍及简单实例的相关资料,这里介绍了三种模式跨子域单点登陆、完全跨单点域登陆、站群共享身份认证,需要的朋友可以参考下...2017-01-25
  • JavaScript实现Base64编码转换

    这篇文章主要介绍了JavaScript实现Base64编码转换的相关资料,非常简单实用,需要的朋友可以参考下...2016-04-25
  • PHP编码转换函数mb_convert_encoding与iconv用法

    文章来实现一个PHP编码转换函数mb_convert_encoding与iconv用法,希望例子能帮助到各位。 将一个短信接口代码从apache迁移到nginx+php-fpm后,发现无法发出短信了,查...2016-11-25
  • c#入门之类型转换详解

    这篇文章主要介绍了c#的类型转换详解,类型转换分两种形式:隐式转换、显示转换,下面是详细介绍...2020-06-25
  • PHP实现创建以太坊钱包转账等功能

    这篇文章主要介绍了PHP实现创建以太坊钱包转账等功能,对以太坊感兴趣的同学,可以参考下...2021-04-20
  • java中JSONObject转换为HashMap(方法+main方法调用实例)

    这篇文章主要介绍了java中JSONObject转换为HashMap(方法+main方法调用实例),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-11-14
  • C#将数字转换成字节数组的方法

    这篇文章主要介绍了C#将数字转换成字节数组的方法,涉及C#字符串操作的技巧,非常具有实用价值,需要的朋友可以参考下...2020-06-25
  • JS跨浏览器解析XML应用过程详解

    这篇文章主要介绍了JS跨浏览器解析XML应用过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下...2020-10-16