1. 程式人生 > >用appium爬取資料python3實現

用appium爬取資料python3實現

二、參考博文  以下網址對於這篇教程非常重要,感謝分享

在看這篇教程前,希望你已經具備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:悠悠博主的後面幾篇環境搭建也要看)

四、appium的使用  恭喜恭喜,走到這一步,我走到這兒可是花了好幾天的時間。本文使用的真機,沒用模擬器,感興趣的可以搜下模擬器的使用。我們用usb連線上手機,要開啟手機上的usb除錯,然後輸入adb devices -l(不是數字1,是小寫l) 這裡寫圖片描述 出現上圖就證明手機和電腦連線成功,若是出現下圖這種,就把手機拔掉再重連一下 這裡寫圖片描述  成功後,開啟appium 這裡寫圖片描述

這裡寫圖片描述 platformName:平臺名稱  deviceName:裝置名稱,就是剛才的adb devices -l中mode後面就是  appPackage:app包名  appActivity:app活動名

start sessions後 這裡寫圖片描述

我們可以點選左邊的登陸(忍不住抱怨下微信,我不就是多登陸了兩下,然後微訊號被封了一天(*  ̄︿ ̄)),點選登陸後可以看到中間的App Source有高亮的程式碼,就是這個登陸按鈕的,可以再看右邊的Selected Element中有Tap、Send keys、Clear。  在最左邊圖中點選登陸後,若最右邊下面的clickable是True,則證明可以點選,可以通過點選Tap實現點選功能,appium就介紹到這。

五、python對接Appium

首先我們要對接app,就是類似於start session這樣的連線 注:程式碼執行時要保證手機不黑屏

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

PLATFORM='Android'
deviceName='HUAWEI_P7_L09'
app_package='com.tencent.mm'
app_activity='.ui.LauncherUI'
driver_server='http://127.0.0.1:4723/wd/hub'

class Moments():
    def __init__(self):
        self.desired_caps={
        'platformName':PLATFORM,
        'deviceName':deviceName,
        'appPackage':app_package,
        'appActivity':app_activity}
        self.driver=webdriver.Remote(driver_server,self.desired_caps)
        self.wait=WebDriverWait(self.driver,300)

    def login(self):
        print('正在登陸中——————')

    def main(self):
        self.login()

M=Moments()
M.main()

如果出現 urllib.error.URLError: urlopen error [WinError 10061] 由於目標計算機積極拒絕,無法連線。  看看開啟appium沒有,開啟後再執行上面的程式碼就沒有問題,手機會自動轉到微信的登陸介面(注:deviceName要改成自己手機的) 這裡寫圖片描述  開啟微信後,我們要模擬點選登陸按鈕,首先要定位到登陸元素,這個跟selenium的用法類似,我們可以開啟appium用前面的方式連線微信,也可以開啟sdk安裝路徑下tools中的uiautomatorviewer.bat,第二種方法比較快 這裡寫圖片描述  下圖中,要先點選圖中的按鈕,才會出現手機上的畫面,圖中我已經定位到登陸按鈕,可以在右邊看到屬性resource-id,以及clickable=True,確實是可以點選的,為什麼要這樣確認下呢,因為有的你以為可以點選的元素,也許你定位沒有定好,比如說你定位到登陸外更大的一個框,它是不可點選的 這裡寫圖片描述

from appium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

PLATFORM='Android'
deviceName='HUAWEI_P7_L09'
app_package='com.tencent.mm'
app_activity='.ui.LauncherUI'
driver_server='http://127.0.0.1:4723/wd/hub'

class Moments():
    def __init__(self):
        self.desired_caps={
        'platformName':PLATFORM,
        'deviceName':deviceName,
        'appPackage':app_package,
        'appActivity':app_activity}
        self.driver=webdriver.Remote(driver_server,self.desired_caps)
        self.wait=WebDriverWait(self.driver,300)

    def login(self):
        print('點選登陸按鈕——————')
        login=self.wait.until(EC.presence_of_element_located((By.ID,'com.tencent.mm:id/d75')))
        login.click()

    def main(self):
        self.login()

M=Moments()
M.main()

執行後就會跳出登陸介面,接下來就都是定位元素與點選元素的事情:

from appium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

PLATFORM='Android'
deviceName='HUAWEI_P7_L09'
app_package='com.tencent.mm'
app_activity='.ui.LauncherUI'
driver_server='http://127.0.0.1:4723/wd/hub'

class Moments():
    def __init__(self):
        self.desired_caps={
        'platformName':PLATFORM,
        'deviceName':deviceName,
        'appPackage':app_package,
        'appActivity':app_activity}
        self.driver=webdriver.Remote(driver_server,self.desired_caps)
        self.wait=WebDriverWait(self.driver,300)

    def login(self):
        print('點選登陸按鈕——————')
        login=self.wait.until(EC.presence_of_element_located((By.ID,'com.tencent.mm:id/d75')))
        login.click()
        #輸入手機號
        phone=self.wait.until(EC.presence_of_element_located((By.ID,    'com.tencent.mm:id/hz')))
        phone_num=input('請輸入手機號')
        phone.send_keys(phone_num)
        print('點選下一步中')
        button=self.wait.until(EC.presence_of_element_located((By.ID,       'com.tencent.mm:id/alr')))
        button.click()
        pass_w=input('請輸入密碼:')
        password=self.wait.until(EC.presence_of_element_located((By.ID,'com.tencent.mm:id/hz')))
        password.send_keys(pass_w)

        login=self.driver.find_element_by_id('com.tencent.mm:id/alr')
        login.click()
        #提示 叉掉
        tip=self.wait.until(EC.element_to_be_clickable((By.ID,'com.tencent.mm:id/an2')))
        tip.click()

    def main(self):
        self.login()

