android AccessibilityService合法合规采集大众点评app商店商品详情(2024-09-02)

devtools/2024/9/18 12:43:11/ 标签: android, java, 前端, 数据采集, 点评app

免责任声明:

        任何可操作性的内容与本人无关,文章内容仅供参考学习,如有侵权损害贵公司利益,请联系作者,会立刻马上进行删除。

一、原理介绍


1、打开大众点评app商店

java">    public void open_shop(Context context,String shop_id){String url="dianping://gcshopshell?shopuuid="+shop_id;scroll_count=0;Uri uri = Uri.parse(url); //Intent intent =new Intent(Intent.ACTION_VIEW,uri);;intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);context.startActivity(intent);}

2、采集如下字段:

java">    public class Commodity{public int id;public String title;        //商品标题public String price;      //售价public String market_price;  //市场价public String sales;            //年销量public String shop_id;        //商店idpublic String shop_index;public int count;}

3、 保存数据为Csv文件

java">Csv csv1=Csv.getInstance(context);boolean bres=csv1.save_commodities(commodities);if(bres==false){fb.set_show("保存数据失败!请检查有没有数据存储权限!");return;}

4、滚动屏幕

java">private void performScroll(AccessibilityNodeInfo rootNode){if(mCurrentUI.startsWith("com.dianping.shopshell")){AccessibilityNodeInfo scrollNode=AccessibilityHelper.findNodeInfosById(rootNode,"com.dianping.v1:id/pagecontainer_recyclerview",0);if(scrollNode!=null) {if (scroll_count < 10) {AccessibilityHelper.performScrollForward(scrollNode);AccessibilityNodeInfo firstNode=AccessibilityHelper.findNodeInfoByTextAllMatched(rootNode,"抢购");if(firstNode==null)scroll_count=10;}else {AccessibilityHelper.performScrollBackward(scrollNode);AccessibilityNodeInfo firstNode=AccessibilityHelper.findNodeInfoByTextAllMatched(rootNode,"封面");if(firstNode!=null)scroll_count=0;}scroll_count += 1;if (scroll_count > 20) {scroll_count = 0;}}//AccessibilityNodeInfo no_moreNode=AccessibilityHelper.findNodeInfosByText(rootNode,"收起",0);}

5、采集数据

java">private Commodity get_commodity(AccessibilityNodeInfo buyNode){try{AccessibilityNodeInfo parent=buyNode.getParent();if(parent==null)return null;parent=parent.getParent();if(parent==null)return null;int price_count=0;Commodity commodity=new Commodity();for (int i = 0; i < parent.getChildCount(); i++) {AccessibilityNodeInfo child=parent.getChild(i);if(child!=null&&child.getText()!=null){String text=child.getText().toString();text=text.replaceAll(",","[comma]");commodity.shop_id=shop_id;commodity.shop_index=String.valueOf(csv.shop_index);commodity.count=commodity_count;if(i==0){//if(isInCommodities(text))return null;commodity.title=text;}if(text.startsWith("年售"))commodity.sales=text;if(text.startsWith("全国爆卖"))commodity.sales=text;if(text.startsWith("¥")){if(price_count==0)commodity.price=text;elseif(price_count==1)commodity.market_price=text;price_count+=1;}}}if(isInCommodities(commodity))return null;return commodity;}catch (Exception e){MyLog.e(e);return null;}}private boolean isInCommodities(String title){for (Commodity commodity:commodities){if(title.equals(commodity.title))return true;}return false;}

6、获取商品数量并点击更多,展开商品信息

