音乐抓取总结
作者:admin 日期:2012-04-07
抓取音乐的工作终于告一段落了,现在把在抓取过程中遇到的一些问题记录下来,下次如果再有抓取音乐的相关工作应该会少走一些弯路。
1.抓取的时候先找到歌曲播放页的链接地址规律,一般用正则表达式进行匹配会比较好,同时要多进行测试,例如我写的正则表达式在windows下可以正确匹配,在Debian下却匹配不上,可能是PHP版本所导致的区别吧,最后把正则表达式微调解决了问题。同时下载mp3(或lrc,下同)的时候一定要有重试的机制,因为抓取音乐是批量进行的工作,服务器的带宽有时也许有限,一次不行试多次,如果试了多次仍然不行可能是服务器挂了,同时有必要把下载失败的url记录下来,一行一个url地址,换个时间也许就可以下载了。
下载文件的重试机制
如果抓取音乐时音乐服务器是多台,则一台服务器如果抓取失败,可以试着再选择其它的服务器试试,多试几次也许就会下载成功了。 $ips = array( function down_file($url) { //一些其它的代码 return strlen($str) > 0 ? true : false; function get_ip() { //随机取出一个ip,起到负载均衡的目的 return $ip;
'8.8.8.1',
'8.8.8.2',
'8.8.8.3'
);
$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));
}
global $ips;
$key = array_rand($ips);
$ip = $ips[$key];
}
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.至此,抓取歌曲基本完成。
广告位