使用脚本从网页批量下载文件

Before

Bash Shell具备强大的功能,结合linux下的很多命令行工具,可以高效地完成很多任务。

比如,在做安卓应用的兼容性测试中,需要获取大量的应用给待测设备安装,那么在这种情况下,写一个脚本,可以高效地完成这个任务。以此为例,这篇博客的任务就是,使用脚本从网页批量下载安卓应用APK文件。

Html

我计划下载的文件在这个网址,这是百度的安卓应用商店下面的一个排行榜。

查看这个html页面可以看到下面显示的应用存在以下部分:


<div class="app-detail">
<div class="icon">
<img data-default="/static/mobres/img/default_app_110.png" class="imagefix" src="http://timg01.baidu-img.cn/timg?mobres&quality=80&size=b220_220&sec=1473090639&di=31d539f1c8c56754a29e047f5d2b9a5a&src=http%3A%2F%2Fb.hiphotos.bdimg.com%2Fwisegame%2Fpic%2Fitem%2Fd78f8c5494eef01fc33f1f7de8fe9925bc317d5b.jpg" alt="优酷" />
<div class="mask mask1 mask-110"></div>
</div>
<p class="name">优酷</p>
<p class="down-size">
<span class="down">5.4亿下载</span>
<span class="size">31.5MB</span>
</p>
<!-- -->
<p class="down-btn">
<span class="inst-btn-big quickdown"
onclick="bd_app_dl_quick(this,event);"
data-action="software"
data-mod="tophot"
data-tj="software_9828067_1827869107_优酷"
data-pos="13"
data_type="apk"
data_url="http://p.gdown.baidu.com/fce3e533d647c8b825186041cbca68e0217a8ddd6615f593dbda4263bf62b22c3fd421044f23ba016ef241b186d81398fbfc2732604a6f4084a5f5a2f9f03f3dc58f29b5df2eeb11ce26a71c4ba0fd4d07d0b98eecdbb37652311d4a11be76002a2ea73b922207bcbf36f315f247778141d6de44c67c9b69d36d23057c857205a2b41e15ccc414e3160664fa576ae82f"
data_name="优酷"
data_detail_type="app"
data_package="com.youku.phone"
data_versionname="5.8.2"
data_icon="http://d.hiphotos.bdimg.com/wisegame/pic/item/5a12b31bb051f819fd2d10f2d2b44aed2e73e77a.jpg"
data_from="1015019e"
data_size="33028082">
<em>装进手机</em>
</span>
</p>
<!-- -->
</div>

思路

可以看到应用的信息都在里面,包括应用名称data_name, 应用版本data_versionname, 应用下载链接data_url.

所以进行批量下载的思路就简单了,即:抓取以上这些数据,通过命令行工具根据下载链接下载文件。

抓取数据

拿到html文件,然后截取其中的data_name等。方法有很多,这里选择的是一种简单粗暴的,就是用curl或者wget下载html文件,然后用sed,grep和awk处理,重定向出来,形成格式化的数据。

wget http://shouji.baidu.com/rank/features/classic/ -O rank.html
grep data_name rank.html |sed 's/\(data_name="\)\(.*\)\("\)/\2/g' > data_name.txt
grep data_versionname rank.html |sed 's/\(data_versionname="\)\(.*\)\("\)/\2/g' > data_versionname.txt
grep data_url rank.html |sed 's/\(data_url="\)\(.*\)\("\)/\2/g' > data_url.txt

执行完上述命令,抓取数据完毕。

批量下载

这里,有了下载链接,下载其实不难,只是需要做一个更优化的处理,即:

将下载的文件名称与data_name一一对应,这样相较于下载01.apk, 02.apk此类文件名要实用的多。

我选用的方法是使用paste,行合并data_name.txt和data_url.txt,然后配合awk,使用wget就能批量下载这个列表中的所有链接了,具体的命令是:

paste data_url.txt data_name.txt > download.txt
awk '{print "wget " $2 " -O " $1NR".apk"}' download.txt > download.sh

现在批量下载的脚本已经生成了,就是download.sh,执行就可以下载html文件中排行榜第一页的所有30个APK了,download.sh中的内容大致如下:

wget http://p.gdown.baidu.com/1de355fb07a5eaf55d0328f998a2edd2740e8fe381fae980f535a6fbc0c60792f48dc74df78f9238d9059db686f9c43c2c31a7a3d527bff3b3b7539c2de52a00d067450e580cff5d4f2815de5fd07a36ccc5fa5454521302badf164fb16561f522a1ceb19051a4dd7fe7df5fd229372127e8cf583dab83ce1c4c4f87c514c0bbd0888fc0b1042050b4b0a19fa746aa4a1d7598661886eba8c58f29b5df2eeb112ac01969bd8b07c54357e77530d7a9bafbbf1aa869c02385c29bf26270e6430bbd76e7296e19be343d48b72df6e3274451b8636dbbf8ba7a7bc3c546ee7a17913ebd27d9e5c94f66 -O 陌陌26.apk
wget http://p.gdown.baidu.com/63126cbcc934522007a4bc8571c5410a5ad2dc54a2fb8168769940d901a3fc20d1a484cc1071791e734472126abfa8d8f78b66ea0346e4f6682393f5f4d92abe0b3946f998cfdd08d8a069b27932c981e38e7b6d92a0a60b0066ea45886a2c90260006a5b3f089dbd6fac69bf41fd9a48091cc09ac463a011f8dfa991e2a957e16341744a90f9b60566739df029a43258c6d393b93f3adbc05af18611ada55a864e4d1447ae7e0ea2ee5deb1515200ee36f6c00ad1c4318f965dd250a50a058852973e18ac055172cd1ab3a033aadc65e736d23f8bda4d76a4dd7de59b13c175b3c2f5dc362f36bac1250aa4f4faf971098157b535f5fad34d3dfa9f650a70e0b500d39db95e597484ae0c76eb985bdee1dd2088b2f29689e62aaf551d2cda510be12632a71fd5c4eec06a1b25f1898c6b21131600d0a6cd955e42fbe9d0f2a1 -O 天天快报27.apk
wget http://p.gdown.baidu.com/dcd8cf4321c60db1c92d270b8b6f0d935e67e8db81884bf478c75a883c2eb9bf59587b0fdd81cafec7f5dfb750a667ddf7b11d5b13f196d3b10c95e907ef4991e0ad9649d5bb872e6293a1fedd41838a67c5d9ecb2db1558e48ea99f4734df8e80f6d6579a965c76e99159a6556763569f09ba9cc6e64abf65c47812349d9d728ba14da571a9607e9de9d0b8fe1ad432d4957acfd5e7db431538926fee90cd009412087f5cc5f8f9fdab217e46922db392afc98f7df3902d430da6600e0cb400e62aaf551d2cda510be12632a71fd5c4eec06a1b25f1898c6b21131600d0a6cd955e42fbe9d0f2a1 -O QQ空间28.apk

扩展应用

基于上面的思路,很容易实现抓取更多页面,比如上面的排行榜界面实际网址是:

http://shouji.baidu.com/rank/features/classic/list_1.html

那么,list_2, list_3, 写个循环批量抓就可以;别的百度榜单,换个网址抓就可以。

更高级

python啥的,抓取会更方便,本文使用的简单粗暴的方法,需要下载html文件。实测下载这些html文件的时候,下载速度变化比较大,可能出现下载某个html缓慢的情况,同样的问题出现在apk的下载中,因此,wget的参数设置就比较重要了,以后再写篇文章详细记录一下wget的参数选项。

不过,这里顺带提一下,-nc, -c, -t这些参数,分别关于是否覆盖下载和下载重试次数等,比较重要,先到这里吧。

博主,今天22周岁生日,感觉年轻,就是好啊!