java">  private void performMoreClick(AccessibilityNodeInfo rootNode){if(commodity_count>0)return;AccessibilityNodeInfo moreNode=AccessibilityHelper.findNodeInfosByText(rootNode,"个团购",0);if(moreNode!=null) {String text=moreNode.getText().toString();if(text.startsWith("更多")){AccessibilityNodeInfo parent=moreNode.getParent();if(parent==null)return;if(parent.getClassName().toString().equals("android.widget.LinearLayout")){MyLog.i("找到:"+text);int more=Funcs.getDigital(text);if(more>0)commodity_count=more+5;show_count();AccessibilityHelper.performClick(moreNode);}}return;}moreNode=AccessibilityHelper.findNodeInfosByText(rootNode,"个商品",0);if(moreNode!=null) {String text=moreNode.getText().toString();if(text.indexOf("更多")>0){String say="非美容院商店...跳过";FloatWindowButton fb=FloatWindowButton.getInstance(context);fb.set_show(say);Csv csv1=Csv.getInstance(context);boolean bres=csv1.save_no_shop_id(shop_id,String.valueOf(csv1.shop_index));if(bres==false){fb.set_show("保存数据失败!请检查有没有数据存储权限!");return;}open_next_shop_prepare(Config.interval,false);}return;}}

二、完整源代码

