Browse Source

1223 添加新的淘宝商品图片获取方法

tags/0.0.3+1
23028876916@qq.com 4 years ago
parent
commit
3ee96bfcfe
3 changed files with 183 additions and 2 deletions
  1. +45
    -0
      lib/util/taobao/goods_pic_model.dart
  2. +137
    -2
      lib/util/taobao/taobao_loader.dart
  3. +1
    -0
      pubspec.yaml

+ 45
- 0
lib/util/taobao/goods_pic_model.dart View File

@@ -0,0 +1,45 @@
class GoodsPicModel {
String api;
Data data;
List<String> ret;
String v;

GoodsPicModel({this.api, this.data, this.ret, this.v});

GoodsPicModel.fromJson(Map<String, dynamic> json) {
api = json['api'];
data = json['data'] != null ? new Data.fromJson(json['data']) : null;
ret = json['ret'].cast<String>();
v = json['v'];
}

Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['api'] = this.api;
if (this.data != null) {
data['data'] = this.data.toJson();
}
data['ret'] = this.ret;
data['v'] = this.v;
return data;
}
}

class Data {
List<String> pages;
List<String> images;

Data({this.pages, this.images});

Data.fromJson(Map<String, dynamic> json) {
pages = json['pages'].cast<String>();
images = json['images'].cast<String>();
}

Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['pages'] = this.pages;
data['images'] = this.images;
return data;
}
}

+ 137
- 2
lib/util/taobao/taobao_loader.dart View File

@@ -1,9 +1,22 @@
import 'dart:convert';
import 'dart:io';

import 'package:dio/dio.dart';
import 'package:dio_cookie_manager/dio_cookie_manager.dart';
import 'package:zhiying_comm/util/taobao/goods_pic_model.dart';
import 'package:zhiying_comm/zhiying_comm.dart';

import 'package:cookie_jar/cookie_jar.dart';
import 'package:convert/convert.dart';
import 'package:crypto/crypto.dart';

