python3 爬虫实战 :用 Appium 抓取手机 app 的 数据

 

 

http://www.ziksp.com/%e5%ad%a6%e4%b9%a0%e8%b5%84%e6%96%99/python%e7%bc%96%e7%a8%8b/  python资料站

From:https://blog.csdn.net/Fan_shui/article/details/81413595

 

本编教程从 appium 的环境配置开始,到抓取手机 app 微信朋友圈结束。

知乎:https://zhuanlan.zhihu.com/p/41311503
GitHub:https://github.com/FanShuixing/git_webspider

 

参考博文
appium+python 环境搭建:https://www.cnblogs.com/yoyoketang/p/6128725.html
[Python3网络爬虫开发实战] 1.7.3-Appium的安装:https://cuiqingcai.com/5407.html
java环境配置:https://jingyan.baidu.com/article/fd8044fa2c22f15031137a2a.html
appium 获取 appPackage 和 appActivity : https://blog.csdn.net/mtbaby/article/details/78676477
selenium 动态抓取网页:https://blog.csdn.net/Fan_shui/article/details/81516645

 

 

环境搭建

 

最开始是按照崔大的环境搭建 https://cuiqingcai.com/5407.html,然后弄完之后发现在 notepad 里面写的 python 运行不了,不能打开手机端的 app,appium 倒是可以打开。另外一篇环境搭建的博文安装的 appium 是旧版,我推荐先按照崔大的教程把appium 环境和 Android studio 搭建下载好,重点:我们在安装的时候,安装环境只要是可以改的都改,不要按照默认的下在c 盘,c 盘就那么大个儿,最重要的是要清楚自己的安装位置,后面会用到。(当然也可以直接按照悠悠博主的教程一步步的搭建下来,若是这样,环境搭建下面就都可以不用看了)
我们按照崔大的教程把 appium 环境 和 Android studio 搭建好,其中第三步我再详细加一点,下图是崔大文中的第三步

我的安装位置在F:/SDK

在环境变量中,系统变量下增加一个这样

在系统变量的path中增加个下面两个

弄好后,我们打开另外一篇博文 https://www.cnblogs.com/yoyoketang/p/6128725.html,一步步按照教程来,其中第三步、四步android_sdk下载就不用再下了,崔大的博文中已经下过。(ps:悠悠博主的后面几篇环境搭建也要看)。

 

如果安装完 Android studio,会自带 把 Android sdk 安装了,可以通过下面步骤找到 sdk 安装路径,然后添加系统环境变量即可

 

 

 

appium 的使用

 

恭喜恭喜,走到这一步,我走到这儿可是花了好几天的时间。本文使用的真机,没用模拟器,感兴趣的可以搜下模拟器的使用。我们用usb连接上手机,要打开手机上的usb调试,然后输入adb devices -l (不是数字1,是小写 L )

出现上图就证明手机和电脑连接成功,若是出现下图这种,就把手机拔掉再重连一下

成功后,打开appium

platformName:平台名称
deviceName:设备名称,就是刚才的adb devices -l中mode后面就是
appPackage:app包名
appActivity:app活动名
有个简单的方法便可以获得appPackage和appActivity:https://blog.csdn.net/mtbaby/article/details/78676477

start sessions后

我们可以点击左边的登陆(忍不住抱怨下微信,我不就是多登陆了两下,然后微信号被封了一天(*  ̄︿ ̄)),点击登陆后可以看到中间的App Source有高亮的代码,就是这个登陆按钮的,可以再看右边的Selected Element中有Tap、Send keys、Clear。
在最左边图中点击登陆后,若最右边下面的clickable是True,则证明可以点击,可以通过点击Tap实现点击功能,appium就介绍到这。 

 

 

python对接Appium

 

首先我们要对接app,就是类似于start session这样的连接
注:代码运行时要保证手机不黑屏

 
  1. from appium import webdriver

  2. from selenium.webdriver.support.ui import WebDriverWait

  3.  
  4. PLATFORM='Android'

  5. deviceName='HUAWEI_P7_L09'

  6. app_package='com.tencent.mm'

  7. app_activity='.ui.LauncherUI'

  8. driver_server='http://127.0.0.1:4723/wd/hub'

  9.  
  10.  
  11. class Moments():

  12. def __init__(self):

  13. self.desired_caps={

  14. 'platformName':PLATFORM,

  15. 'deviceName':deviceName,

  16. 'appPackage':app_package,

  17. 'appActivity':app_activity

  18. }

  19. self.driver=webdriver.Remote(driver_server, self.desired_caps)

  20. self.wait=WebDriverWait(self.driver,300)

  21.  
  22. def login(self):

  23. print('正在登陆中——————')

  24.  
  25. def main(self):

  26. self.login()

  27.  
  28.  
  29. M = Moments()

  30. M.main()

