虾米自动签到的实现


<h4>前言</h4>
<p>今天抽空整理了下把它写成了一个多账号版本的,放在了SAE上头,网址是:http://autocheck.sinaapp.com 。 上头输玩账号密码程序就可以自动帮你的账号签到了。切记程序会记住你的账号密码,如果有介意的请千万不要使用,本人不对你的账号问题进行负责。</p>

<p>上一篇文章中,我们讲述了如何利用PHP批量下载虾米已下载的歌曲。其中我们实现了如何用PHP+CURL模拟虾米登陆,这回我们来实现一下如何自动签到。(对于我这样的只是拿虾米当下载音乐的地方,而且经常忘记签到的孩子真的是非常有用啊有木有!T_T)</p>
<h4>一、获取登陆COOKIES</h4>
<p>还是老样子,我们先获取到登陆的COOKIES文件。<red>修改代码中的第2行和第3行,填入自己的账号和密码。</red>如果成功的话,会在该文件的同级目录下得到一个cookies.txt文件。

$name = ''; //输入你的账号
$password = ''; //输入你的密码
//获取登陆cookie
$curl_post = 'email='.$name.'&password='.$password.'&done=/&submit=登 录';
$cookie_file = dirname(__FILE__).'/cookie.txt';
$curl = curl_init();
curl_setopt($curl, CURLOPT_HEADER, 1);
curl_setopt($curl, CURLOPT_URL, "http://www.xiami.com/member/login");
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $curl_post);
curl_setopt($curl, CURLOPT_COOKIEJAR, $cookie_file);
curl_exec($curl);
curl_close($curl);

</p>
<h4>二、获取签到地址</h4>
<p>虾米的签到其实是向http://www.xiami.com/task/signin这个网页发送一个POST,这个POST的Data长度是0。代码利用虾米手机页面的签到机制,向一个特定的地址发送一个POST过去就可以了。所以再要就是获取签到的地址。</p>
<p>
<script src="https://gist.github.com/lizheming/fc5c616daac8b2eb24e9.js";></script>
</p>
<h4>三、进行签到</h4>
<p>利用上一步中获取到的地址进行签到。但是要注意的是,网页会判断页面来源,如果不是从虾米网站POST过去的会签到失败。所以我添加了自定义Referer来源。之前就一直因为这个没有更改而一直都没有成功,后来索性模拟了所有的HTTP Header才发现了问题的所在。另外,虽然POST空数据过去,但千万不要以为不POST数据过去就行了,无和0还是有点区别的,哈哈!其它的就没有什么问题了。签到成功的话页面会返回你的签到天数。</p>
<p>

//自动签到
$url = 'http://www.xiami.com' . $match1;
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_COOKIEFILE, $cookie_file);
curl_setopt($curl, CURLOPT_HEADER, 1);
curl_setopt($curl, CURLOPT_REFERER, 'http://www.xiami.com/web');
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$num = curl_exec($curl);
curl_close($curl);

</p>
<h4>四、Cron添加自动签到任务</h4>
<p>我这里以SAE为例,将第一步获取到的cookies.txt文件和第二步的xiami.auto.sign.php一起上传到应用中。例如存放位置是/xiami。在cron.yaml末尾添加如下代码:

  - description:cron XiamiAutoSign
    url: xiami/xiami.auto.sign.php
    schedule: every day of month 00:10
    timezone: Beijing

设置成功的话会在每天的00:10访问这个页面,完成自动签到功能!
</p>

如何批量下载虾米已下载歌曲


本文方法已失效,新版见:如何批量下载虾米已下载歌曲(新)

