首页 > 编程语言 >「docker实战篇」python的docker- 多设备端并发抓取抖音粉丝数据(23)

「docker实战篇」python的docker- 多设备端并发抓取抖音粉丝数据(23)

时间:2023-01-06 12:06:08浏览次数:67  
标签:widget RelativeLayout 23 driver 实战篇 LinearLayout FrameLayout docker android


之前的文章搞过,抖音web端用户信息的抓取和抖音app端粉丝的抓取。一台设备抓取抖音粉丝数据实在是太慢了,这次咱们来演示下多模拟器同时爬取信息。源码:​​https://github.com/limingios/dockerpython.git​​ (源码/「docker实战篇」python的docker- 多设备端并发抓取抖音粉丝数据(22))

「docker实战篇」python的docker- 多设备端并发抓取抖音粉丝数据(23)_python

拷贝之前的带xponsed的模拟器

  • 1.桌面有夜神模拟器多开

「docker实战篇」python的docker- 多设备端并发抓取抖音粉丝数据(23)_android_02

  • 2.选择中,点击复制,可能一下复制出来3个,咱们不需要那么多删除2个就可以了,你如果电脑足够强大也可以复制多个,下面代码的思路是一样的。

「docker实战篇」python的docker- 多设备端并发抓取抖音粉丝数据(23)_docker_03

  • 3.复制完成后,改下别名,方便区别

「docker实战篇」python的docker- 多设备端并发抓取抖音粉丝数据(23)_python_04

  1. 启动2个模拟器。

「docker实战篇」python的docker- 多设备端并发抓取抖音粉丝数据(23)_python_05

多任务抓取

按照常理一般的互联网操作,如果要实现多任务抓取基本都是使用容器化的来完成的,但是目前直接说docker有点尚早,不过这个系列肯定是要实现docker的多设备抓取的,这里先说说使用python多进程的方式来完成。

  • 1.查看夜神模拟器的端口,启动cmd,输入
adb devices

「docker实战篇」python的docker- 多设备端并发抓取抖音粉丝数据(23)_docker_06

  • 2.如果输入adb devices没有列表

在启动夜神模拟器的时候adb还没启动。也就是夜神模拟器比adb先启动,解决方案。
1.打开任务管理器,查看夜神模拟器的PID,可以通过点击状态-选中PID

「docker实战篇」python的docker- 多设备端并发抓取抖音粉丝数据(23)_python_07

2.刚查看到的PID

netstat -ano | findstr "452"

「docker实战篇」python的docker- 多设备端并发抓取抖音粉丝数据(23)_docker_08

netstat -ano | findstr "16712"

「docker实战篇」python的docker- 多设备端并发抓取抖音粉丝数据(23)_docker_09

3.夜神模拟器端口是有规律的,第一个模拟器端口是62001,第二个是62025,第三个62025+1,第4个62025+2

「docker实战篇」python的docker- 多设备端并发抓取抖音粉丝数据(23)_docker_10

  1. 手动的命令方式连接设备
adb connect 127.0.0.1:62025

「docker实战篇」python的docker- 多设备端并发抓取抖音粉丝数据(23)_docker_11

5.appium【客户端】需要设置udid,在appium里面识别就是udid,因为之前是一台设备所以不需要指定udid,光指定deviceName就可以了。

「docker实战篇」python的docker- 多设备端并发抓取抖音粉丝数据(23)_android_12

  1. appium【服务端】需要设置bootstrapPort,服务端进行设置,设备和appium通信的端口。

「docker实战篇」python的docker- 多设备端并发抓取抖音粉丝数据(23)_python_13

「docker实战篇」python的docker- 多设备端并发抓取抖音粉丝数据(23)_android_14

「docker实战篇」python的docker- 多设备端并发抓取抖音粉丝数据(23)_docker_15

7.appium的2台的属性设置
1.douyin1 port=4723 bootstrapPort=4724
2.douyin1 port=4725 bootstrapPort=4726

「docker实战篇」python的docker- 多设备端并发抓取抖音粉丝数据(23)_python_16

「docker实战篇」python的docker- 多设备端并发抓取抖音粉丝数据(23)_android_17

  1. 报错解决方案

selenium.common.exceptions.WebDriverException: Message: An unknown server-side error occurred while processing the command. Original error: Failed to Dump Window Hierarchy

「docker实战篇」python的docker- 多设备端并发抓取抖音粉丝数据(23)_android_18

解决方案
在含有Emoji特殊符号的页面中,爆出Failed to Dump Window Hierarchy
​​​https://github.com/appium/appium/issues/4151​​​javascript:void(0)
won’t be solved until the new android driver is completed. This is a known bug in uiautomator v1
此问题是uiautomator自身bug,换用Android5.1以上的系统

源码

#!/usr/bin/env python

import time
from appium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
import multiprocessing

def get_size(driver):
x = driver.get_window_size()['width']
y = driver.get_window_size()['height']
return (x, y)