// 淘宝详情图抓取
class TaobaoLoader {
static Future<List<String>> loadImages(String id) async {
return _loadImagesNew(id);
}

static Future<List<String>> _loadImages1(String id) async {
String url =
'http://h5api.m.taobao.com/h5/mtop.taobao.detail.getdesc/6.0/?api=mtop.taobao.detail.getdesc&appkey=12574478&data={"type":"0","f":"TB1AsvbfnqWBKNjSZFx8qwpLpla","id":"${id.toString()}"}&dataType=json&jsv=2.4.11&sign=e93a97b7e9a9a459297f4e689051c895&t=1538180732308&type=json';
Dio dio = Dio();
@@ -21,8 +34,7 @@ class TaobaoLoader {
if (image != null && image != '') {
if (image.startsWith('//')) {
images.add('http:' + image);
} else
if (image.startsWith('https://') || image.startsWith('http://')) {
} else if (image.startsWith('https://') || image.startsWith('http://')) {
images.add(image);
}
}
@@ -31,7 +43,130 @@ class TaobaoLoader {
Logger.error(err);
}

return images;
}

///方法说明:通过破解淘宝签名接口获取商品详情图片
///流程:第一次请求接口拿到cookie数据,拼接签名数据,第二次请求接口拿到图片连接数据
///方法地址
///https://darktiantian.github.io/%E8%AE%B0%E4%B8%80%E6%AC%A1%E6%B7%98%E5%AE%9D%E6%8E%A5%E5%8F%A3sign%E7%AD%BE%E5%90%8D%E7%A0%B4%E8%A7%A3/
static Future<List<String>> _loadImagesNew(String id) async {
String data = "{\"item_num_id\":\"" + id + "\"}";
String time = DateTime.now().millisecondsSinceEpoch.toString();
String appkey = "12574478"; //文章中使用的appkey
String url = "https://h5api.m.taobao.com/h5/mtop.wdetail.getitemdescx/4.9/?jsv=2.4.11&appKey=$appkey&t=$time"
"&sign=FAKE_SIGN_WITH_ANYTHING&api=mtop.wdetail.getItemDescx&v=4.9&type=jsonp&dataType=jsonp&callback=mtopjsonp2&data="
"$data";
Logger.log("url: " + url);
Dio dio = Dio(BaseOptions(responseType: ResponseType.plain));
var cookieJar = CookieJar();
//dio绑定cookie管理器,以便第一次请求后获取cookie数据
dio.interceptors.add(CookieManager(cookieJar));
Map<String, dynamic> headers = new Map();
headers['User-Agent'] =
"Mozilla/5.0 (iPhone; CPU iPhone OS 9_3_4 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13G35 Safari/601.1";
Options options = new Options(headers: headers);
//首次请求获取cookie
await dio.get(url, options: options);

String token = "";
String _m_h5_tk = "";
String enc_token = "";
//根据第一次请求后返回的cookie拿到需要的数据
List<Cookie> cookieList = cookieJar.loadForRequest(Uri.parse(url));
for (int i = 0; i < cookieList.length; i++) {
Cookie cookie = cookieList[i];
Logger.log(cookie.name + " : " + cookie.value);
if ("_m_h5_tk" == cookie.name) {
_m_h5_tk = cookie.value;
List<String> token_with_time = cookie.value.split("_");
if (token_with_time.length > 0) {
token = token_with_time[0];
}
}
if ("_m_h5_tk_enc" == cookie.name) {
enc_token = cookie.value;
}
}

//设置第二次请求的cookie数据
Map<String, dynamic> headers2 = new Map();
headers2['cookie'] = "_m_h5_tk=$_m_h5_tk; _m_h5_tk_enc=$enc_token;"
"User-Agent=Mozilla/5.0 (iPhone; CPU iPhone OS 9_3_4 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13G35 Safari/601.1";
Options options2 = new Options(headers: headers2);

//设置签名
String time2 = DateTime.now().millisecondsSinceEpoch.toString();
String sign = token + "&" + time2 + "&" + appkey + "&" + data;
String mySign = string2Md5(sign);

//设置第二次请求的url
String url2 = "https://h5api.m.taobao.com/h5/mtop.wdetail.getitemdescx/4.9/?jsv=2.4.11&appKey=$appkey&t=$time2"
"&sign=$mySign&api=mtop.wdetail.getItemDescx&v=4.9&type=jsonp&dataType=jsonp&callback=mtopjsonp2&data="
"$data";

//进行第二次网络请求拿到图片数据
Dio dio2 = Dio(BaseOptions(responseType: ResponseType.plain));
Response response2 = await dio2.get(url2, options: options2);
Logger.log(response2.data);

//根据返回的数据,拼接图片链接数据
String result2 = response2.data;
String object = result2.substring(result2.indexOf("(") + 1, result2.length - 1);
Logger.log(object);
var json = jsonDecode(object);
GoodsPicModel model = GoodsPicModel.fromJson(json);
List<String> images = List();
if (null != model.data.images && model.data.images.length > 0) {
/**
* images字段的数据,在前面拼接好https:就可以作为商品详情的图片链接使用了
*/
List<String> Images = model.data.images;
List<String> mPicList = [];
for (String pic in Images) {
if (pic.isNotEmpty) {
mPicList.add("https:" + pic);
}
}
Logger.log("mPicList图片:" + mPicList.length.toString() + "\n" + mPicList.toString());
if (mPicList.length > 0) {
return mPicList;
}
} else {
if (null != model.data.pages && model.data.pages.length > 0) {
/**
* pages字段的数据,数组中可能有多张图片的链接数据,以<img></img>标签框起来的
* 先去掉前面的<img>标签,再以</img>标签分割各个图片链接数据,
* 最后每个数据拼接上https:就可以作为商品详情图片链接返回了
* 经测试images字段和pages字段的数据是相同的,所以取一个字段的数据返回就可以了
*/
List<String> pages = model.data.pages;
List<String> mPicList = [];
for (String pic in pages) {
String pic1 = pic.replaceAll("<img>", "");
List<String> pic2 = pic1.split("</img>");
if (pic2.length > 0) {
for (String s in pic2) {
if (s.isNotEmpty) {
mPicList.add("https:" + s);
}
}
}
}
Logger.log("图片2:" + mPicList.length.toString() + "\n" + mPicList.toString());
if (mPicList.length > 0) {
return mPicList;
}
}
}

return images;
}

// md5 加密
static String string2Md5(String data) {
var content = new Utf8Encoder().convert(data);
var digest = md5.convert(content);
return hex.encode(digest.bytes);
}
}

+ 1
- 0
pubspec.yaml View File

@@ -74,6 +74,7 @@ dependencies:
#保存文件到相册
save_image: ^1.0.1

dio_cookie_manager: 1.0.0


dev_dependencies:


Loading…
Cancel
Save