概述
特别注意: 微信具有一定的反爬能力,在测试时发现,每次爬取任务时, 对应特定节点的ID和XPath都会发生变化,保险起见,每次重新连接手机,都要对节点ID和Xpath作更新。
同时设置参数 'noReset': True, # 启动后结束后不清空应用数据,用例执行完后会默认重置APP,也就是删除APP所有数据。
避免多次输入用户名和密码登录,防止被封
首次登录需要用到login函数,第二次登录,请注释login
import os
from appium import webdriver
from appium.webdriver.common.touch_action import TouchAction
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from pymongo import MongoClient
from time import sleep
from processor import Processor
from config import *
class Moments():
def __init__(self):
"""
初始化
"""
# 驱动配置
self.desired_caps = {
'platformName': PLATFORM,
'deviceName': DEVICE_NAME,
'appPackage': APP_PACKAGE,
'appActivity': APP_ACTIVITY,
'noReset': True
}
self.driver = webdriver.Remote(DRIVER_SERVER, self.desired_caps)
self.wait = WebDriverWait(self.driver, TIMEOUT)
self.client = MongoClient(MONGO_URL)
self.db = self.client[MONGO_DB]
self.collection = self.db[MONGO_COLLECTION]
# 处理器
self.processor = Processor()
def login(self):
"""
登录微信
:return:
"""
# 登录按钮
login = self.wait.until(EC.presence_of_element_located((By.ID, 'com.tencent.mm:id/cjk')))
login.click()
# 手机输入
phone = self.wait.until(EC.presence_of_element_located((By.ID, 'com.tencent.mm:id/h2')))
phone.set_text(USERNAME)
# 下一步
next = self.wait.until(EC.element_to_be_clickable((By.ID, 'com.tencent.mm:id/adj')))
next.click()
# 密码
password = self.wait.until(
EC.presence_of_element_located((By.XPATH, '//*[@resource-id="com.tencent.mm:id/h2"][1]')))
password.set_text(PASSWORD)
# 提交
submit = self.wait.until(EC.element_to_be_clickable((By.ID, 'com.tencent.mm:id/adj')))
submit.click()
def enter(self):
"""
进入朋友圈
:return:
"""
# 选项卡
tab = self.wait.until(
EC.presence_of_element_located((By.XPATH, '//*[@resource-id="com.tencent.mm:id/bw3"][3]')))
tab.click()
# 朋友圈
moments = self.wait.until(EC.presence_of_element_located((By.ID, 'com.tencent.mm:id/atz')))
moments.click()
def crawl(self):
"""
爬取
:return:
"""
while True:
# 当前页面显示的所有状态
items = self.wait.until(
EC.presence_of_all_elements_located(
(By.XPATH, '//*[@resource-id="com.tencent.mm:id/cve"]//android.widget.FrameLayout')))
# 上滑
self.driver.swipe(FLICK_START_X, FLICK_START_Y + FLICK_DISTANCE, FLICK_START_X, FLICK_START_Y)
# 遍历每条状态
for item in items:
try:
# 昵称
nickname = item.find_element_by_id('com.tencent.mm:id/aig').get_attribute('text')
# 正文
content = item.find_element_by_id('com.tencent.mm:id/cwm').get_attribute('text')
# 日期
date = item.find_element_by_id('com.tencent.mm:id/crh').get_attribute('text')
# 处理日期
date = self.processor.date(date)
print(nickname, content, date)
data = {
'nickname': nickname,
'content': content,
'date': date,
}
# 插入MongoDB
self.collection.update({'nickname': nickname, 'content': content}, {'$set': data}, True)
sleep(SCROLL_SLEEP_TIME)
except NoSuchElementException:
pass
def main(self):
"""
入口
:return:
"""
# 登录 首次登录需要用到login函数,第二次登录,请注释login
self.login()
# 进入朋友圈
self.enter()
# 爬取
self.crawl()
if __name__ == '__main__':
moments = Moments()
moments.main()
配置代码config.py
import os
# 平台
PLATFORM = 'Android'
# 设备名称 通过 adb devices -l 获取
DEVICE_NAME = 'MI_NOTE_Pro'
# APP路径
APP = os.path.abspath('.') + '/weixin.apk'
# APP包名
APP_PACKAGE = 'com.tencent.mm'
# 入口类名
APP_ACTIVITY = '.ui.LauncherUI'
# Appium地址
DRIVER_SERVER = 'http://localhost:4723/wd/hub'
# 等待元素加载时间
TIMEOUT = 300
# 微信手机号密码
USERNAME = ''
PASSWORD = ''
# 滑动点
FLICK_START_X = 300
FLICK_START_Y = 300
FLICK_DISTANCE = 700
# MongoDB配置
MONGO_URL = 'localhost'
MONGO_DB = 'moments'
MONGO_COLLECTION = 'moments'
# 滑动间隔
SCROLL_SLEEP_TIME = 1
时间处理代码processor.py
import time
import re
class Processor():
def date(self, datetime):
"""
处理时间
:param datetime: 原始时间
:return: 处理后时间
"""
if re.match('d+分钟前', datetime):
minute = re.match('(d+)', datetime).group(1)
datetime = time.strftime('%Y-%m-%d', time.localtime(time.time() - float(minute) * 60))
if re.match('d+小时前', datetime):
hour = re.match('(d+)', datetime).group(1)
datetime = time.strftime('%Y-%m-%d', time.localtime(time.time() - float(hour) * 60 * 60))
if re.match('昨天', datetime):
datetime = time.strftime('%Y-%m-%d', time.localtime(time.time() - 24 * 60 * 60))
if re.match('d+天前', datetime):
day = re.match('(d+)', datetime).group(1)
datetime = time.strftime('%Y-%m-%d', time.localtime(time.time()) - float(day) * 24 * 60 * 60)
return datetime
最后
以上就是矮小嚓茶为你收集整理的利用appium和Android模拟器爬取微信朋友圈(解决每次重启登录)的全部内容,希望文章能够帮你解决利用appium和Android模拟器爬取微信朋友圈(解决每次重启登录)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复