音乐抓取总结

抓取音乐的工作终于告一段落了,现在把在抓取过程中遇到的一些问题记录下来,下次如果再有抓取音乐的相关工作应该会少走一些弯路。


1.抓取的时候先找到歌曲播放页的链接地址规律,一般用正则表达式进行匹配会比较好,同时要多进行测试,例如我写的正则表达式在windows下可以正确匹配,在Debian下却匹配不上,可能是PHP版本所导致的区别吧,最后把正则表达式微调解决了问题。同时下载mp3(或lrc,下同)的时候一定要有重试的机制,因为抓取音乐是批量进行的工作,服务器的带宽有时也许有限,一次不行试多次,如果试了多次仍然不行可能是服务器挂了,同时有必要把下载失败的url记录下来,一行一个url地址,换个时间也许就可以下载了


下载文件的重试机制

如果抓取音乐时音乐服务器是多台,则一台服务器如果抓取失败,可以试着再选择其它的服务器试试,多试几次也许就会下载成功了。

$ips = array(
    '8.8.8.1',
    '8.8.8.2',
    '8.8.8.3'
);

function down_file($url) {
    $cnt = 0;
    $try_count = 30;
    while ($cnt < $try_count && ($str = @file_get_contents($url, false)) === FALSE) {
        writeLog(sprintf("%s spider url: |%s| try %d times", __FUNCTION__, $url, $cnt + 1));
       
        //每台服务器试3次
        if ($cnt % 3 == 0) {
            $ip = get_ip();
            $url = //替换$url中原来的ip为新的随机取的ip
        }
        $cnt++;
    }

    //一些其它的代码
    writeFile($mp3_file, request_data($mp3_url));

    return strlen($str) > 0 ? true : false;
}

function get_ip() {
    global $ips;

    //随机取出一个ip,起到负载均衡的目的
    $key = array_rand($ips);
    $ip = $ips[$key];

    return $ip;
}

 


 

2.下载歌曲的同时最好不要进行相关的转换,因为ffmpeg比较消耗服务器的资源,如果遇到某个文件是坏的可能会导致转换中止,严重的时候可能会导致程序中止,因此得不偿失,分开处理会比较好。另外有的wma文件可以正常播放,但是转换为mp3的时候可以会出错,可能是此音乐文件有问题,flash不支持wma,用MediaPlayer播放倒是不需要转换了。


某个wma文件无法转换的log

FFmpeg version 0.5, Copyright (c) 2000-2009 Fabrice Bellard, et al.
  configuration: --prefix=/usr/local --enable-memalign-hack --enable-libmp3lame --enable-shared
  libavutil     49.15. 0 / 49.15. 0
  libavcodec    52.20. 0 / 52.20. 0
  libavformat   52.31. 0 / 52.31. 0
  libavdevice   52. 1. 0 / 52. 1. 0
  built on Dec 14 2009 11:41:56, gcc: 4.3.2
/data/musictmp/spidertmp_3c070b27720b91fd255f4d346a685416.wma: Error while opening file


 

3.下载歌曲的时候不要将歌曲相关的信息入库,因为此歌曲是否能正常下载还不得而知,要是直接入库了,歌曲却下载失败了,这条记录在数据库中就算是垃圾信息了。

ffmpeg转换歌曲的时候也不要入库,因为转换的时候你只是启动了一个ffmpeg进程,此文件什么时候转换完成是无法程序是不太好监控的,转换成功还是失败也无法知道。


4.抓取歌曲流程总结

a.抓取歌曲的时候如果歌曲下载成功,则将歌曲下载成功的歌曲信息(例如歌曲id、歌曲名称、歌手名称等)记录在一个文件中(例如succeed.txt),下载失败的文件记录在另外一个文件中(例如failed.txt),以免下次换个时间再次抓取。同时音乐文件及lrc文件的命名与被抓取的音乐的歌曲id关联起来,以方便下面文件的查找


b.抓取歌曲的时候不要进行转换,等下载全部完成后再统一转换,转换的时候循环读取succeed.txt文件。启动每个ffmpeg进程后最好sleep几秒钟,这样可以避免在短时间内启动很多的ffmpeg进程。转换的时候无法判断歌曲转换是否成功,所有歌曲转换完成以后统一判断


c.估计歌曲差不多完成了,用ps -ef | grep ffmpeg查看一下,看看系统中是否有僵死的进程,如果有,则把它记录下来,再次转换看能否转换成功,如果不能转换则可能音乐文件是坏的,抛弃之。


d.循环读取succeed.txt文件,取得歌曲id,根据歌曲id可以知道mp3文件是否存在,如果存在,则表示转换成功了(不过也有少部分例外,就是比如几十K的mp3文件可能是转换失败了,手动将convert_succeed.txt中的相对应的记录删除即可),则将歌曲转换成功的歌曲信息保存到一个文件中(例如convert_succeed.txt,此文件的行数<=succeed.txt)。


e.循环读取convert_succeed.txt文件,然后将歌曲信息入库。入库的时候如果有其它的操作,且此操作与新入库的记录id有关,则最好入库后sleep几秒钟,主要是服务器比较繁忙的时候可能会出问题,考虑细一点没有什么坏处

$new_songid = update_data($row, $singername);
$cnt = 0;
//如果数据插入不成功,则等待一下,主要用于服务器比较繁忙的时候
while ($cnt < 10 && (int)$new_songid < 0) {
    writeLog(sprintf("%s data insert no finished, waiting...", __METHOD__));
    sleep(1);
    $cnt++;
}
if ((int)$new_songid > 0) move_file($songid, $new_songid);


f.在尽可能的地方有重试机制。


g.至此,抓取歌曲基本完成。



上一篇: 递归在请求远程URL时的应用
下一篇: PHP关于URL参数传递的问题
文章来自: 本站原创
引用通告: 查看所有引用 | 我要引用此文章
Tags: php
相关日志:
评论: 0 | 引用: 0 | 查看次数: 1476
发表评论
昵 称:
密 码: 游客发言不需要密码.
邮 箱: 邮件地址支持Gravatar头像,邮箱地址不会公开.
网 址: 输入网址便于回访.
内 容:
验证码:
选 项:
虽然发表评论不用注册,但是为了保护您的发言权,建议您注册帐号.
字数限制 1000 字 | UBB代码 开启 | [img]标签 关闭

 广告位

↑返回顶部↑