更多>>关于我们
西安鲲之鹏网络信息技术有限公司从2010年开始专注于Web(网站)数据抓取领域。致力于为广大中国客户提供准确、快捷的数据采集相关服务。我们采用分布式系统架构,日采集网页数千万。我们拥有海量稳定高匿HTTP代理IP地址池,可以有效获取互联网任何公开可见信息。
您只需告诉我们您想抓取的网站是什么,您感兴趣的字段有哪些,你需要的数据是哪种格式,我们将为您做所有的工作,最后把数据(或程序)交付给你。
数据的格式可以是CSV、JSON、XML、ACCESS、SQLITE、MSSQL、MYSQL等等。
更多>>技术文章
在模拟操作安卓App进行数据采集的时候,我们需要给安卓设备(或模拟器)设置HTTP代理,手动设置的方法网上有很多介绍(WIFI属性->高级选项->代理设置)。对于需要频繁切换代理IP的情况,手动设置显然不太可能,那么如何通过程序进行HTTP代理设置呢?
前面我们曾介绍过“Drony + 动态PAC文件”实现安卓设备下的自动代理切换(http://www.site-digger.com/html/articles/20190113/694.html),但是该方案也无法直接通过程序来控制。
下面再介绍两种可以通过程序控制安卓设备HTTP代理的方案:
1.使用AndroidProxySetter APP
通过adb调用AndroidProxySetter这个安卓APP,来实现代理的设置和清除功能,不需要ROOT权限。关于AndroidProxySetter的使用方法,详见这里:https://github.com/jpkrause/AndroidProxySetter,APK下载地址:https://github.com/jpkrause/AndroidProxySetter/releases。
下面是用法举例:
# 设置设备的代理为192.168.1.8:8888 adb shell am start -n tk.elevenk.proxysetter/.MainActivity -e host 192.168.1.8 -e port 8888 # 清除代理配置 adb shell am start -n tk.elevenk.proxysetter/.MainActivity -e clear true
PS:上述命令中未指定WIFI名称,proxysetter将会使用默认连接的WIFI。
注意:实测发现,该方案只支持安卓4.x及以下版本。
由于proxysetter依赖于https://github.com/shouldit/android-proxy/tree/master/android-proxy-library,而在android-proxy-library主页有说明:"supported all Android versions: 1.x - 2.x - 3.x - 4.x"。
2.通过配置系统的http_proxy参数
注意:该方法适合于安卓5.x及以上版本。
下面是用法举例:
设置代理为192.168.1.8:8888:
adb shell settings put global http_proxy 192.168.1.8:8888
PS:所有安卓版本都支持。
安卓4.x及以下版本请慎用该方法,一旦设置代理后,无法轻易清除。
清除代理:
adb shell settings delete global http_proxy adb shell settings delete global http_proxy_host adb shell settings delete global http_proxy_port
PS:只有安卓5.x及以上版本才支持delete命令。
安卓4.x版本清除http_proxy代理设置的方法可以参考:https://stackoverflow.com/questions/31807559/undo-setting-proxy-via-settings-global-in-android,需要ROOT权限。
清除代理后需要重启设备才能生效。
上述命令实际上是对/data/data/com.android.providers.settings/databases/settings.db这个SQLite数据库进行了添加/删除操作。
如下图所示为settings.db中http代理的相关参数:
总结一下,Android 4.x及以下版本,使用AndroidProxySetter,Andorid 5.x及以上版本使用http_proxy属性。下面给出一个我们在项目中使用的Python代码片段,它能够根据设备的安卓版本,自动选用合适的方法进行代理设置和代理清除。
# coding: utf-8 import os import time import subprocess class ADBProxyManager: """通过ADB设置安卓设备的HTTP代理 """ def __init__(self): # 设备安卓主版本号 self.device_android_version = self.get_device_android_version() def get_device_android_version(self): """获取设备的安卓版本 """ ret = subprocess.check_output('adb shell getprop ro.build.version.release', shell=True) if '.' in ret: return int(ret.strip().split('.')[0]) else: raise Exception(u'获取设备的安卓版本号失败.') def ensure_install_proxysetter(self): """确保安装了AndroidProxySetter """ while True: apps_installed = subprocess.check_output('adb shell pm list packages').splitlines() if 'package:tk.elevenk.proxysetter' not in apps_installed: print u'该手机尚未安装"WIFI代理设置器", 将自动安装.' os.system('adb install ./bin/proxy-setter.apk') time.sleep(10) else: break def set_proxy(self, host, port): """设置代理 host - 代理IP; port - 代理端口; """ if self.device_android_version <= 4: # 安卓4.x之下可以使用AndroidProxySetter来设置代理 print u'当前设备安卓版本号为{}.*, 将使用AndroidProxySetter来配置代理'.format(self.device_android_version) # 确保安装了AndroidProxySetter self.ensure_install_proxysetter() os.system('adb shell am start -n tk.elevenk.proxysetter/.MainActivity -e host {} -e port {}'.format(host, port)) time.sleep(10) else: # 安卓4.x之上版本使用global http_proxy参数来设置代理 print u'当前设备安卓版本号为{}.*, 将通过系统global http_proxy属性来配置代理'.format(self.device_android_version) os.system('adb shell settings put global http_proxy {}:{}'.format(host, port)) time.sleep(5) def clear_proxy(self): """清除代理 """ if self.device_android_version <= 4: # 安卓4.x之下可以使用AndroidProxySetter来设置代理 print u'当前设备安卓版本号为{}.*, 将使用AndroidProxySetter来配置代理'.format(self.device_android_version) # 确保安装了AndroidProxySetter self.ensure_install_proxysetter() os.system('adb shell am start -n tk.elevenk.proxysetter/.MainActivity -e clear true') time.sleep(5) else: # 安卓4.x之上版本使用global http_proxy参数来设置代理 print u'当前设备安卓版本号为{}.*, 将通过系统global http_proxy属性来配置代理'.format(self.device_android_version) os.system('adb shell settings delete global http_proxy') os.system('adb shell settings delete global global_http_proxy_host') os.system('adb shell settings delete global global_http_proxy_port') time.sleep(5)