如果出现 urllib.error.URLError: urlopen error [WinError 10061] 由于目标计算机积极拒绝,无法连接。
看看打开appium没有,打开后再运行上面的代码就没有问题,手机会自动转到微信的登陆界面(注:deviceName要改成自己手机的) 

打开微信后,我们要模拟点击登陆按钮,首先要定位到登陆元素,这个跟selenium的用法类似,我们可以打开appium用前面的方式连接微信,也可以打开sdk安装路径下tools中的uiautomatorviewer.bat,第二种方法比较快

下图中,要先点击图中的按钮,才会出现手机上的画面,图中我已经定位到登陆按钮,可以在右边看到属性resource-id,以及clickable=True,确实是可以点击的,为什么要这样确认下呢,因为有的你以为可以点击的元素,也许你定位没有定好,比如说你定位到登陆外更大的一个框,它是不可点击的 

 
  1. from appium import webdriver

  2. from selenium.webdriver.support.ui import WebDriverWait

  3. from selenium.webdriver.support import expected_conditions as EC

  4. from selenium.webdriver.common.by import By

  5.  
  6.  
  7. PLATFORM = 'Android'

  8. deviceName = 'HUAWEI_P7_L09'

  9. app_package = 'com.tencent.mm'

  10. app_activity = '.ui.LauncherUI'

  11. driver_server = 'http://127.0.0.1:4723/wd/hub'

  12.  
  13.  
  14. class Moments():

  15. def __init__(self):

  16. self.desired_caps={

  17. 'platformName': PLATFORM,

  18. 'deviceName': deviceName,

  19. 'appPackage': app_package,

  20. 'appActivity': app_activity

  21. }

  22. self.driver = webdriver.Remote(driver_server, self.desired_caps)

  23. self.wait = WebDriverWait(self.driver, 300)

  24.  
  25. def login(self):

  26. print('点击登陆按钮——————')

  27. login = self.wait.until(EC.presence_of_element_located((By.ID, 'com.tencent.mm:id/d75')))

  28. login.click()

  29.  
  30. def main(self):

  31. self.login()

  32.  
  33.  
  34. M = Moments()

  35. M.main()

运行后就会跳出登陆界面,接下来就都是定位元素与点击元素的事情:

 
  1. from appium import webdriver

  2. from selenium.webdriver.support.ui import WebDriverWait

  3. from selenium.webdriver.support import expected_conditions as EC

  4. from selenium.webdriver.common.by import By

  5.  
  6. PLATFORM = 'Android'

  7. deviceName = 'HUAWEI_P7_L09'

  8. app_package = 'com.tencent.mm'

  9. app_activity = '.ui.LauncherUI'

  10. driver_server = 'http://127.0.0.1:4723/wd/hub'

  11.  
  12.  
  13. class Moments():

  14. def __init__(self):

  15. self.desired_caps = {

  16. 'platformName': PLATFORM,

  17. 'deviceName': deviceName,

  18. 'appPackage': app_package,

  19. 'appActivity': app_activity

  20. }

  21. self.driver = webdriver.Remote(driver_server, self.desired_caps)

  22. self.wait = WebDriverWait(self.driver, 300)

  23.  
  24. def login(self):

  25. print('点击登陆按钮——————')

  26. login = self.wait.until(EC.presence_of_element_located((By.ID, 'com.tencent.mm:id/d75')))

  27. login.click()

  28. # 输入手机号

  29. phone = self.wait.until(EC.presence_of_element_located((By.ID, 'com.tencent.mm:id/hz')))

  30. phone_num = input('请输入手机号')

  31. phone.send_keys(phone_num)

  32. print('点击下一步中')

  33. button = self.wait.until(EC.presence_of_element_located((By.ID, 'com.tencent.mm:id/alr')))

  34. button.click()

  35. pass_w = input('请输入密码:')

  36. password = self.wait.until(EC.presence_of_element_located((By.ID, 'com.tencent.mm:id/hz')))

  37. password.send_keys(pass_w)

  38. login = self.driver.find_element_by_id('com.tencent.mm:id/alr')

  39. login.click()

  40.  
  41. # 提示 叉掉

  42. tip = self.wait.until(EC.element_to_be_clickable((By.ID, 'com.tencent.mm:id/an2')))

  43. tip.click()

  44.  
  45. def main(self):

  46. self.login()

  47.  
  48.  
  49. M = Moments()

  50. M.main()