def handle_douyin(driver):
while True:
#定位搜索框
if WebDriverWait(driver,60).until(lambda x:x.find_element_by_xpath("//android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[2]/android.widget.EditText[1]")):
#获取douyin_id进行搜索
driver.find_element_by_xpath("//android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[2]/android.widget.EditText[1]").send_keys('1860719705')
while driver.find_element_by_xpath("//android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[2]/android.widget.EditText[1]").text != '1860719705':
driver.find_element_by_xpath("//android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[2]/android.widget.EditText[1]").send_keys('1860719705')
time.sleep(0.1)
#点击搜索
driver.find_element_by_xpath("//android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.LinearLayout[1]/android.widget.TextView[1]").click()


#点击用户标签
if WebDriverWait(driver,30).until(lambda x:x.find_element_by_xpath("//android.widget.TextView[@text='用户']")):
driver.find_element_by_xpath("//android.widget.TextView[@text='用户']").click()
#点击头像
if WebDriverWait(driver,30).until(lambda x:x.find_element_by_xpath("//android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.support.v4.view.ViewPager[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[2]/android.view.View[1]/android.support.v7.widget.RecyclerView[1]/android.widget.RelativeLayout[1]/android.widget.RelativeLayout[1]/android.widget.ImageView[1]")):
driver.find_element_by_xpath("//android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.support.v4.view.ViewPager[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[2]/android.view.View[1]/android.support.v7.widget.RecyclerView[1]/android.widget.RelativeLayout[1]/android.widget.RelativeLayout[1]/android.widget.ImageView[1]").click()
#点击粉丝按钮
if WebDriverWait(driver,30).until(lambda x:x.find_element_by_xpath("//android.widget.TextView[@text='粉丝']")):
driver.find_element_by_xpath("//android.widget.TextView[@text='粉丝']").click()

x1 = int(driver.get_window_size()['width']*0.5)
y1 = int(driver.get_window_size()['height']*0.75)
y2 = int(driver.get_window_size()['height']*0.25)
while True:
time.sleep(3)
if '没有更多了' in driver.page_source:
break
elif 'TA还没有粉丝' in driver.page_source:
break
else:
driver.swipe(x1,y1,x1,y2)
time.sleep(0.5)

#返回
driver.find_element_by_xpath("//android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.LinearLayout[1]/android.widget.RelativeLayout[1]/android.widget.FrameLayout[1]/android.widget.ImageView[1]").click()
#返回
driver.find_element_by_id("com.ss.android.ugc.aweme:id/jk").click()
#重新清空用户id
driver.find_element_by_xpath("//android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[2]/android.widget.EditText[1]").clear()



def handle_appium(device,port):
cap = {
"platformName": "Android",
"platformVersion": "4.4.2",
"deviceName": device,
"udid":device,
# 真机的
# "platformName": "Android",
# "platformVersion": "7.1.2",
# "deviceName": "10d4e4387d74",
"appPackage": "com.ss.android.ugc.aweme",
"appActivity": "com.ss.android.ugc.aweme.main.MainActivity",
"noReset": True,
"unicodeKeyboard": True,
"resetkeyboard": True
}

driver = webdriver.Remote("http://localhost:"+str(port)+"/wd/hub", cap)



try:
# 点击搜索
print('点击搜索')
if WebDriverWait(driver, 60).until(lambda x: x.find_element_by_xpath(
"//android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.support.v4.view.ViewPager[1]/android.widget.FrameLayout[1]/android.support.v4.view.ViewPager[1]/android.widget.TabHost[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.view.View[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.LinearLayout[2]/android.widget.FrameLayout[1]/android.widget.ImageView[1]")):
driver.find_element_by_xpath(
"//android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.support.v4.view.ViewPager[1]/android.widget.FrameLayout[1]/android.support.v4.view.ViewPager[1]/android.widget.TabHost[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.widget.FrameLayout[1]/android.view.View[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.RelativeLayout[1]/android.widget.LinearLayout[2]/android.widget.FrameLayout[1]/android.widget.ImageView[1]").click()
except:
# [26,76][115,165]
driver.tap([(26, 76), (115, 165)], 500)

handle_douyin(driver)

if __name__ == '__main__':
m_list = []
#定义了2台虚拟设备,夜神模拟器
devices_list = ["127.0.0.1:62001","127.0.0.1:62025"]
for device in range(len(devices_list)):
port = 4723 + 2 * device
m_list.append(multiprocessing.Process(target=handle_appium,args=(devices_list[device],port,)))

for m1 in m_list:
m1.start()

for m2 in m_list:
m2.join()

启动步骤

  • 1.启动2个appium

之前上边已经提到过的端口(4723 4724 )(4725 4726)

「docker实战篇」python的docker- 多设备端并发抓取抖音粉丝数据(23)_android_19

  • 2.启动python代码,查看效果

调试测试代码次数太多了,douyin要求我登录,哈哈