java">
package accessibility.app;
import accessibility.AccessibilityFindByText;
import accessibility.AccessibilityHelper;
import accessibility.BaseAccessibilityJob;
import accessibility.AccService;
import floatwindow.FloatWindowButton;
import utils.Config;
import utils.Csv;
import utils.Funcs;
import utils.MyLog;import android.content.Context;
import android.content.Intent;
import android.graphics.Point;
import android.net.Uri;
import android.os.Handler;
import android.util.Log;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.Toast;import com.dp.jp.MainActivity;import java.util.ArrayList;
import java.util.List;public class ShopInfoJob  extends BaseAccessibilityJob{public static final int STAT_NONE=0;public static final int STAT_WORKING=1;public static final int STAT_WAITING=2;public static int state=0;private static ShopInfoJob current;private utils.Csv csv;private int scroll_count=0;public String CurrentUI=null;public String shop_id=null;private boolean is_alarm=false;//--------------------------------------------------------------------------public List<Commodity> commodities=new ArrayList<Commodity>() ;public boolean isBusy=false;private int commodity_count=0;private ShopInfoJob() {//super(new String[]{Config.PKG_IM_TOKEN,Config.PKG_HUOBI,Config.PKG_BTD});super(new String[]{"com.dianping.v1"});//super(null);技术支持:metabycf or byc6352csv= Csv.getInstance(context);}public static synchronized ShopInfoJob getInstance() {if(current == null) {current = new ShopInfoJob();}return current;}@Overridepublic void onCreateJob(AccService service) {super.onCreateJob(service);EventStart();}@Overridepublic void onStopJob() {super.onStopJob();}/** (刷新处理流程)* @see accessbility.AccessbilityJob#onWorking()*/@Overridepublic void onWorking(){FloatWindowButton fb=FloatWindowButton.getInstance(context);String say="正在执行任务...";if(commodity_count>0&&commodities.size()>=commodity_count){say="采集完成...";fb.set_show(say);Csv csv1=Csv.getInstance(context);boolean bres=csv1.save_commodities(commodities);if(bres==false){fb.set_show("保存数据失败!请检查有没有数据存储权限!");return;}AccessibilityHelper.performBack(service);Funcs.sleep(2);open_next_shop_prepare(Config.interval,false);return;}AccessibilityNodeInfo rootNode = service.getRootInActiveWindow();if (rootNode == null) return;fb.set_show(say);//com.dianping.shopshell.GCShopInfoActivityif(rootNode.getPackageName().toString().equals("com.dianping.v1")){if(mCurrentUI.startsWith("com.dianping.shopshell.")) {performMoreClick(rootNode);performScroll(rootNode);}}}@Overridepublic void onReceiveJob(AccessibilityEvent event) {super.onReceiveJob(event);if(!mIsEventWorking)return;if(!mIsTargetPackageName)return;CurrentUI=mCurrentUI;if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED){MyLog.i("mCurrentUI="+mCurrentUI);if(mCurrentUI.startsWith("com.dianping.shopshell.")){if(state==STAT_WORKING) {}if(is_alarm)Funcs.alarm(context,false);}if(mCurrentUI.startsWith("android.app.Dialog")){if(Config.auto_close_verify){AccessibilityNodeInfo rootNode=event.getSource();if(rootNode==null)return;//close_verify_btn(rootNode);}else {Funcs.alarm(context,true);is_alarm=true;}}if(mCurrentUI.startsWith("com.meituan.android.yoda.activity.YodaConfirmActivity")){if(Config.auto_close_verify){AccessibilityNodeInfo rootNode=event.getSource();if(rootNode==null)return;//close_verify_back(rootNode);}else {Funcs.alarm(context,true);is_alarm=true;}}}if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED){if(commodity_count>0&&commodity_count==commodities.size())return;if(mCurrentUI.startsWith("com.dianping.shopshell.")){if(state==STAT_WORKING) {AccessibilityNodeInfo rootNode=event.getSource();if(rootNode==null)return;pluck_from_shop(rootNode);TimeStart();performMoreClick(rootNode);}}}}//---------------------------------------------------------------------//"dianping://gcshopshell?shopuuid=H44paDfKZflcSGHd"public void open_shop(Context context,String shop_id){String url="dianping://gcshopshell?shopuuid="+shop_id;scroll_count=0;Uri uri = Uri.parse(url); //Intent intent =new Intent(Intent.ACTION_VIEW,uri);;intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);context.startActivity(intent);}/*1.浮动窗口:下一个2.working.over3.主窗口:继续4.accservice open*/public void open_next_shop_prepare(int delay,boolean cur){if(runnableStart!=null)return;state=STAT_WAITING;//et_cur_id.setText(String.valueOf(csv1.commodities_index));runnableStart = new Runnable() {@Overridepublic void run() {try {Csv csv1=Csv.getInstance(context);if(cur)shop_id=csv1.get_shop_id();elseshop_id=csv1.get_next_shop_id();FloatWindowButton fb=FloatWindowButton.getInstance(context);fb.ShowFloatWindow();if(csv1.shop_index>Config.end_id||csv1.shop_index>csv1.get_shop_total_count()||shop_id.equals("")){String say="已完成任务";fb.set_show(say);runnableStart=null;return;}state=STAT_WORKING;String say="开始执行任务...";fb.set_show(say);fb.set_commodity_count_show(String.valueOf(csv1.shop_index));open_shop(context,shop_id);commodities.clear();commodity_count=0;runnableStart=null;}catch (Exception e){MyLog.e(e.getMessage().toString());}}};handler.postDelayed(runnableStart, delay);}//private boolean pluck_start=false;//private int pluck_count=0;//private Commodity commodity=null;private void pluck_from_shop(AccessibilityNodeInfo rootNode){try{if(mCurrentUI.startsWith("com.dianping.shopshell.")){if(isBusy)return;isBusy=true;try{//com.dianping.v1:id/pagecontainer_recyclerview//AccessibilityNodeInfo pagecontainerNode=AccessibilityHelper.findNodeInfosById(rootNode,"com.dianping.v1:id/pagecontainer_recyclerview",0);//if(pagecontainerNode!=null){List<AccessibilityNodeInfo>  buyNodes=AccessibilityHelper.findNodeInfosByTextAllMatched(rootNode,"抢购");if(buyNodes==null||buyNodes.size()==0)return;for (AccessibilityNodeInfo buyNode:buyNodes){Commodity commodity=get_commodity(buyNode) ;if(commodity!=null)commodities.add(commodity);}show_count();//}}catch (Exception e){MyLog.e(e.getMessage().toString());return ;}finally {isBusy=false;}}}catch (Exception e){MyLog.e(e.getMessage().toString());}}private void performScroll(AccessibilityNodeInfo rootNode){if(mCurrentUI.startsWith("com.dianping.shopshell")){AccessibilityNodeInfo scrollNode=AccessibilityHelper.findNodeInfosById(rootNode,"com.dianping.v1:id/pagecontainer_recyclerview",0);if(scrollNode!=null) {if (scroll_count < 10) {AccessibilityHelper.performScrollForward(scrollNode);AccessibilityNodeInfo firstNode=AccessibilityHelper.findNodeInfoByTextAllMatched(rootNode,"抢购");if(firstNode==null)scroll_count=10;}else {AccessibilityHelper.performScrollBackward(scrollNode);AccessibilityNodeInfo firstNode=AccessibilityHelper.findNodeInfoByTextAllMatched(rootNode,"封面");if(firstNode!=null)scroll_count=0;}scroll_count += 1;if (scroll_count > 20) {scroll_count = 0;}}//AccessibilityNodeInfo no_moreNode=AccessibilityHelper.findNodeInfosByText(rootNode,"收起",0);//if(no_moreNode!=null&&no_moreNode.getText()!=null&&no_moreNode.getText().toString().startsWith("收起")) scroll_count=10;}}private Commodity get_commodity(AccessibilityNodeInfo buyNode){try{AccessibilityNodeInfo parent=buyNode.getParent();if(parent==null)return null;parent=parent.getParent();if(parent==null)return null;int price_count=0;Commodity commodity=new Commodity();for (int i = 0; i < parent.getChildCount(); i++) {AccessibilityNodeInfo child=parent.getChild(i);if(child!=null&&child.getText()!=null){String text=child.getText().toString();text=text.replaceAll(",","[comma]");commodity.shop_id=shop_id;commodity.shop_index=String.valueOf(csv.shop_index);commodity.count=commodity_count;if(i==0){//if(isInCommodities(text))return null;commodity.title=text;}if(text.startsWith("年售"))commodity.sales=text;if(text.startsWith("全国爆卖"))commodity.sales=text;if(text.startsWith("¥")){if(price_count==0)commodity.price=text;elseif(price_count==1)commodity.market_price=text;price_count+=1;}}}if(isInCommodities(commodity))return null;return commodity;}catch (Exception e){MyLog.e(e);return null;}}private boolean isInCommodities(String title){for (Commodity commodity:commodities){if(title.equals(commodity.title))return true;}return false;}private boolean isInCommodities(Commodity commodity_new){try {for (Commodity commodity:commodities){if(Funcs.isEqua(commodity_new.title,commodity.title)&&Funcs.isEqua(commodity_new.price,commodity.price)&&Funcs.isEqua(commodity_new.sales,commodity.sales))return true;}return false;}catch (Exception e){MyLog.e(e);return false;}}private void performMoreClick(AccessibilityNodeInfo rootNode){if(commodity_count>0)return;AccessibilityNodeInfo moreNode=AccessibilityHelper.findNodeInfosByText(rootNode,"个团购",0);if(moreNode!=null) {String text=moreNode.getText().toString();if(text.startsWith("更多")){AccessibilityNodeInfo parent=moreNode.getParent();if(parent==null)return;if(parent.getClassName().toString().equals("android.widget.LinearLayout")){MyLog.i("找到:"+text);int more=Funcs.getDigital(text);if(more>0)commodity_count=more+5;show_count();AccessibilityHelper.performClick(moreNode);}}return;}moreNode=AccessibilityHelper.findNodeInfosByText(rootNode,"个商品",0);if(moreNode!=null) {String text=moreNode.getText().toString();if(text.indexOf("更多")>0){String say="非美容院商店...跳过";FloatWindowButton fb=FloatWindowButton.getInstance(context);fb.set_show(say);Csv csv1=Csv.getInstance(context);boolean bres=csv1.save_no_shop_id(shop_id,String.valueOf(csv1.shop_index));if(bres==false){fb.set_show("保存数据失败!请检查有没有数据存储权限!");return;}open_next_shop_prepare(Config.interval,false);}return;}}private void show_count(){String say="";if(commodity_count==0)say="当前商店编号:"+String.valueOf(csv.shop_index)+"已找到商品数:"+String.valueOf(commodities.size());elsesay="当前商店编号:"+String.valueOf(csv.shop_index)+"共有商品数:"+String.valueOf(commodity_count)+"已找到商品数:"+String.valueOf(commodities.size());FloatWindowButton.getInstance(context).set_commodity_count_show(say);}private Runnable runnableStart=null;private Handler handler = new Handler();public class Commodity{public int id;public String title;public String price;public String market_price;public String sales;public String shop_id;public String shop_index;public int count;}}

技术支持:

UVHvvJozOTg0ODg3MuW+ruS/oe+8mmJ5YzYzNTLmiJZtZXRhYnljZueUteaKpe+8mmJ5YzAx (base64解码)


http://www.ppmy.cn/devtools/107747.html

相关文章

负载均衡调度器--LVS

文章目录 集群和分布式集群分布式 LVS介绍LVS特点LVS工作原理LVS集群架构 LVS集群中的术语CIPVIPRSDIPRIP LVS集群的工作模式NAT模式DR模式DR模式的特点: TUN模式 LVS调度算法LVS相关软件ipvsadm 命令管理集群服务&#xff1a;增、改、删管理集群上的RS:增、改、删 创建集群 LV…

Elastic Stack--ELFK实例与Dashboard界面

前言&#xff1a;本博客仅作记录学习使用&#xff0c;部分图片出自网络&#xff0c;如有侵犯您的权益&#xff0c;请联系删除 学习B站博主教程笔记&#xff1a; 最新版适合自学的ElasticStack全套视频&#xff08;Elk零基础入门到精通教程&#xff09;Linux运维必备—Elastic…

构建STM32智能平衡车项目:PID控制算法与蓝牙通信技术

一、项目概述 项目目标和用途 本项目旨在设计和实现一款基于STM32单片机的平衡车。平衡车是一种新型的个人交通工具&#xff0c;广泛应用于短途出行、休闲娱乐等场景。通过本项目&#xff0c;我们希望能够实现一款具备良好稳定性和操控性的平衡车&#xff0c;能够在不同的地形…

Java反射与File操作:创建文件的实践

引言 在Java中&#xff0c;反射是一种强大的机制&#xff0c;允许我们在运行时动态地获取类的信息以及创建和操作对象。本文将展示如何结合使用Java反射和java.io.File类来创建文件。具体来说&#xff0c;我们将通过反射获取File类的构造器&#xff0c;并创建一个新文件。 步…

第4章-08-用Python Requests库模拟浏览器访问接口

🏆作者简介,黑夜开发者,CSDN领军人物,全栈领域优质创作者✌,CSDN博客专家,阿里云社区专家博主,2023年CSDN全站百大博主。 🏆数年电商行业从业经验,历任核心研发工程师,项目技术负责人。 🏆本文已收录于专栏:Web爬虫入门与实战精讲,后续完整更新内容如下。 文章…

Qt 创建一个json数组对象写入文档并从文档读出q

void createJsonArray() { // 创建一个JSON数组 QJsonArray jsonArray; // 创建一些JSON对象并添加到数组中 for (int i 0; i < 3; i) { QJsonObject jsonObject; jsonObject["key" QString::number(i)] "value" QStri…

【Linux 从基础到进阶】Elasticsearch 搜索服务安装与调优

Elasticsearch 搜索服务安装与调优 引言 Elasticsearch 是一个分布式的、基于 RESTful API 的搜索和分析引擎,专为快速处理大量数据而设计。它经常被用来进行全文搜索、日志和指标分析等操作。本文将介绍如何在 CentOS 和 Ubuntu 系统上安装 Elasticsearch,并进行必要的调优…

Linux CentOS 部署Docker

1. yum 配置 &#xff08;1&#xff09;更新yum yum update -y 如果不升级更新yum 可能在后续docker部署后再更新容器会出现oci runtime error等 &#xff08;2&#xff09;安装yum工具类准备 yum install -y yum-utils device-mapper-persistent-data lvm2 &#xff08;3&…

从零开始学数据结构系列之第五章《B树的删除》

文章目录 情况1案例1案例2 情况2样例1&#xff1a; 往期回顾 可以观看以下两个UP的视频来先看看 B树的插入删除1 B树的插入和删除2 删除操作是指&#xff0c;根据key删除记录&#xff0c;如果B树中的记录中不存对应key的记录&#xff0c;则删除失败。 1&#xff09;如果当前需…

[线程]单例模式 及 指令重排序

文章目录 一. 单例模式饿汉模式懒汉模式单例模式中涉及到的线程安全问题 二. 指令重排序引起线程安全问题 一. 单例模式 单例模式, 是一种经典的设计模式 设计模式: 类似于棋谱, 把编程中各种经典的问题场景给你盘一盘, 并给出一下解决方案 遇到这种场景, 代码就这样写, 绝对不…

leetcode:516 最长回文字序列

516. 最长回文字序列 题目链接https://leetcode.cn/problems/longest-palindromic-subsequence/ 题目描述 给定一个字符串 s&#xff0c;找到 s 中最长的回文子序列。你可以假设 s 的最大长度为 1000。 示例 1: 输入: "bbbab" 输出: 4 解释: 一个…

单元测试、系统测试和集成测试知识详解

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 一、单元测试的概念 单元测试是对软件基本组成单元进行的测试&#xff0c;如函数或一个类的方法。当然这里的基本单元不仅仅指的是一个函数或者方法&#xff…

MySQL基础:索引

&#x1f48e;所属专栏&#xff1a;MySQL 1. 索引概述 MySQL中的索引是帮助MySQL高效获取数据的数据结构&#xff0c;可以极大地提高数据库的查询效率&#xff0c;减少数据库的I/O成本&#xff0c;就像书的目录一样&#xff0c;它可以帮助我们快速定位到书中的内容。 优势&…

组件化是如何进行通信的

目录 1.接口&#xff08;Interface&#xff09;2.事件总线&#xff08;[Event Bus](https://blog.csdn.net/Sh_12345/article/details/131623985)&#xff09;3. 服务&#xff08;Service&#xff09;4.消息队列&#xff08;Message Queue&#xff09;5.依赖注入&#xff08;De…

9. GIS技术支持工程师岗位职责、技术要求和常见面试题

本系列文章目录&#xff1a; 1. GIS开发工程师岗位职责、技术要求和常见面试题 2. GIS数据工程师岗位职责、技术要求和常见面试题 3. GIS后端工程师岗位职责、技术要求和常见面试题 4. GIS前端工程师岗位职责、技术要求和常见面试题 5. GIS工程师岗位职责、技术要求和常见面试…

leetcode209. Minimum Size Subarray Sum

题目 Given an array of positive integers nums and a positive integer target, return the minimal length of a subarray whose sum is greater than or equal to target. If there is no such subarray, return 0 instead. Example 1: Input: target 7, nums [2,3,1,…

209.长度最小的子数组

题目 链接&#xff1a;leetcode链接 思路分析&#xff08;滑动窗口&#xff09; 1、为什么会想到使用滑动窗口呢&#xff1f; 首先&#xff0c;子数组是连续的&#xff0c;第二&#xff0c;所有的元素都是正整数&#xff0c;所以子数组的和具有单调性。 所以&#xff0c;对…

进程

进程 进程进程的含义PCB块内存空间进程分类&#xff1a;进程的作用进程的状态进程已经准备好执行&#xff0c;所有的资源都已分配&#xff0c;只等待CPU时间进程的调度 进程相关命6.查询进程相关命令1.ps aux2.top3.kill和killall发送一个信号 函数1.fork();2.getpid3.getppid示…

一台手机一个ip地址吗?手机ip地址泄露了怎么办

在数字化时代&#xff0c;‌手机作为我们日常生活中不可或缺的一部分&#xff0c;‌其网络安全性也日益受到关注。‌其中一个常见的疑问便是&#xff1a;‌“一台手机是否对应一个固定的IP地址&#xff1f;‌”实际上&#xff0c;‌情况并非如此简单。‌本文首先解答这一问题&a…

一个webpack的plugin 的简单例子

下面是一个简单的 Webpack 插件示例&#xff0c;该插件会在输出目录中创建一个文本文件&#xff0c;并向其中写入当前的时间戳。这个插件演示了如何注册一个监听器&#xff0c;在编译完成之后执行自定义的操作。 首先&#xff0c;你需要创建一个 JavaScript 文件来定义你的插件…