本帖最后由 孤云 于 2018-10-18 22:00 编辑
由于最近想换壁纸,但是又懒得去翻帖子一个个的看,所以自已动手写了个简单的app下载图片。
由于我不会安卓,所以写得很多bug、简陋,下载速度慢(可以用多线程优化,不会安卓的我不知道怎么写),而且只支持三楼的链接才能爬取。
安卓跟web爬虫基本上没什么区别,都是通过请求获得响应。Android返回的是json格式的字符串,web返回的是页面。
这里思路就是通过抓包抓取请求,查看他的响应内容,将我们需要的数据取出来就ok了。
下面开始教程:
需要用到抓包,手机电脑都行,因为是android爬虫,所有就以手机为例了,这里我用的是数据包捕获抓包。
1.打开三楼的一篇帖子,打开抓包 软件
2.开始抓包,并刷新一下帖子,然后从大到小从数据包里找到请求。
找到下图这样的内容,title是标题的意思,然后跟帖子的标题对比一下,如果是一样的就是他了。
3.将图片中蓝色区域的那一块复制出来,将Host和GET后面的以host在前,get在后的方式拼接起来,不要host和get!(注意空格,得到的链接可以先拿到浏览器试下)
最后获得这样的一个链接。
[Java] 纯文本查看 复制代码 http://floor.huluxia.com/post/detail/ANDROID/2.2?platform=2&gkey=440000&app_version=3.5.0.83.2&versioncode=20141384&market_id=floor_tencent&_key=6DBDBD8B6601BFF3BC3F87DF526DD80EABA9E4557F5F7B8745B40F9E7075239D052447C61C5F77EEF718DE489A7A21DB49D0F5B90A55F166&device_code=%5Bw%5D02%3A00%3A00%3A00%3A00%3A00-%5Bi%5D864447034701670-%5Bs%5D89860040221578535925&post_id=32336552&page_no=1&page_size=20&doc=1
将链接输入到浏览器得到的如下图。
4.将链接复制到软件中,点击下载即可。(速度有点慢)
可以将链接中的page_no的修改控制从第几页开始。
下载完成效果图
教程完毕。
最后附上软件,和源码。
软件链接:https://pan.baidu.com/s/1pQlXarBYNZHkOV5_nUjvxg 提取码:4q2w
[Java] 纯文本查看 复制代码 public class MainActivity extends AppCompatActivity {
private Thread t;//线程
private static int page = 0;//页数
private static int countPage = 1;//总数
private static int downloading = 0;//下载数
private EditText et_main_url;
private Button btn_main_download;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_main_url = (EditText) findViewById(R.id.et_main_url);
btn_main_download = (Button) findViewById(R.id.bt_main_download);
if (Build.VERSION.SDK_INT >= 23) { //安卓6.0以上需要允许授权才能写入图片到本地
int REQUEST_CODE_CONTACT = 101;
String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE};
//验证是否许可权限
for (String str : permissions) {
if (this.checkSelfPermission(str) != PackageManager.PERMISSION_GRANTED) {
//申请权限
this.requestPermissions(permissions, REQUEST_CODE_CONTACT);
}
}
}
}
//按钮的点击事件
public void download(View v){
String text = et_main_url.getText().toString();
if(text != null && !"".equals(text)) {
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){//判断是否有读写权限
Toast.makeText(MainActivity.this, "开始下载...", Toast.LENGTH_SHORT).show();
new MainActivity().getAllLinks(text);
btn_main_download.setEnabled(false);//设置按钮不能点击
btn_main_download.setText("正在下载");//设置文字
}else {
Toast.makeText(this, "没有权限!", Toast.LENGTH_LONG).show();
}
}else {
Toast.makeText(MainActivity.this, "链接不能为空!", Toast.LENGTH_LONG).show();
}
}
/**
* 获取所有图片链接
* @return
*/
public void getAllLinks(final String str){
//因为安卓不能在主线程执行耗时的网络操作,所以需要开个分线程
t =new Thread(() ->{ //jdk1.8新特性lambda表达式
try {
int count = 0;//定义一个变量控制链接的截取和给总页数赋值
for (; page < countPage; page++) {
String link = str;//将传入的参数赋值给link
String page_no = link.substring(link.indexOf("page_no"));//字符串截取
if(count == 0) {
//当第一次进入方法时,将用户输入的链接页数截取出来
page = Integer.valueOf(page_no.substring(page_no.indexOf("=") + 1, page_no.indexOf("&")));
}
//将链接截取拼接成新的链接
page_no = page_no.substring(0, page_no.indexOf("=") + 1);
link = link.substring(0, link.lastIndexOf("page_no"));
link = link + page_no + page;
//连接到url
Document doc = Jsoup.connect(link).timeout(10000).ignoreContentType(true).get();
//将返回回来的json字符串转换
JSONObject json = JSONObject.fromObject(doc.text());
//如果是第一页,就获取主题的图片
if (page == 1) {
String theme = json.getJSONObject("post").getString("images");//主题的图片
}
//如果是第一进入方法就获取总页数的值,并将count的值改变
if(count == 0) {
countPage = json.getInt("totalPage");//获取总页数
count = count + 1;
}
//获取装有图片的json数组
JSONArray jsonArray = json.getJSONArray("comments");
//遍历json数组
for (int i = 0; i < jsonArray.size(); i++) {
//获取到图片的链接,因为是多个图片连接的,所以将链接拆分
String images = jsonArray.getJSONObject(i).getString("images");
String imgLink = images.replaceAll("\\[", "").replaceAll("]", "");
if (imgLink != null && !"".equals(imgLink)) {
//以","将链接分成一个数组
String[] strs = imgLink.split(",");
for (int j = 0; j < strs.length; j++) {
//链接格式有问题,需要处理
strs[j] = strs[j].substring(1, strs[j].lastIndexOf("\""));
download(strs[j]);//调用下载方法
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
});
t.start();
}
/**
* 下载图片
* @param link
*/
public void download(String link){
try {
URL url = new URL(link);//定义一个URL
//输入流,读取图片
DataInputStream dis = new DataInputStream(url.openStream());
byte[] bytes = new byte[1024];
//截取后缀
String suffix = link.substring(link.lastIndexOf("."));
//获取用户的sd卡目录
File directory = Environment.getExternalStorageDirectory();
File file = new File(directory + "/guyun/");
if(!file.exists()){
file.mkdirs();
}
Log.e("输出目录",file.getAbsolutePath());
//输出流,用时间的毫秒值当图片名称
FileOutputStream fos = new FileOutputStream(new File(file.getAbsolutePath()+ "/" + new Date().getTime() + suffix));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
//写出图片
int len = -1;
while ((len = dis.read(bytes)) != -1){
baos.write(bytes,0,len);
}
fos.write(baos.toByteArray());
downloading ++;
dis.close();
baos.close();
fos.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
|