M=Moments()
M.main()

現在已經進入到微信了,我們需要先定位到微信下面的 發現->朋友圈

from appium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
import time
PLATFORM='Android'
deviceName='HUAWEI_P7_L09'
app_package='com.tencent.mm'
app_activity='.ui.LauncherUI'
driver_server='http://127.0.0.1:4723/wd/hub'

class Moments():
    def __init__(self):
        self.desired_caps={
        'platformName':PLATFORM,
        'deviceName':deviceName,
        'appPackage':app_package,
        'appActivity':app_activity}
        self.driver=webdriver.Remote(driver_server,self.desired_caps)
        self.wait=WebDriverWait(self.driver,300)

    def login(self):
        print('點選登陸按鈕——————')
        login=self.wait.until(EC.presence_of_element_located((By.ID,'com.tencent.mm:id/d75')))
        login.click()
        #輸入手機號
        phone=self.wait.until(EC.presence_of_element_located((By.ID,    'com.tencent.mm:id/hz')))
        phone_num=input('請輸入手機號')
        phone.send_keys(phone_num)
        print('點選下一步中')
        button=self.wait.until(EC.presence_of_element_located((By.ID,       'com.tencent.mm:id/alr')))
        button.click()
        pass_w=input('請輸入密碼:')
        password=self.wait.until(EC.presence_of_element_located((By.ID,'com.tencent.mm:id/hz')))
        password.send_keys(pass_w)

        login=self.driver.find_element_by_id('com.tencent.mm:id/alr')
        login.click()
        #提示 叉掉
        tip=self.wait.until(EC.element_to_be_clickable((By.ID,'com.tencent.mm:id/an2')))
        tip.click()

    def enter(self):
        print('點擊發現——')
        tab=self.wait.until(EC.element_to_be_clickable((By.XPATH,'//*[@resource-id="com.tencent.mm:id/cdh"]/..')))
        print('已經找到發現按鈕')
        time.sleep(6)
        tab.click()
        # self.wait.until(EC.text_to_be_present_in_element((By.ID,'com.tencent.mm:id/cdj'),'發現'))
        print('點選朋友圈')
        friends=self.wait.until(EC.presence_of_element_located((By.XPATH,'//*[@resource-id="android:id/list"]/*[@class="android.widget.LinearLayout"][1]')))
        friends.click()

    def main(self):
        self.login()
        self.enter()

M=Moments()
M.main()

都是些元素定位,多用幾次就會了。接下來我們可以提取資料了

from appium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
import time
import pymongo
PLATFORM='Android'
deviceName='HUAWEI_P7_L09'
app_package='com.tencent.mm'
app_activity='.ui.LauncherUI'
driver_server='http://127.0.0.1:4723/wd/hub'

class Moments():
    def __init__(self):
        self.desired_caps={
        'platformName':PLATFORM,
        'deviceName':deviceName,
        'appPackage':app_package,
        'appActivity':app_activity}
        self.driver=webdriver.Remote(driver_server,self.desired_caps)
        self.wait=WebDriverWait(self.driver,300)
        self.client=pymongo.MongoClient()
        self.db=self.client.weixin
        self.collection=self.db.weixin

    def login(self):
        print('點選登陸按鈕——————')
        login=self.wait.until(EC.presence_of_element_located((By.ID,'com.tencent.mm:id/d75')))
        login.click()
        #輸入手機號
        phone=self.wait.until(EC.presence_of_element_located((By.ID,    'com.tencent.mm:id/hz')))
        phone_num=input('請輸入手機號:')
        phone.send_keys(phone_num)
        print('點選下一步中')
        button=self.wait.until(EC.presence_of_element_located((By.ID,       'com.tencent.mm:id/alr')))
        button.click()
        pass_w=input('請輸入密碼:')
        password=self.wait.until(EC.presence_of_element_located((By.ID,'com.tencent.mm:id/hz')))
        password.send_keys(pass_w)

        login=self.driver.find_element_by_id('com.tencent.mm:id/alr')
        login.click()
        #提示 叉掉
        tip=self.wait.until(EC.element_to_be_clickable((By.ID,'com.tencent.mm:id/an2')))
        tip.click()

    def enter(self):
        print('點擊發現——')
        tab=self.wait.until(EC.element_to_be_clickable((By.XPATH,'//*[@resource-id="com.tencent.mm:id/cdh"]/..')))
        print('已經找到發現按鈕')
        time.sleep(6)
        tab.click()
        # self.wait.until(EC.text_to_be_present_in_element((By.ID,'com.tencent.mm:id/cdj'),'發現'))
        print('點選朋友圈')
        friends=self.wait.until(EC.presence_of_element_located((By.XPATH,'//*[@resource-id="android:id/list"]/*[@class="android.widget.LinearLayout"][1]')))
        friends.click()

    def crawl(self):
        while True:
            items=self.wait.until(EC.presence_of_all_elements_located((By.XPATH,'//*[@resource-id="com.tencent.mm:id/dja"]//*[@class="android.widget.FrameLayout"]')))
            self.driver.swipe(300,1000,300,300)
            for item in items:
                try:
                    nickname=item.find_element_by_id('com.tencent.mm:id/as6').get_attribute('text')
                    print(nickname)
                    content=item.find_element_by_id('com.tencent.mm:id/dkf').get_attribute('text')
                    print(content)
                    data={'nickname':nickname,
                    'content':content}
                    self.collection.update({'nickname':nickname,'content':content},{'$set':data},True)

                except:
                    pass


    def main(self):
        self.login()
        self.enter()
        self.crawl()

M=Moments()
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都已經誕生了………