「docker实战篇」python的docker- 多设备端并发抓取抖音粉丝数据(23)_docker_20

伪装爬虫

刚出现的因为访问册数太多,douyin那边识别了,这样需要解决。通过代理的方式。

「docker实战篇」python的docker- 多设备端并发抓取抖音粉丝数据(23)_python_21

「docker实战篇」python的docker- 多设备端并发抓取抖音粉丝数据(23)_python_22

  • 2.登录【阿布云】后,使用mitmdump的方式,设置阿布云的代理

启动cmd,输入
mitmdump -s ​​​test.py​​ -p 8889 --mode upstream:HTTP隧道服务器:端口 --upstream-auth 通行证书:通行秘钥

mitmdump -s test.py -p 8889 --mode upstream:http://http-pro.abuyun.com:9010 --upstream-auth HS821YO6BA7D6M8P:75021E5CF3AB82EE

「docker实战篇」python的docker- 多设备端并发抓取抖音粉丝数据(23)_python_23

  • 3.模拟器的wifi也要设置对应的代理,之前说过在重复说下。

「docker实战篇」python的docker- 多设备端并发抓取抖音粉丝数据(23)_android_24

  • 4.这样就使用了代理的方式了。 所有请求就是代理的阿布云了。

感谢老铁的建议,以后的所有的系列的源码都是按照对应文章进行整理,原来的源码都是按照我的开发历程的,这样不适合中间参与进来的老铁。

PS:调试过程中,夜神模拟器,appium,python代码插件没有问题的话,程序在运行过程中出现的最多的问题还是xpath定位的问题,对于python的代码其实也是很好理解的。另外注意的文章中提到的要使用安卓5.1以上否则会因为页面中含有Emoji特殊符号,爆出Failed to Dump Window Hierarchy。udid对于启动多个模拟器的时候一定要进行设置。

「docker实战篇」python的docker- 多设备端并发抓取抖音粉丝数据(23)_docker_25


标签:widget,RelativeLayout,23,driver,实战篇,LinearLayout,FrameLayout,docker,android
From: https://blog.51cto.com/u_12040702/5992962

相关文章

  • docker介绍
    Docker是一个容器化平台,它以容器的形式将你的应用程序及所有的依赖项打包在一起,以确保你的应用程序在任何环境中无缝运行。Docker利用Linux核心中的资源分离机制(例如cgro......
  • 2023.1.06 java打印杨辉三角(二维数组)
    publicclassyanghui{publicstaticvoidmain(String[]args){int[][]yanghui=newint[10][];for(inti=0;i<yanghui.length;i++){......
  • 『中级篇』docker的魅力初体验-5分钟安装wordpress不走弯路(三)
    安装截图说话官网安装教程:​​wordpress中文安装教程​​咱们也用docker在一个新的centos虚拟机装一把。光吹说多好没用。开始展示真实的实力的时候了,用我的教程保证5分钟......
  • 『中级篇』docker架构和底层技术(12)
    ​前11节主要是介绍docker的安装,如果跟这我来学我相信大家已经有了一个docker的安装环境,本次是看下docker的架构和底层的技术,其实随着各位老铁的学习我相信对于docker架......
  • 『中级篇』docker之wordpress容器SSL(番外篇)(78)
    ache2容器内安装SSL实现wordpress证书安装。前提​​『中级篇』docker容器安装wordpress(37)​​通过上边的方式已经安装了wordpress和mysql,可以正常的访问准备工作进入容......
  • 『中级篇』docker体验阿里云的容器服务(58)
    ​体验下阿里云的容器服务,前提给自己的账号充值100以上啊,大概自己玩一个小时跟去网吧差不多2,3块钱吧!容器服务进入容器服务进入首页:cn.aliyun.com往下拉选择「容器服务」选......
  • 『中级篇』docker之CI/CD持续集成-(终结篇)(77)
    个月的时间,每天的坚持学习和更新收获还是满满的,跟我一起学习的小伙伴不知道你收获到了吗?想说的这几次CI/CD介绍了gitlab,gitlab-ci,docker,所有的工具都是免费的,提供了一个方式......
  • 『高级篇』docker容器来说微服务导学(一)
    gcloud,重点是落地,之前的CICD涉及的面有老铁说最后镜像部署没说,我说高级一定补上的!微服务微服务最近几年比较火,不了解也没关系,可以理解成一个项目的模块吧,微服务运行在docke......
  • 『中级篇』在centos上安装docker(九)
    ​在mac和window上都已经安装了docker,这次咱们在linux系统下安装docker。这次也补充下vagrant如何搜索:Vagrantfile如何搜Vagrantfile之前的课程已经已经完成了在windows/mac......
  • 『中级篇』docker Image概述(13)
    什么是镜像,镜像是怎么产生的,通过这节的学习的Dockercontainer机制要比虚拟机的机制要小巧,原因何在?本节课程的内容是连接12节的,所以肯定跟12节的github有关系:​​https://g......