<h3>前言</h3>
<p>首先要说明的是,这不是一篇讲述如何免费批量下载虾米高质量音乐的文章,而是讲述一个杯具男如何因为懒惰而DIY出的成果。所以如果抱有前述心理的同学到此可以关闭网页了。另外本文中代码运用到了PHP+CURL+JavaScript,推荐大家在本地环境中进行操作。同时最重要的是,本文不是讨论如何绕过虾米的收费机制下载歌曲,所以你必须保证你有足够的虾米币或者红包用来下载歌曲才行,否则一切免谈。</p>
<h3>事出有因</h3>
<p>事情是这样的。前两天安装了Linux Mint,在Linux中打开了音乐,没过一会儿就卡掉了,当时我也没在意。结果一回到Windows就提示我文件夹损坏了,里面的文件也自然都悲剧了。用恢复软件恢复了效果也不太理想。400首歌总共2G多的文件也不是说割舍就能割舍的,所以就有了下面这些。</p>
<h3>解题思路</h3>
<p>虾米下载的机制是这样的:在网站点击下载之后,网站向你的账户中未下载列表传递下载歌曲信息,之后未下载列表则返回一个以emoun://特有协议开头的文件,用以打开虾歌(这个和迅雷thunder://以及电骡等的ed2k://是一个道理)。虾歌打开后查询未下载的表单,返回表单中的歌曲,然后下载。同时将未下载列表中的歌曲提交到已下载列表中,并在未下载列表中删除。这样,一次下载就完成了。</p>
download
<p>如图所示,点击下载歌曲,网站向http://www.xiami.com/download/song页面POST提交了相关Data,同时网页返回一个emoun://协议开头的文件(图中左侧红色方框标记的)。</p>
<p>所以我的想法是这样的:首先登陆网页抓取已下载列表中已经下载过歌曲的信息,然后批量的提交到未下载列表。然后打开虾歌去查询未下载列表中的歌曲就好了。如果和我所想一样的话,虾歌应该会一次性批量得到所有歌曲,那么我们只要等待下载完成就好了。</p>
<h3>解题步骤</h3>
<h4>一、获取登陆COOKIES</h4>
<p>获取登陆后的COOKIES文件,方便之后的抓取工作。<red>修改代码中的第2行和第3行,填入自己的账号和密码。</red>如果成功的话,会在该文件的同级目录下得到一个cookies.txt文件。

$name = ''; //输入你的账号
$password = ''; //输入你的密码
$curl_post = 'email='.$name.'&password='.$password.'&done=/&submit=登 录';
$cookie_file = dirname(__FILE__).'/cookie.txt';
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, "http://www.xiami.com/member/login");
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $curl_post);
curl_setopt($curl, CURLOPT_COOKIEJAR, $cookie_file);
curl_exec($curl);
curl_close($curl);

<h4>二、抓取下载列表并提交到未下载列表</h4>
<p>有了上一步之后,这一步就变的非常的简单。这里主要考虑的是效率的问题,由于我的歌曲打开400首,虾米一页显示20首。所以我大概有20页要抓取,这对于PHP来说是一个不小的工作量,在本地运行更甚。如果你的页面少可以使用下面的代码,如果你要抓的页面多,可以尝试将其改写成multi_curl同步抓取,或者改写成AJAX形式,亦或是分批抓取都行。<red>使用代码时候记得修改第三行的抓取页数。</red>

set_time_limit(0); //设置成不限制页面运行时间
$page = ''; //填写你的已经下载页面的页数
$cookie_file = dirname(__FILE__).'/cookie.txt';
       
$song = '';
//如果页数过多可以分批获取,以免等待时间过长
for($i=1;$i<=$page;$i++) {
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, "http://www.xiami.com/account/mysongs/s/2/page/".$i);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($curl, CURLOPT_COOKIEFILE, $cookie_file);
    $data = curl_exec($curl);
    curl_close($curl);

    $preg = '/<td.class="iname"><a.href="/song/(.?)">(.?)</a>/s';
    preg_match_all($preg, $data, $match);
    foreach($match[1] as $item) {
        $song .= $item . ',';
    }
}
$song = str_replace(' ', '', $song);
$song = substr($song, 0, -1);
echo "var song = new Array($song);";
/end/

<h4>三、批量提交下载歌曲</h4>
<p>上一步的代码中,我将下载歌曲的ID输出成了JavaScript数组的形式。因为这一步中我们将以歌曲数为基数向虾米网站POST提交信息,400对于PHP来说仍然是一个庞大的数字,对于本地更甚。你可以修改成multi_curl的形式,不过我第一反应是AJAX异步传输,这就是为什么我将歌曲的ID输出成了JavaScript数组的原因。<p>
<p>原理很简单,JS用来模拟循环,PHP则负责POST提交数据。<red>使用代码时记得将xiami.song.download.html中的第3行替换成你在上一步中获得的代码。</red>