现在已经进入到微信了,我们需要先定位到微信下面的 发现->朋友圈

 
  1. from appium import webdriver

  2. from selenium.webdriver.support.ui import WebDriverWait

  3. from selenium.webdriver.support import expected_conditions as EC

  4. from selenium.webdriver.common.by import By

  5. import time

  6.  
  7. PLATFORM = 'Android'

  8. deviceName = 'HUAWEI_P7_L09'

  9. app_package = 'com.tencent.mm'

  10. app_activity = '.ui.LauncherUI'

  11. driver_server = 'http://127.0.0.1:4723/wd/hub'

  12.  
  13.  
  14. class Moments():

  15. def __init__(self):

  16. self.desired_caps = {

  17. 'platformName': PLATFORM,

  18. 'deviceName': deviceName,

  19. 'appPackage': app_package,

  20. 'appActivity': app_activity

  21. }

  22. self.driver = webdriver.Remote(driver_server, self.desired_caps)

  23. self.wait = WebDriverWait(self.driver, 300)

  24.  
  25. def login(self):

  26. print('点击登陆按钮——————')

  27. login = self.wait.until(EC.presence_of_element_located((By.ID, 'com.tencent.mm:id/d75')))

  28. login.click()

  29. # 输入手机号

  30. phone = self.wait.until(EC.presence_of_element_located((By.ID, 'com.tencent.mm:id/hz')))

  31. phone_num = input('请输入手机号')

  32. phone.send_keys(phone_num)

  33. print('点击下一步中')

  34. button = self.wait.until(EC.presence_of_element_located((By.ID, 'com.tencent.mm:id/alr')))

  35. button.click()

  36. pass_w = input('请输入密码:')

  37. password = self.wait.until(EC.presence_of_element_located((By.ID, 'com.tencent.mm:id/hz')))

  38. password.send_keys(pass_w)

  39. login = self.driver.find_element_by_id('com.tencent.mm:id/alr')

  40. login.click()

  41. # 提示 叉掉

  42. tip = self.wait.until(EC.element_to_be_clickable((By.ID, 'com.tencent.mm:id/an2')))

  43. tip.click()

  44.  
  45. def enter(self):

  46. print('点击发现——')

  47. tab = self.wait.until(EC.element_to_be_clickable((By.XPATH, '//*[@resource-id="com.tencent.mm:id/cdh"]/..')))

  48. print('已经找到发现按钮')

  49. time.sleep(6)

  50. tab.click()

  51. # self.wait.until(EC.text_to_be_present_in_element((By.ID,'com.tencent.mm:id/cdj'),'发现'))

  52. print('点击朋友圈')

  53. friends = self.wait.until(EC.presence_of_element_located(

  54. (By.XPATH, '//*[@resource-id="android:id/list"]/*[@class="android.widget.LinearLayout"][1]')))

  55. friends.click()

  56.  
  57. def main(self):

  58. self.login()

  59. self.enter()

  60.  
  61.  
  62. M = Moments()

  63. M.main()

