android AccessibilityService合法合规采集大众点评app商店商品详情(2024-09-02)
免责任声明:
任何可操作性的内容与本人无关,文章内容仅供参考学习,如有侵权损害贵公司利益,请联系作者,会立刻马上进行删除。
一、原理介绍
1、打开大众点评app商店
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、采集如下字段:
public class Commodity{
public int id;
public String title; //商品标题
public String price; //售价
public String market_price; //市场价
public String sales; //年销量
public String shop_id; //商店id
public String shop_index;
public int count;
}
3、 保存数据为Csv文件
Csv csv1=Csv.getInstance(context);
boolean bres=csv1.save_commodities(commodities);
if(bres==false){
fb.set_show("保存数据失败!请检查有没有数据存储权限!");
return;
}
4、滚动屏幕
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、采集数据
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;
else
if(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、获取商品数量并点击更多,展开商品信息
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;
}
}
二、完整源代码
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 byc6352
csv= Csv.getInstance(context);
}
public static synchronized ShopInfoJob getInstance() {
if(current == null) {
current = new ShopInfoJob();
}
return current;
}
@Override
public void onCreateJob(AccService service) {
super.onCreateJob(service);
EventStart();
}
@Override
public void onStopJob() {
super.onStopJob();
}
/*
* (刷新处理流程)
* @see accessbility.AccessbilityJob#onWorking()
*/
@Override
public 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.GCShopInfoActivity
if(rootNode.getPackageName().toString().equals("com.dianping.v1")){
if(mCurrentUI.startsWith("com.dianping.shopshell.")) {
performMoreClick(rootNode);
performScroll(rootNode);
}
}
}
@Override
public 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.over
3.主窗口:继续
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() {
@Override
public void run() {
try {
Csv csv1=Csv.getInstance(context);
if(cur)
shop_id=csv1.get_shop_id();
else
shop_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;
else
if(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());
else
say="当前商店编号:"+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解码)