<script type="text/javascript">
//将第二步获得的代码复制到下面,记得删除最后一位数的逗号
var song = new Array(1769629171,3338870,1769902385,1770432131,2868586,1770149760,367633,1769832130,35526,1769962750,1770551145,1770457081,3486103,1769400110,127903,3367334,2078855,71830,376007,376015,2074918,2730,1770450144,3455520,79157,79151,81366,65256,390070,2138604,1770345727,376050,376006,149193,388168,1769665592,3497062,1769236069,3632104,1768923954,1769491757,3608275,2092882,1770354410,3480460,3620143,2095376,2561774,3664677,1770462404,1769056924,3527076,2126340,2089410,1769177482,2083322,1769831952,1769316186,1770524409,1769517803,1190507,1964547,1769107542,3486203,1769686818,1769028326,1858814,2084011,1769235816,1770614545,2083187,2605276,378268,2515019,1122167,1769176497,3302053,2083102,3638520,189072,371017,1770168732,1083760,2122948,2070331,2128868,3319126,2561592,1381654,3441719,1768939471,2091290,2098665,2067235,1770060224,3562953,54342,1769831786,1770145312,76323,2067242,173117,136054,1770068043,1769833104,1769833105,1769833106,1769833107,1769833108,2082305,1768989931,1769356638,1769082273,1769776879,1769740304,1205851,1768984809,1769102373,1769740095,1768989928,1769381931,1769227674,3599015,1768962602,3463177,1769381938,1769381935,1769381934,1769381932,3410377,2067242,3381901,3381903,373969,2072395,373971,373990,374039,3381910,3381911,3381912,382134,378711,193010,162269,143775,127673,120041,89443,52732,382512,383210,1769274527,1769004670,1768958960,3599311,3365855,2314604,2080987,2073790,385907,115384,374057,377936,380029,382560,382852,383962,33806,378041,380287,385729,385760,388406,389153,381833,83126,386773,389072,389080,389077,43542,52726,375183,382821,384595,385074,386954,373818,376387,378307,379302,382777,384646,384670,385137,385976,386073,386347,2342433,3550893,1769699970,2095102,2095107,2017034,2286524,2342421,2286523,3338183,1768988423,2286527,2380720,3464931,1176114,1769334977,2155384,1769839800,3225258,2091936,1769334987,3187867,2095104,3413844,1769072635,1007695,3636957,3467770,1768940269,1769292436,1769850021,1769102619,3409064,1769870173,1769850022,1769850019,1769463117,3446206,2028877,2136483,1769072646,1769291745,1769072643,1769113798,196142,3187959,2079575,2286522,2079581,2385273,1769673320,3513664,1769071426,3502285,1769801604,1769801605,3484274,1769303054,1769303056,1769303057,1769303058,1769303059,1769303060,1769303061,1769303062,1769303055,1768914983,378646,3586293,1769830111,1769830112,1769830113,1769830114,1769830115,1769830116,1769830117,1769830118,1769830119,1769830120,1769570445,);
    
//复制结束
 
//下面的代码不需要修改 
var XHR; //定义一个全局对象 
function xm_download(id){  
    if(window.ActiveXObject){//IE的低版本系类 
        XHR=new ActiveXObject('Microsoft.XMLHTTP');
    }else if(window.XMLHttpRequest){//非IE系列的浏览器,但包括IE7 IE8 
        XHR=new XMLHttpRequest(); 
    } 
    XHR.open("GET","download.php?id="+id,true);        
    XHR.send(null); 
} 
for (var i=0;i<song.length;i++) {
    xm_download(song[i]);
}
</script>
$data = 'pid=&ptype=&song_count=1&id='.$_GET['id'];        
$cookie_file = dirname(__FILE__).'/cookie.txt'; //登陆COOKIES文件地址
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, "http://www.xiami.com/download/song");
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_COOKIEFILE, $cookie_file);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);    
$data = curl_exec($curl);
curl_close($curl);

</p>
<h4>四、打开虾歌查询订单</h4>
<p>最后一步是打开虾歌,选择“文件”→“检查未完成下载”,静候片刻你就可以欢呼了!之后静静等待虾歌批量下载成功就好了。</p>