都是些元素定位,多用几次就会了。接下来我们可以提取数据了

 
  1. from appium import webdriver

  2. from selenium.webdriver.support.ui import WebDriverWait

  3. from selenium.webdriver.support import expected_conditions as EC

  4. from selenium.webdriver.common.by import By

  5. import time

  6. import pymongo

  7.  
  8. PLATFORM = 'Android'

  9. deviceName = 'HUAWEI_P7_L09'

  10. app_package = 'com.tencent.mm'

  11. app_activity = '.ui.LauncherUI'

  12. driver_server = 'http://127.0.0.1:4723/wd/hub'

  13.  
  14.  
  15. class Moments():

  16. def __init__(self):

  17. self.desired_caps = {

  18. 'platformName': PLATFORM,

  19. 'deviceName': deviceName,

  20. 'appPackage': app_package,

  21. 'appActivity': app_activity

  22. }

  23. self.driver = webdriver.Remote(driver_server, self.desired_caps)

  24. self.wait = WebDriverWait(self.driver, 300)

  25. self.client = pymongo.MongoClient()

  26. self.db = self.client.weixin

  27. self.collection = self.db.weixin

  28.  
  29. def login(self):

  30. print('点击登陆按钮——————')

  31. login = self.wait.until(EC.presence_of_element_located((By.ID, 'com.tencent.mm:id/d75')))

  32. login.click()

  33. # 输入手机号

  34. phone = self.wait.until(EC.presence_of_element_located((By.ID, 'com.tencent.mm:id/hz')))

  35. phone_num = input('请输入手机号:')

  36. phone.send_keys(phone_num)

  37. print('点击下一步中')

  38. button = self.wait.until(EC.presence_of_element_located((By.ID, 'com.tencent.mm:id/alr')))

  39. button.click()

  40. pass_w = input('请输入密码:')

  41. password = self.wait.until(EC.presence_of_element_located((By.ID, 'com.tencent.mm:id/hz')))

  42. password.send_keys(pass_w)

  43. login = self.driver.find_element_by_id('com.tencent.mm:id/alr')

  44. login.click()

  45.  
  46. # 提示 叉掉

  47. tip = self.wait.until(EC.element_to_be_clickable((By.ID, 'com.tencent.mm:id/an2')))

  48. tip.click()

  49.  
  50. def enter(self):

  51. print('点击发现——')

  52. tab = self.wait.until(EC.element_to_be_clickable((By.XPATH, '//*[@resource-id="com.tencent.mm:id/cdh"]/..')))

  53. print('已经找到发现按钮')

  54. time.sleep(6)

  55. tab.click()

  56. # self.wait.until(EC.text_to_be_present_in_element((By.ID,'com.tencent.mm:id/cdj'),'发现'))

  57. print('点击朋友圈')

  58. friends = self.wait.until(EC.presence_of_element_located(

  59. (By.XPATH, '//*[@resource-id="android:id/list"]/*[@class="android.widget.LinearLayout"][1]')))

  60. friends.click()

  61.  
  62. def crawl(self):

  63. while True:

  64. items = self.wait.until(EC.presence_of_all_elements_located(

  65. (By.XPATH, '//*[@resource-id="com.tencent.mm:id/dja"]//*[@class="android.widget.FrameLayout"]')))

  66. self.driver.swipe(300, 1000, 300, 300)

  67. for item in items:

  68. try:

  69. nickname = item.find_element_by_id('com.tencent.mm:id/as6').get_attribute('text')

  70. print(nickname)

  71. content = item.find_element_by_id('com.tencent.mm:id/dkf').get_attribute('text')

  72. print(content)

  73. data = {'nickname': nickname, 'content': content}

  74. self.collection.update({'nickname': nickname, 'content': content}, {'$set': data}, True)

  75. except BaseException as e:

  76. print(e)

  77.  
  78. def main(self):

  79. self.login()

  80. self.enter()

  81. self.crawl()

  82.  
  83.  
  84. M = Moments()

  85. M.main()

driver.swipe() 是从点 A 滑动到点 B,driver.swipe(300,1000,300,300)是从点(300,1000)滑动到(300,300)
self.collection.update({'nickname':nickname,'content':content},{'$set':data},True)

首先根据昵称和正文来查询,如果信息不存在,则插入数据,否则更新数据,关键点是第三个参数True,这可以实现存在即更新,不存在即插入的代码,用着感觉很舒服呢

总的来说,感觉学appium挺不容易的,开头就有个环境配置,后面再加上appium对接python的时候超级慢,调试要等很久,再加上微信次数登多了会被封一天,所以这篇教程花了很多时间,在这段时间内下一篇mitmdump都已经诞生了………

如有错误,欢迎指正~

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
爬虫(Web Crawler)是一种自动化程序,用于从互联网上收集信息。其主要功能是访问网页、提取数据并存储,以便后续分析或展示。爬虫通常由搜索引擎、数据挖掘工具、监测系统等应用于网络数据抓取的场景。 爬虫的工作流程包括以下几个关键步骤: URL收集: 爬虫从一个或多个初始URL开始,递归或迭代地发现新的URL,构建一个URL队列。这些URL可以通过链接分析、站点地图、搜索引擎等方式获取。 请求网页: 爬虫使用HTTP或其他协议向目标URL发起请求,获取网页的HTML内容。这通常通过HTTP请求库实现,如Python中的Requests库。 解析内容: 爬虫对获取的HTML进行解析,提取有用的信息。常用的解析工具有正则表达式、XPath、Beautiful Soup等。这些工具帮助爬虫定位和提取目标数据,如文本、图片、链接等。 数据存储: 爬虫将提取的数据存储到数据库、文件或其他存储介质中,以备后续分析或展示。常用的存储形式包括关系型数据库、NoSQL数据库、JSON文件等。 遵守规则: 为避免对网站造成过大负担或触发反爬虫机制,爬虫需要遵守网站的robots.txt协议,限制访问频率和深度,并模拟人类访问行为,如设置User-Agent。 反爬虫应对: 由于爬虫的存在,一些网站采取了反爬虫措施,如验证码、IP封锁等。爬虫工程师需要设计相应的策略来应对这些挑战。 爬虫在各个领域都有广泛的应用,包括搜索引擎索引、数据挖掘、价格监测、新闻聚合等。然而,使用爬虫需要遵守法律和伦理规范,尊重网站的使用政策,并确保对被访问网站的服务器负责。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值