那年那月那时,我闲了蛋疼去刷机,于是给整机数据备份了。刷机的时候脑壳发热把数据全清了,备份的数据也没电脑备份,相册查看时每次都要同步不下载,然后官网还没有批量下载,我真想哎呦,艾瑞巴蒂在你头上暴扣,漏福来儿,我也不是爱豆。(代码与jar包文章结尾)
言归正传,屁话不多说。由于能力有限,找不出官网的密码加密,所以也就不麻烦了,因为还附带了一些参数,直接登陆官网,请求相册,取到cookie。
初次请求相册
请求地址https://cloud.h2os.com/gallery/pc/listNormalPhotos
请求参数:size=100&state=active&smallPhotoScaleParams=image/resize,m_mfit,h_250,w_250&originalPhotoScaleParams=image/resize,m_mfit,h_1300,w_1300
返回json,photos节点就是我们要的数据,附带图片id,和压缩过的图片地址originalPhotoUrl,smallPhotoUrl。这个originalPhotoUrl还真是女人的嘴,骗人的鬼,original是原件,原来的意思,让我以为是无压缩文件。等下载下来看文件大小才发现我就是个憨憨,不或许我就是个弟弟。待会需要这个id得到真实的地址。
继续找规律发现返回的json数据中lastMatchedMoment这个数据是需要用来下次请求用的,时间节点,作为下次请求数据中的游标,还有这个参数realPhotoIndex,不晓得干嘛用的。不管他,拿他就对了。
我们继续向下滚动,还会出现listNormalPhotos这个请求,因为每次加载有限,第二次请求就要基础数据带上面的参数了。
好了,这个地方就已经获得所有图片的信息,通过json解析拿到图片id,请求真实地址。然后下载,美滋滋。
请求地址:https://cloud.h2os.com/gallery/pc/getRealPhotoUrls
参数:ids:=["图片id"]
这个时候根据返回的数据,拿到图片无压缩地址。
ps:cookie有时效性,失效后台会爆403的错误,这个时候重新登陆网站后获取新cookie替换即可。
成果:
遇到的问题:
1.请求返回403,由于cookie失效导致的,好像还有浏览器标识,用火狐得到解决,之后的403都是cookie失效。
2.请求无压缩地址返回500,哎,瞎了狗眼,参数用k:v,其实是k=v。纳闷的是请求图片列表时参数用的是冒号,竟然能有数据返回。
3.解析json,拿到图片id。由于返回的数据是json套json数组,时间节点又不固定,取值就很烦,可把我累坏了,本来基础就差,刚玩java。不过世上无难事,只怕有心人,终于还是查资料找到了。
总结:真的是不想手动下载,跑来搞了这么个东西。希望也可以帮到需要这个东西的加友,一加官方你可长点心吧,同步相册竟然不下载,我们想手动下载还没有批量,我也是佛了。
以下是java代码(你们只需要替换cookie和保存路径):
import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.io.Reader; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import sun.misc.BASE64Encoder; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; /** * <p>Title: Test.java</p> * <p>Description:Oneplus相册爬虫(无压缩) </p> * <p>Company: www.zhguo.vip</p> * @author zhenghuiguo * @date 2019-8-23 * @version 1.0 * Readme:请在官网登录https://cloud.h2os.com,点击相册,请求后拿到cookie替换到本程序cookie。 */ public class Test { public static void main(String[] args) throws Exception{ int count=0; ArrayList<String> arr= new ArrayList<String>(); Map<String, String> hashmap=new HashMap<String, String>(); //文件保存路径 String saveImgPath="C://Users//zhg//Desktop//img//"; //获取相册列表 //cursor=20190822&photoIndex=1 //lastMatchedMoment realPhotoIndex //初始化数据 String data="size=100&state=active&smallPhotoScaleParams=image/resize,m_mfit,h_250,w_250&originalPhotoScaleParams=image/resize,m_mfit,h_1300,w_1300"; String urlpath="https://cloud.h2os.com/gallery/pc/listNormalPhotos"; String cookie="此处需要替换"; while(true){ //post请求得到json数据 String postServer = PostServer(data, urlpath, cookie); //重置data基础数据 data="size=100&state=active&smallPhotoScaleParams=image/resize,m_mfit,h_250,w_250&originalPhotoScaleParams=image/resize,m_mfit,h_1300,w_1300"; System.out.println("postServer"+"======"+postServer); JSONObject jobj = JSON.parseObject(postServer); System.out.println("下一个时间段"+jobj.getString("lastMatchedMoment")+"....."+"下一个index"+jobj.getString("realPhotoIndex")); //获取下一页游标 String lastMatchedMoment=(jobj.getString("lastMatchedMoment"))== null?null:jobj.getString("lastMatchedMoment"); String photoIndex=(jobj.getString("realPhotoIndex"))== null?null:jobj.getString("realPhotoIndex"); //判断下一页是否有值 if(lastMatchedMoment!=null&&!"".equals(lastMatchedMoment)&&photoIndex!=null&&!"".equals(photoIndex)){ data=data+"&cursor="+lastMatchedMoment+"&photoIndex="+photoIndex; } //System.out.println("name"+jobj.get("photos")); //拿到photos节点 JSONObject photosjson = jobj.getJSONObject("photos"); //将photosjson赋值给map1,便于后面遍历时间节点。由于时间节点不固定,无法准确拿到json数据。 Map map1 = photosjson; //遍历出key值存入arr for (Object o : map1.entrySet()) { Map.Entry<String,JSONArray> entry = (Map.Entry<String,JSONArray>)o; arr.add(entry.getKey()); } //遍历每个时间节点的值 for (int i = 0; i < arr.size(); i++) { JSONArray photos = photosjson.getJSONArray(arr.get(i)); //遍历每个时间节点下的多个照片 for (int j = 0; j < photos.size(); j++) { JSONObject phototimeJson = (JSONObject) photos.get(j); String title=phototimeJson.getString("title"); //得到图片id,存入hashmap<"title","id"> String img_id=phototimeJson.getString("id"); hashmap.put(title, img_id); } } for(String key : hashmap.keySet()){ String realPathJson = Downimg.getRealPath(hashmap.get(key), cookie); JSONObject j=JSONObject.parseObject(realPathJson); String realPath = j.getString(hashmap.get(key)); Downimg.downloadPicture(realPath, saveImgPath+key); count++; } if(lastMatchedMoment.equals("EOF")){ System.out.println("下载完成"+">>>>>文件个数:"+count+"个"); return ; } //清空数据 map1.clear(); hashmap.clear(); arr.clear(); System.out.println("清空完成"); } } //Post请求 public static String PostServer(String data,String urlpath,String cookie){ PrintWriter out = null; BufferedReader is = null; String result = ""; try { URL url = new URL(urlpath); //打开和url之间的连接 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestProperty("accept", "*/*"); conn.setRequestProperty("connection", "Keep-Alive"); conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:68.0) Gecko/20100101 Firefox/68.0"); conn.setRequestProperty("Host", "cloud.h2os.com"); conn.setRequestProperty("referer", "https://cloud.h2os.com/"); conn.setRequestProperty("Cookie", cookie); conn.setRequestMethod("POST");//GET和POST必须全大写 conn.setDoOutput(true); conn.setDoInput(true); out = new PrintWriter(conn.getOutputStream());//获取URLConnection对象对应的输出流 out.print(data);//发送请求参数即数据 out.flush();//缓冲数据 // 定义BufferedReader输入流来读取URL的响应 is = new BufferedReader( new InputStreamReader(conn.getInputStream())); String line; while ((line = is.readLine()) != null) { result += line; } } catch (Exception e) { System.out.println("发送 POST 请求出现异常!"+e); e.printStackTrace(); } finally{ try{ if(out!=null){ out.close(); } if(is!=null){ is.close(); } } catch(IOException ex){ ex.printStackTrace(); } } return result; } //根据id得到无压缩图片地址 public static String getRealPath(String Imgid,String cookie){ String urlpath="https://cloud.h2os.com/gallery/pc/getRealPhotoUrls"; String data="ids=[\""+Imgid+"\"]"; // System.out.println("imgId"+"====="+data); String realImgPath = PostServer(data, urlpath, cookie); return realImgPath; } //链接url下载图片 public static void downloadPicture(String urlPath,String savePath) { URL url = null; try { url = new URL(urlPath); DataInputStream dataInputStream = new DataInputStream(url.openStream()); File file=new File(savePath); if(!file.exists()){ FileOutputStream fileOutputStream = new FileOutputStream(file); ByteArrayOutputStream output = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int length; while ((length = dataInputStream.read(buffer)) > 0) { output.write(buffer, 0, length); } BASE64Encoder encoder = new BASE64Encoder(); String encode = encoder.encode(buffer);//返回Base64编码过的字节数组字符串 // System.out.println(encode); fileOutputStream.write(output.toByteArray()); dataInputStream.close(); fileOutputStream.close(); }else{ System.out.println("文件已存在"); } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
jar包下载地址:https://cloud.189.cn/t/Nvi2uanANRzu(访问码:zs99)
运行后直接浏览器打开:localhost,填写cookie使用。