{"id":13626205,"url":"https://github.com/seveniruby/AppCrawler","last_synced_at":"2025-04-16T11:31:29.942Z","repository":{"id":46257688,"uuid":"51831105","full_name":"seveniruby/AppCrawler","owner":"seveniruby","description":"基于appium的app自动遍历工具","archived":false,"fork":false,"pushed_at":"2023-12-17T15:47:44.000Z","size":65447,"stargazers_count":1182,"open_issues_count":7,"forks_count":466,"subscribers_count":80,"default_branch":"master","last_synced_at":"2024-11-08T15:47:26.204Z","etag":null,"topics":["appium","appium-app","crawler","diff","scala","xpath"],"latest_commit_sha":null,"homepage":"https://ceshiren.com/c/opensource/appcrawler","language":"Scala","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/seveniruby.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-02-16T11:27:13.000Z","updated_at":"2024-11-08T02:33:26.000Z","dependencies_parsed_at":"2024-06-11T19:03:34.874Z","dependency_job_id":"69b4244f-2ac7-4821-8c20-368aeac21d78","html_url":"https://github.com/seveniruby/AppCrawler","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seveniruby%2FAppCrawler","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seveniruby%2FAppCrawler/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seveniruby%2FAppCrawler/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/seveniruby%2FAppCrawler/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/seveniruby","download_url":"https://codeload.github.com/seveniruby/AppCrawler/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249235066,"owners_count":21235141,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["appium","appium-app","crawler","diff","scala","xpath"],"created_at":"2024-08-01T21:02:12.845Z","updated_at":"2025-04-16T11:31:29.649Z","avatar_url":"https://github.com/seveniruby.png","language":"Scala","funding_links":[],"categories":["移动端性能","Scala"],"sub_categories":[],"readme":"# appcrawler\n\nAppcrawler是一个基于自动遍历的App爬虫工具，支持Android和IOS，支持真机和模拟器。最大的特点是灵活性高，可通过配置来设定遍历的规则。\n\n## quick start\n\n```bash\n-------------------------------------------------\nappcrawler 全平台自动遍历测试工具\nQ\u0026A: https://ceshiren.com/c/opensource/appcrawler\nauthor: seveniruby\n-------------------------------------------------\n\n\nUsage: appcrawler [options]\n\n  -a, --app \u003cvalue\u003e        Android或者iOS的文件地址, 可以是网络地址, 赋值给appium的app选项\n  -e, --encoding \u003cvalue\u003e   set encoding, such as UTF-8 GBK\n  -c, --conf \u003cvalue\u003e       配置文件地址\n  -p, --platform \u003cvalue\u003e   平台类型android或者ios, 默认会根据app后缀名自动判断\n  -t, --maxTime \u003cvalue\u003e    最大运行时间. 单位为秒. 超过此值会退出. 默认最长运行3个小时\n  -u, --appium \u003cvalue\u003e     appium的url地址\n  -o, --output \u003cvalue\u003e     遍历结果的保存目录. 里面会存放遍历生成的截图, 思维导图和日志\n  --capability k1=v1,k2=v2...\n                           appium capability选项, 这个参数会覆盖-c指定的配置模板参数, 用于在模板配置之上的参数微调\n  -y, --yaml \u003cvalue\u003e       代表配置的yaml语法，比如blackList: [ {xpath: action_night } ]，用于避免使用配置文件的情况\n  -r, --report \u003cvalue\u003e     输出html和xml报告\n  --template \u003cvalue\u003e       输出代码模板\n  --master \u003cvalue\u003e         master的diff.yml文件地址\n  --candidate \u003cvalue\u003e      candidate环境的diff.yml文件\n  -v, --verbose-debug      是否展示更多debug信息\n  -vv, --verbose-trace     是否展示更多trace信息\n  --demo                   生成demo配置文件学习使用方法\n  --help\n                           示例\n                           appcrawler -a xueqiu.apk\n                           appcrawler -a xueqiu.apk --capability noReset=true\n                           appcrawler -c conf/xueqiu.json -p android -o result/\n                           appcrawler -c xueqiu.yaml --capability udid=[你的udid] -a Snowball.app\n                           appcrawler -c xueqiu.yaml -a Snowball.app -u 4730\n                           appcrawler -c xueqiu.yaml -a Snowball.app -u http://127.0.0.1:4730/wd/hub\n\n                           #生成demo配置文件到当前目录下的demo.yaml\n                           appcrawler --demo\n\n                           #启动已经安装过的app\n                           appcrawler --capability \"appPackage=com.xueqiu.android,appActivity=.view.WelcomeActivityAlias\"\n\n                           #使用yaml参数\n                           appcrawler -a xueqiu.apk -y \"blackList: [ {xpath: action_night}, {xpath: '.*[0-9\\\\.]{2}.*'} ]\"\n\n                           #从已经结束的结果中重新生成报告\n                           appcrawler --report result/\n\n```\n\n## 配置文件格式\n\n### 执行参数与配置文件\n\n- capability设置：与appium完全一致\n- testcase：用于启动app后的基础测试用例\n- selectedList：遍历范围设定\n- triggerActions：特定条件触发执行动作的设置\n- selectedList：需要被遍历的元素范围\n- firstList：优先被点击\n- lastList：最后被点击\n- tagLimitMax：同祖先（同类型）的元素最多点击多少次\n- backButton：当所有元素都被点击后默认后退控件定位\n- blackList：黑名单\n- maxDepth: 遍历的最大深度\n\n### 配置的最小单元 测试用例模型\n\ntestcase的完整形态\n\n- given：所有的先决条件\n- when：先决条件成立后的行为\n- then：断言集合\n\ntestcase的简写形态\n\n- xpath：对应when里的xpath\n- action：对应when的action\n\n执行参数比配置文件优先级别高\n\n- given 前提条件\n- when 执行动作\n- then 写断言\n\n简写形态\n\n- xpath xpath支持xpath表达式、正则、包含\n- action 支持\n\n### xpath定义\n\n- xpath\n    - //*[@resource-id=‘xxxx’]\n    - //*[contains(@text, ‘密码’)]\n- 正则\n    - ^确定$\n    - ^.*输入密码\n- 包含\n    - 密码\n    - 输入\n    - 请\n\n### action定义\n\n- \"\" 只是截图记录\n- back 后退\n- backApp 回退到当前的app 默认等价于back行为 可定制\n- monkey 随机事件\n- click\n- longTap\n- xxx() 执行scala或者java代码\n    - Thread.sleep(3000)\n    - driver.swipe(0.9, 0.5, 0.1, 0.5)\n- 非以上所有行为是输入 xx ddd\n\n### 完整配置文件\n\n```yaml\n---\nmaxTimeDescription: \"最大运行时间\"\nmaxTime: 10800\nmaxDepthDescription: \"默认的最大深度10, 结合baseUrl可很好的控制遍历的范围\"\nmaxDepth: 10\ncapabilityDescription: \"appium的capability通用配置，其中automationName代表自动化的驱动引擎，除了支持appium的\\\n  所有引擎外，额外增加了adb和selenium的支持\"\ncapability:\n  appActivity: \".ApiDemos\"\n  appium: \"http://127.0.0.1:4723/wd/hub\"\n  noReset: \"true\"\n  appPackage: \"io.appium.android.apis\"\n  fullReset: \"false\"\ntestcaseDescription: \"测试用例设置，用于遍历开始之前的一些前置操作，比如自动登录\"\ntestcase:\n  name: \"AppCrawler TestCase\"\n  steps:\n    - given: []\n      when: null\n      then: []\n      xpath: \"/*/*\"\n      action: \"Thread.sleep(1000)\"\n      actions: []\n      times: -1\ntriggerActionsDescription: \"在遍历过程中需要随时处理的一些操作，比如弹框、登录等\"\ntriggerActions:\n  - given: []\n    when: null\n    then: []\n    xpath: \"permission_allow_button\"\n    action: \"\"\n    actions: []\n    times: 3\n  - given: []\n    when: null\n    then: []\n    xpath: \"允许\"\n    action: \"\"\n    actions: []\n    times: 3\nselectedListDescription: \"默认遍历列表，只有出现在这个列表里的控件范围才会被遍历\"\nselectedList:\n  - given: []\n    when: null\n    then: []\n    xpath: \"//*[contains(name(), 'Button')]\"\n    action: \"\"\n    actions: []\n    times: -1\n  - given: []\n    when: null\n    then: []\n    xpath: \"//*[contains(name(), 'Text') and @clickable='true' and string-length(@text)\u003c10]\"\n    action: \"\"\n    actions: []\n    times: -1\n  - given: []\n    when: null\n    then: []\n    xpath: \"//*[@clickable='true']//*[contains(name(), 'Text') and string-length(@text)\u003c10]\"\n    action: \"\"\n    actions: []\n    times: -1\n  - given: []\n    when: null\n    then: []\n    xpath: \"//*[contains(name(), 'Image') and @clickable='true']\"\n    action: \"\"\n    actions: []\n    times: -1\n  - given: []\n    when: null\n    then: []\n    xpath: \"//*[@clickable='true']/*[contains(name(), 'Image')]\"\n    action: \"\"\n    actions: []\n    times: -1\n  - given: []\n    when: null\n    then: []\n    xpath: \"//*[contains(name(), 'Image') and @name!='']\"\n    action: \"\"\n    actions: []\n    times: -1\n  - given: []\n    when: null\n    then: []\n    xpath: \"//*[contains(name(), 'Text') and @name!='' and string-length(@label)\u003c10]\"\n    action: \"\"\n    actions: []\n    times: -1\n  - given: []\n    when: null\n    then: []\n    xpath: \"//a\"\n    action: \"\"\n    actions: []\n    times: -1\n  - given: []\n    when: null\n    then: []\n    xpath: \"//*[contains(@class, 'Text') and @clickable='true' and string-length(@text)\u003c10]\"\n    action: \"\"\n    actions: []\n    times: -1\n  - given: []\n    when: null\n    then: []\n    xpath: \"//*[@clickable='true']//*[contains(@class, 'Text') and string-length(@text)\u003c10]\"\n    action: \"\"\n    actions: []\n    times: -1\n  - given: []\n    when: null\n    then: []\n    xpath: \"//*[contains(@class, 'Image') and @clickable='true']\"\n    action: \"\"\n    actions: []\n    times: -1\n  - given: []\n    when: null\n    then: []\n    xpath: \"//*[@clickable='true']/*[contains(@class, 'Image')]\"\n    action: \"\"\n    actions: []\n    times: -1\n  - given: []\n    when: null\n    then: []\n    xpath: \"//*[@clickable='true' and contains(@class, 'Button')]\"\n    action: \"\"\n    actions: []\n    times: -1\nblackListDescription: \"黑名单列表 matches风格, 默认排除内容包含2个数字的控件\"\nblackList:\n  - given: []\n    when: null\n    then: []\n    xpath: \".*[0-9]{2}.*\"\n    action: \"\"\n    actions: []\n    times: -1\nfirstListDescription: \"优先遍历列表，同时出现在selectedList与firstList中的控件会被优先遍历\"\nfirstList: []\nlastListDescription: \"最后遍历列表，同时出现在selectedList与lastList中的控件会被最后遍历\"\nlastList:\n  - given: []\n    when: null\n    then: []\n    xpath: \"//*[@selected='true']/..//*\"\n    action: \"\"\n    actions: []\n    times: -1\n  - given: []\n    when: null\n    then: []\n    xpath: \"//*[@selected='true']/../..//*\"\n    action: \"\"\n    actions: []\n    times: -1\nbackButtonDescription: \"后退按钮列表，默认在所有控件遍历完成后，才会最后点击后退按钮。目前具备了自动判断返回按钮的能力，默认不需要配置\"\nbackButton:\n  - given: []\n    when: null\n    then: []\n    xpath: \"Navigate up\"\n    action: \"\"\n    actions: []\n    times: -1\nxpathAttributesDescription: \"在生成一个控件的唯一定位符中应该包含的关键属性\"\nxpathAttributes:\n  - \"name()\"\n  - \"name\"\n  - \"label\"\n  - \"value\"\n  - \"resource-id\"\n  - \"content-desc\"\n  - \"text\"\n  - \"id\"\n  - \"name\"\n  - \"innerText\"\n  - \"tag\"\n  - \"class\"\nsortByAttributeDescription: \"陆续根据属性进行遍历排序微调，depth表示从dom中最深层的控件开始遍历，list表示dom中列表优先，\\\n  selected表示菜单最后遍历，这是默认规则，一般不需要改变\"\nsortByAttribute:\n  - \"depth\"\n  - \"list\"\n  - \"selected\"\nfindByDescription: \"默认生成控件唯一定位符的表达式风格，可选项 default|android|id|xpath，默认会自动判断是否使用android定\\\n  位或者ios定位\"\nfindBy: \"xpath\"\nbaseUrlDescription: \"设置一个起始点，从这个起始点开始计算深度，比如默认从登录后的界面开始计算\"\nbaseUrl: []\nappWhiteListDescription: \"app白名单，允许在这些app里进行遍历\"\nappWhiteList: []\nurlBlackListDescription: \"url黑名单，用于排除某些页面的遍历\"\nurlBlackList: []\nurlWhiteListDescription: \"url白名单，仅在这些界面内遍历\"\nurlWhiteList: []\nbeforeStartWaitDescription: \"启动一个app默认等待的时间\"\nbeforeStartWait: 6000\nbeforeRestart: []\nbeforeElementDescription: \"在遍历每个控件之前默认执行的动作\"\nbeforeElement: []\nafterElementDescription: \"在遍历每个控件之后默认执行的动作\"\nafterElement: []\nafterElementWaitDescription: \"在遍历每个控件之后默认等待的时间，用于等待新页面加载\"\nafterElementWait: 500\nafterAllDescription: \"在遍历完当前页面内的所有控件后，是否需要刷新或者滑动\"\nafterAll: []\nafterAllMaxDescription: \"afterAll的最大重试次数，比如连续滑动2次都没新元素即取消\"\nafterAllMax: 2\ntagLimitMaxDescription: \"相似控件最多点击几次\"\ntagLimitMax: 2\ntagLimitDescription: \"设置部分相似控件的最大遍历次数\"\ntagLimit:\n  - given: []\n    when: null\n    then: []\n    xpath: \"确定\"\n    action: \"\"\n    actions: []\n    times: 1000\n  - given: []\n    when: null\n    then: []\n    xpath: \"取消\"\n    action: \"\"\n    actions: []\n    times: 1000\n  - given: []\n    when: null\n    then: []\n    xpath: \"share_comment_guide_btn_name\"\n    action: \"\"\n    actions: []\n    times: 1000\nassertGlobalDescription: \"全局断言\"\nassertGlobal: []\nsuiteNameDescription: \"报告中的测试套件名字可以由列表内的控件内容替换，增强报告中关键界面的辨识度\"\nsuiteName:\n  - \"//*[@selected='true']//android.widget.TextView/@text\"\nscreenshotDescription: \"是否截图\"\nscreenshot: true\nreportTitleDescription: \"报告的title\"\nreportTitle: \"AppCrawler\"\nresultDirDescription: \"结果目录，如果为空会自动创建对应时间戳_报名的结果目录\"\nresultDir: \"\"\nshowCancelDescription: \"是否展示跳过的控件记录\"\nshowCancel: true\npluginListDescription: \"插件列表，暂时禁用，太高级了，很多人不会用\"\nDescription: \"。在selectedList firstList lastList等很多配置中，需要填充的是测试步骤Step类型。Step类型由given（\\\n  满足条件）when（条件满足的行为）then（断言）三部分组成。Step可以简化为xpath（定位表达式，支持xpath 正则 包含关系）与action（点击\\\n  \\ 输入等行为）。\"\npluginList: []\n```\n\n## 金牌赞助商（Gold Sponsor）\n\n![logo霍格沃兹测试学院](https://ceshiren.com/uploads/default/original/3X/a/2/a270cdc0bf8cb41110ce5999d5278515a0e7cf0f.png)\n\n[霍格沃兹测试开发学社](https://ceshiren.com/)\n是 [测吧（北京）科技有限公司](http://qrcode.testing-studio.com/f?from=appcrawler\u0026url=https://ceshiren.com/t/topic/14814)\n旗下业界领先的测试开发技术高端教育品牌。 学院课程均由名企一线测试大牛设计，提供实战驱动的系列课程。涵盖移动app自动化测试、接口自动化测试、性能测试、持续集成/持续交付/DevOps 、测试左移、测试右移、测试管理等课程。\n[点击学习!](http://qrcode.testing-studio.com/f?from=appcrawler\u0026url=https://testerh.ke.qq.com?flowToken=1040391)\n\n[测吧（北京）科技有限公司](http://qrcode.testing-studio.com/f?from=appcrawler\u0026url=https://ceshiren.com/t/topic/14814)\n是一家服务于测试领域的高科技公司，为企业提供全方位的自动化测试技术支持、测试平台开发定制、测试效能提升等咨询与科研合作服务。 先后服务于华为、工信部、信通院等知名企业与机构。\n\n## 编译\n\n```bash\nmvn clean package\n```\n\n## 技术交流\n\n由霍格沃兹测试开发学社维护，技术交流与issue提交请移步 https://ceshiren.com/c/opensource/appcrawler/ 交流\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseveniruby%2FAppCrawler","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fseveniruby%2FAppCrawler","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseveniruby%2FAppCrawler/lists"}