|
|
@@ -0,0 +1,89 @@ |
|
|
|
import 'dart:convert'; |
|
|
|
|
|
|
|
import 'package:flutter/material.dart'; |
|
|
|
import 'package:webview_flutter/webview_flutter.dart'; |
|
|
|
import 'package:zhiying_comm/zhiying_comm.dart'; |
|
|
|
|
|
|
|
class TaobaoImageLoader extends StatefulWidget { |
|
|
|
final String url; |
|
|
|
String script; |
|
|
|
final ValueChanged<List<String>> onImagesLoad; |
|
|
|
|
|
|
|
TaobaoImageLoader(this.url, {Key key, this.script, this.onImagesLoad}) |
|
|
|
: super(key: key) { |
|
|
|
this.script = script; |
|
|
|
if (EmptyUtil.isEmpty(this.script)) { |
|
|
|
this.script = |
|
|
|
'CnZhciB6cj17fTsKZnVuY3Rpb24gZ2V0aW4oc3RyMSxzdHIyLHN0cjMpewogICAgc3RyMT1zdHIxKycnO3N0cjI9c3RyMisnJztzdHIzPXN0cjMrJyc7CiAgICB2YXIgdG1wPXN0cjEuc3BsaXQoc3RyMik7CiAgICBpZih0bXBbMV09PW51bGwpdG1wWzFdPScnOwogICAgdG1wPXRtcFsxXS5zcGxpdChzdHIzKTsKICAgIHJldHVybiB0bXBbMF07Cn0KZnVuY3Rpb24gY2hlY2soKXsKICAgIC8qenIudG1wPWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdkZXNjcmlwdGlvbicpLmlubmVySFRNTDsqLwogICAgenIudG1wPWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdKX2Z1bGxDb250ZW50JykuaW5uZXJIVE1MOwogICAgaWYoenIudG1wPT1udWxsfHx6ci50bXA9PScnfHx6ci50bXAuaW5kZXhPZigiLmpwZyIpPT0tMSl7CiAgICAgICAgd2luZG93LnNldFRpbWVvdXQoZnVuY3Rpb24oKXtjaGVjaygpO30sMzAwKTsKICAgICAgICByZXR1cm47CiAgICB9CiAgICB6ci5hbGw9enIudG1wLnNwbGl0KCdzcmM9Jyk7CiAgICB6ci5yZXR1cm5fZGF0YT1bXTsKICAgIHpyLm49LTE7CiAgICBmb3IodmFyIGkgPSAwLGxlbiA9IHpyLmFsbC5sZW5ndGg7IGkgPCBsZW47IGkrKyl7CiAgICAgICAgaWYoaT09MCljb250aW51ZTsKICAgICAgICBpZih6ci5hbGwubGVuZ3RoLTE9PWkpY29udGludWU7CiAgICAgICAgenIudG1wdmFsPXpyLmFsbFtpXTsKICAgICAgICB6ci50bXB2YWw9Z2V0aW4oenIudG1wdmFsLCciJywnIicpOwogICAgICAgIGlmKHpyLnRtcHZhbC5pbmRleE9mKCJiYXNlNjQiKSE9LTF8fHpyLnRtcHZhbC5pbmRleE9mKCJocmVmPSIpIT0tMSljb250aW51ZTsKICAgICAgICBpZih6ci50bXB2YWwuaW5kZXhPZigiaHR0cCIpPT0tMSl6ci50bXB2YWw9Imh0dHBzOiIrenIudG1wdmFsOwogICAgICAgIHpyLm4rKzsKICAgICAgICB6ci5yZXR1cm5fZGF0YVt6ci5uXT16ci50bXB2YWw7CiAgICB9CiAgICB6ci5yZXR1cm5fZGF0YT1KU09OLnN0cmluZ2lmeSh6ci5yZXR1cm5fZGF0YSk7CiAgICAvLyBkb2N1bWVudC5ib2R5LmlubmVySFRNTD16ci5yZXR1cm5fZGF0YTsKICAgIExvYWRlci5wb3N0TWVzc2FnZSh6ci5yZXR1cm5fZGF0YSk7CiAgICAvLyBqaCh6ci5yZXR1cm5fZGF0YSwiIik7Cn0KdHJ5e3dpbmRvdy5zZXRUaW1lb3V0KGZ1bmN0aW9uKCl7Y2hlY2soKTt9LDApO30KY2F0Y2goZXJyKXtkb2N1bWVudC5ib2R5LmlubmVySFRNTD1KU09OLnN0cmluZ2lmeShlcnIpO30KCg=='; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
@override |
|
|
|
_TaobaoImageLoaderState createState() => _TaobaoImageLoaderState(); |
|
|
|
} |
|
|
|
|
|
|
|
class _TaobaoImageLoaderState extends State<TaobaoImageLoader> { |
|
|
|
WebViewController _webViewController; |
|
|
|
|
|
|
|
List<String> _images = []; |
|
|
|
|
|
|
|
@override |
|
|
|
Widget build(BuildContext context) { |
|
|
|
return Scaffold( |
|
|
|
appBar: AppBar( |
|
|
|
title: const Text('抓取淘宝详情图'), |
|
|
|
), |
|
|
|
// We're using a Builder here so we have a context that is below the Scaffold |
|
|
|
// to allow calling Scaffold.of(context) so we can show a snackbar. |
|
|
|
body: Builder(builder: (BuildContext context) { |
|
|
|
return WebView( |
|
|
|
initialUrl: widget.url, |
|
|
|
javascriptMode: JavascriptMode.unrestricted, |
|
|
|
onWebViewCreated: (WebViewController webViewController) { |
|
|
|
_webViewController = webViewController; |
|
|
|
}, |
|
|
|
// TODO(iskakaushik): Remove this when collection literals makes it to stable. |
|
|
|
// ignore: prefer_collection_literals |
|
|
|
javascriptChannels: <JavascriptChannel>[ |
|
|
|
_imageLoaderJavascriptChannel(context), |
|
|
|
].toSet(), |
|
|
|
navigationDelegate: (NavigationRequest request) { |
|
|
|
print('allowing navigation to $request'); |
|
|
|
return NavigationDecision.navigate; |
|
|
|
}, |
|
|
|
onPageStarted: (String url) { |
|
|
|
print('Page started loading: $url'); |
|
|
|
}, |
|
|
|
onPageFinished: (String url) { |
|
|
|
_loadImages(); |
|
|
|
}, |
|
|
|
gestureNavigationEnabled: true, |
|
|
|
); |
|
|
|
}), |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
void _loadImages() { |
|
|
|
String js = EncodeUtil.decodeBase64(widget.script); |
|
|
|
_webViewController.evaluateJavascript(js).then((result) {}); |
|
|
|
} |
|
|
|
|
|
|
|
JavascriptChannel _imageLoaderJavascriptChannel(BuildContext context) { |
|
|
|
return JavascriptChannel( |
|
|
|
name: 'Loader', |
|
|
|
onMessageReceived: (JavascriptMessage message) { |
|
|
|
if (widget.onImagesLoad != null) { |
|
|
|
List list = jsonDecode(message.message); |
|
|
|
if (list.length != _images.length) { |
|
|
|
Future.delayed(Duration(milliseconds: 1000), () { |
|
|
|
_loadImages(); |
|
|
|
}); |
|
|
|
_images = list.map((item) => item.toString()).toList(); |
|
|
|
widget.onImagesLoad(_images); |
|
|
|
} else { |
|
|
|
print('图片抓取结束'); |
|
|
|
} |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
} |