From 350426ff813af2961bdbaa9fe3cf38e593fc50e8 Mon Sep 17 00:00:00 2001 From: ASeidel Date: Mon, 4 Jul 2022 19:18:11 +0200 Subject: [PATCH 1/3] implement search apps by query feature --- google_play_scraper/constants/element.py | 20 +++++++++ google_play_scraper/constants/request.py | 19 ++++++++ google_play_scraper/features/search.py | 54 +++++++++++++++++++++++ tests/e2e_tests/test_search.py | 56 ++++++++++++++++++++++++ 4 files changed, 149 insertions(+) create mode 100644 google_play_scraper/features/search.py create mode 100644 tests/e2e_tests/test_search.py diff --git a/google_play_scraper/constants/element.py b/google_play_scraper/constants/element.py index 12ee5cf..cc5552e 100644 --- a/google_play_scraper/constants/element.py +++ b/google_play_scraper/constants/element.py @@ -154,3 +154,23 @@ class ElementSpecs: Permission_List = ElementSpec( None, [2], lambda container: sorted([item[1] for item in container]) ) + Searchresult = { + "appId": ElementSpec(None, [0,0,0]), + "icon": ElementSpec(None, [0,1,3,2]), + "screenshots": ElementSpec(None, [0,2], lambda container: [item[3][2] + for item in container], []), + "title": ElementSpec(None, [0,3]), + "score": ElementSpec(None, [0,4,1]), + "genre": ElementSpec(None, [0,5]), + "price": ElementSpec(None, [0,8,1,0,0], lambda price: ( + price / 1000000) or 0 + ), + "free": ElementSpec(None, [0,8,1,0,0], lambda s: s == 0), + "currency": ElementSpec(None, [0,8,1,0,1]), + "video": ElementSpec(None, [0,12,0,0,3,2]), + "videoImage": ElementSpec(None, [0,12,0,3,3,2]), + "description": ElementSpec(None, [0,13,1], unescape_text), + "descriptionHTML": ElementSpec(None, [0,13,1]), + "developer": ElementSpec(None, [0,14]), + "installs": ElementSpec(None, [0,15]) + } diff --git a/google_play_scraper/constants/request.py b/google_play_scraper/constants/request.py index 28e4d29..9cb061b 100644 --- a/google_play_scraper/constants/request.py +++ b/google_play_scraper/constants/request.py @@ -80,6 +80,25 @@ def build_body(self, app_id: str) -> bytes: return result.encode() + class _Searchresults(Format): + URL_FORMAT = "{}/store/search?q={{query}}&c=apps&hl={{lang}}&gl={{country}}".format( + PLAY_STORE_BASE_URL + ) + FALLBACK_URL_FORMAT = "{}/store/search?q={{query}}&c=apps&hl={{lang}}".format( + PLAY_STORE_BASE_URL + ) + + def build(self, query: str, lang: str, country: str) -> str: + return self.URL_FORMAT.format(query=query, lang=lang, country=country) + + def fallback_build(self, query: str, lang: str) -> str: + return self.FALLBACK_URL_FORMAT.format(query=query, lang=lang) + + def build_body(self, *args): + return None + + Detail = _Detail() Reviews = _Reviews() Permissions = _Permissions() + Searchresults = _Searchresults() diff --git a/google_play_scraper/features/search.py b/google_play_scraper/features/search.py new file mode 100644 index 0000000..0dc67ab --- /dev/null +++ b/google_play_scraper/features/search.py @@ -0,0 +1,54 @@ + +import json +from typing import Any, Dict +from urllib.parse import quote + +from google_play_scraper.constants.element import ElementSpecs +from google_play_scraper.constants.regex import Regex +from google_play_scraper.constants.request import Formats +from google_play_scraper.utils.request import get +from google_play_scraper.exceptions import NotFoundError + +def search(query: str, n_hits: int = 30, lang: str = "en", country: str = "us") -> Dict[str, Any]: + query = quote(query) + url = Formats.Searchresults.build(query=query, lang=lang, country=country) + try: + dom = get(url) + except NotFoundError: + url = Formats.Searchresults.fallback_build(query=query, lang=lang) + dom = get(url) + + matches = Regex.SCRIPT.findall(dom) + + dataset = {} + + for match in matches: + key_match = Regex.KEY.findall(match) + value_match = Regex.VALUE.findall(match) + + if key_match and value_match: + key = key_match[0] + value = json.loads(value_match[0]) + dataset[key] = value + + success = False + # different idx for different countries and languages + for idx in range(len(dataset["ds:4"][0][1])): + try: + dataset = dataset["ds:4"][0][1][idx][22][0] + success = True + except Exception: + pass + if not success: + return [] + + n_apps = min(len(dataset), n_hits) + search_results = [] + for app_idx in range(n_apps): + app = {} + for k, spec in ElementSpecs.Searchresult.items(): + content = spec.extract_content(dataset[app_idx]) + app[k] = content + search_results.append(app) + + return search_results diff --git a/tests/e2e_tests/test_search.py b/tests/e2e_tests/test_search.py new file mode 100644 index 0000000..fd217b9 --- /dev/null +++ b/tests/e2e_tests/test_search.py @@ -0,0 +1,56 @@ +from unittest import TestCase + +from google_play_scraper.features.search import search + + +class TestSearch(TestCase): + def test_e2e_scenario_1(self): + """ + Check if apps are found based on the search query and if all app properies are correct. + """ + results = search("best Pikachu game") + + self.assertGreater(len(results), 0) + + for result in results: + if result["appId"] == "com.nianticlabs.pokemongo": + break + + self.assertTrue("Pokémon GO" in result["title"]) + self.assertEqual("com.nianticlabs.pokemongo", result["appId"]) + self.assertTrue("Explore and discover Pokémon" in result["description"]) + self.assertTrue("
" in result["descriptionHTML"]) + self.assertTrue(result["installs"].endswith("000+")) + self.assertTrue(1.0 < result["score"] < 5.0) + self.assertEqual(0, result["price"]) + self.assertTrue(result["free"]) + self.assertEqual("USD", result["currency"]) + self.assertEqual("Niantic, Inc.", result["developer"]) + self.assertEqual("Adventure", result["genre"]) + self.assertEqual( + "https://play-lh.googleusercontent.com/SVQIX_fYcu5mc4Pq-D7dgxXZdRMpNTAbRKeBJygAsIXKITHEcKckyhzLsIXMQLSRZw", + result["icon"], + ) + self.assertTrue(result["screenshots"]) + for screenshot_url in result["screenshots"]: + self.assertTrue( + screenshot_url.startswith("https://play-lh.googleusercontent.com/") + ) + self.assertTrue(result["video"].startswith("https://www.youtube.com")) + self.assertTrue(result["videoImage"].endswith(".jpg")) + + def test_e2e_scenario_2(self): + """ + Test for different language and country. + """ + results = search("Bestes Pikachu Spiel", lang="de", country="de") + + self.assertGreater(len(results), 0) + + def test_e2e_scenario_3(self): + """ + Test for limited number of results. + """ + n_hits = 3 + results = search("best Pikachu game", n_hits=n_hits) + self.assertEqual(len(results), n_hits) From b0136c31f0b0dac19df2458a514165274454700c Mon Sep 17 00:00:00 2001 From: ASeidel Date: Tue, 5 Jul 2022 10:08:03 +0200 Subject: [PATCH 2/3] add search function to __init__.py --- google_play_scraper/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/google_play_scraper/__init__.py b/google_play_scraper/__init__.py index f5bdc57..064d5d1 100644 --- a/google_play_scraper/__init__.py +++ b/google_play_scraper/__init__.py @@ -2,5 +2,6 @@ from .features.app import app from .features.reviews import reviews, reviews_all from .features.permissions import permissions +from .features.search import search VERSION = __version__ = "1.1.0" From c7bd812be0df0a81c52d5597f96e1a96122e62f4 Mon Sep 17 00:00:00 2001 From: Anja Seidel <63776292+anjaseidel@users.noreply.github.com> Date: Tue, 5 Jul 2022 10:17:20 +0200 Subject: [PATCH 3/3] Update README.md --- README.md | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/README.md b/README.md index 962b4bd..f40ce6e 100644 --- a/README.md +++ b/README.md @@ -292,6 +292,104 @@ Result of `print(result)`: ] } ``` +### App Search +```python +from google_play_scraper import search + +result = search("best Pikachu game", + lang="en", # defaults to 'en' + country="us", # defaults to 'us' + n_hits=3 # defaults to 30 (= Google's maximum) +) +result +``` + +Result of `print(result)`: + +``` +[{'appId': 'com.nianticlabs.pokemongo', + 'icon': 'https://play-lh.googleusercontent.com/SVQIX_fYcu5mc4Pq-D7dgxXZdRMpNTAbRKeBJygAsIXKITHEcKckyhzLsIXMQLSRZw', + 'screenshots': ['https://play-lh.googleusercontent.com/O-OR6Mh0AoNyiaYYaa3OJ_VHGfLqWW2qNzUUZxRRodD3fqs2Pm04FatavdNbz-jsMZM', + 'https://play-lh.googleusercontent.com/HiLNXxmIpOl1jLBssHWcGqsQ58oUC5RvmS5tiX7L86mPHCG6wVEN-aX5OxTKAbDzh10', + 'https://play-lh.googleusercontent.com/Il9B11lqrHX_Kd3QzLCA6hA6O7EsT56ItiLWMf1JkwcdmRyR3CE2KW_vR9w1izanO-JM', + 'https://play-lh.googleusercontent.com/_84Pq9dJ0_iTKwx9-CkYFYoakSMKK_yfdrp1WSX-inE2XvCTr8ri2tKoISLHN_9PEvP5', + 'https://play-lh.googleusercontent.com/JjgLXR7CMiQfSbtICOa86_35f7Pf8IzJn78zWQslwJn56Qm2O7BOV7xzXXE8mz3Vhg', + 'https://play-lh.googleusercontent.com/iAYd9LdbFI7aajPU760XoNZ8b3woDQ58B0harYiUed2y7WQLU19fcj9I8yS-_K9BDQ', + 'https://play-lh.googleusercontent.com/lpw5tz7Onf_6Sx4Q3kGX1zKXcec4EWpRyr9I4w5d3TrQMoorPWVke6veB5qmqhfQZn4', + 'https://play-lh.googleusercontent.com/KgDQ-Kjb2B7_jDP-8KmQDNhAmP2lqAV_w3zArOCBL7YZnQ02Qqp4VTlgdocO-4MFk4s'], + 'title': 'Pokémon GO', + 'score': 4.283571, + 'genre': 'Adventure', + 'price': 0, + 'free': True, + 'currency': 'USD', + 'video': 'https://www.youtube.com/embed/DFXbVBFPOOs?ps=play&vq=large&rel=0&autohide=1&showinfo=0', + 'videoImage': 'https://i.ytimg.com/vi/DFXbVBFPOOs/hqdefault.jpg', + 'description': 'New! Now you can battle other Pokémon GO Trainers online! Try the GO Battle League today!\r\n\r\nJoin Trainers across the globe who are discovering Pokémon as they explore the world around them. Pokémon GO is the global gaming sensation that has been downloaded over 1 billion times and named “Best Mobile Game” by the Game Developers Choice Awards and “Best App of the Year” by TechCrunch.\r\n_______________\r\n\r\nUncover the world of Pokémon: Explore and discover Pokémon wherever you are!\r\n \r\nCatch more Pokémon to complete your Pokédex!\r\n \r\nJourney alongside your Buddy Pokémon to help make your Pokémon stronger and earn rewards!\r\n\r\nCompete in epic Gym battles and...\r\n\r\nTeam up with other Trainers to catch powerful Pokémon during Raid Battles!\r\n \r\nIt’s time to get moving—your real-life adventures await! Let’s GO!\r\n_______________\r\n\r\nNotes: \r\n- This app is free-to-play and offers in-game purchases. It is optimized for smartphones, not tablets.\r\n- Compatible with Android devices that have 2GB RAM or more and have Android Version 6.0–10.0+ installed.\r\n- Compatibility is not guaranteed for devices without GPS capabilities or devices that are connected only to Wi-Fi networks.\r\n- Application may not run on certain devices even if they have compatible OS versions installed.\r\n- It is recommended to play while connected to a network in order to obtain accurate location information.\r\n- Compatibility information may be changed at any time.\r\n- Please visit PokemonGO.com for additional compatibility information. \r\n- Information current as of October 20, 2020.', + 'descriptionHTML': 'New! Now you can battle other Pokémon GO Trainers online! Try the GO Battle League today!

Join Trainers across the globe who are discovering Pokémon as they explore the world around them. Pokémon GO is the global gaming sensation that has been downloaded over 1 billion times and named “Best Mobile Game” by the Game Developers Choice Awards and “Best App of the Year” by TechCrunch.
_______________

Uncover the world of Pokémon: Explore and discover Pokémon wherever you are!

Catch more Pokémon to complete your Pokédex!

Journey alongside your Buddy Pokémon to help make your Pokémon stronger and earn rewards!

Compete in epic Gym battles and...

Team up with other Trainers to catch powerful Pokémon during Raid Battles!

It’s time to get moving—your real-life adventures await! Let’s GO!
_______________

Notes:
- This app is free-to-play and offers in-game purchases. It is optimized for smartphones, not tablets.
- Compatible with Android devices that have 2GB RAM or more and have Android Version 6.0–10.0+ installed.
- Compatibility is not guaranteed for devices without GPS capabilities or devices that are connected only to Wi-Fi networks.
- Application may not run on certain devices even if they have compatible OS versions installed.
- It is recommended to play while connected to a network in order to obtain accurate location information.
- Compatibility information may be changed at any time.
- Please visit PokemonGO.com for additional compatibility information.
- Information current as of October 20, 2020.', + 'developer': 'Niantic, Inc.', + 'installs': '100,000,000+'}, + {'appId': 'jp.pokemon.pokemonunite', + 'icon': 'https://play-lh.googleusercontent.com/l6iBBhrah3mNhvcjZgZBwICAF5uu3KjorU4pq-eMOxYgT_L_TnpzT7a3TmmdxaMMgbUy', + 'screenshots': ['https://play-lh.googleusercontent.com/0BXdHWr_OWcqwc2egRCGa9el75tMO9VS7tj2K2oiHMulKpVZ7t7eKLYwdye7JnUhdxMj', + 'https://play-lh.googleusercontent.com/tReAAbW5OMk2tFwAWHuCCjdfUHTcx11tHPfmX8HF9ggTf4dJZ5A5AKfEoGYhg0ee9kU', + 'https://play-lh.googleusercontent.com/VVXVsn7QiICtyN7VI4IlFAhC4i5Vw-ezx3sLbywIG01HpKUlbVcDsnqM6Rc6TStHgQ', + 'https://play-lh.googleusercontent.com/qIdex-XxcS2Dl5Efq6DJF39VQuJShLoeLC0X40YiqeSV-ePG0N2CGKWbZI07sXPEDDo', + 'https://play-lh.googleusercontent.com/BQun4awXd5t-NapkXAI7-uyOl1PzWr80NWPKnSsDBrR8-FZLLBIz5KNg_pHK36EMoYYK', + 'https://play-lh.googleusercontent.com/57M-IQvvMsyRUULDZZ6cXGRaiVJMUY9ABf7R19sdmi8sS-hOzf7wp3v5JgOxrIMcag', + 'https://play-lh.googleusercontent.com/BOIBHIXkqZKDcUSvZUM88GiftsIxLoFU1qR2R0PiKRImWXOT4MG0GRdfRkIhESTlipoc', + 'https://play-lh.googleusercontent.com/F_kaX-tKz2KwQeozaB4emu8OaH422d3uSB9Ovhp3Rdycyh303Pukj-LLmsh4drid4Q2Y', + 'https://play-lh.googleusercontent.com/HuxwQsc_wqUeGgyeclWyiNYKIYbUhx4HL2evXauReksvdMwKazZ2Ze8oYysbPkTH7Do', + 'https://play-lh.googleusercontent.com/h_VR3XmUEbStoW4Kbkz48etOwc6I8AO7caEPmlG_s6QoFn_Hvy8cPGHZs8Ie8sIn4COD', + 'https://play-lh.googleusercontent.com/pXZIkNh6VGWAkL5kDDVUVxAjba1aRVootuQRfHmLRLnI3TC2AqMm5H19M8jIj2jzIQ', + 'https://play-lh.googleusercontent.com/zW64FFgL-bacNW851Z-veKZJEAFjt5G6iA_1DJjH5GGgoBrzOITYOSANSoZRvTrV91Dp', + 'https://play-lh.googleusercontent.com/LgY2r8NPH1SErkQ46Srhyzujxg3Po-ZBo7DYOUrqctIya-DeeTJRbOtC1lAtgdAE3w', + 'https://play-lh.googleusercontent.com/legf5ocJ02NksPSP__k5g7I-EXa9w34F1Xd5BBQ2p4ILvvGdkR2T-CXfqwhzLF4RJW8', + 'https://play-lh.googleusercontent.com/KRaCNowecDHdl1V7y1wkhlBf_qOiGddBNRORXOU5xfAQdjnJqK3RYD8dgCUFY29E_Uo', + 'https://play-lh.googleusercontent.com/Kx2V-5ybEv2m1K1f1v2bJHRO27WNIpb-2Gex6sMh63Fzr9T6Npwh3lDu2tG8oOnP7A', + 'https://play-lh.googleusercontent.com/_yL5mS4Iw65B0L9gfoz--xKbfijilqEA0kEVk5N3muLXBLsWly2BR-mpwJl5Ia2IoQ', + 'https://play-lh.googleusercontent.com/ULyQg55oKym85qsQMvKq0nVginG2gF0qw5g82knbjS15pMu-n_HxRYL86FyOEiRXboQ', + 'https://play-lh.googleusercontent.com/6LZs0vvZFta2dcFjKSglRx-ugeYzYYjM_ziEYv8_O14Hngr6rid2-qYuBsgri8GefQ', + 'https://play-lh.googleusercontent.com/Q5nklhiiZwY_tnUjUlvh9PkDS-H-OF7wBI_AblMUbpVVdVr1CEw1CuO791p_1bU0bkgE', + 'https://play-lh.googleusercontent.com/AVrvQmbm06_cta6VInNudHS0aqOQcZEkM-KRGU8IdN3HW3lHMEXwJsyWTivUK8juBQ', + 'https://play-lh.googleusercontent.com/MaFH8pnG9lT6m7XeaFC0r2ZsRprk9VkSTO22ornPlot9GGrimGl9iBoiy4emMtgOFg'], + 'title': 'Pokémon UNITE', + 'score': 4.5547147, + 'genre': 'Action', + 'price': 0, + 'free': True, + 'currency': 'USD', + 'video': 'https://www.youtube.com/embed/ZLBVuHDguvQ?ps=play&vq=large&rel=0&autohide=1&showinfo=0', + 'videoImage': 'https://i.ytimg.com/vi/ZLBVuHDguvQ/hqdefault.jpg', + 'description': 'Headline:\r\n\r\nPokémon UNITE:\r\nTeam up and take down the opposition in Pokémon’s first 5-on-5 strategic team battle game! \r\n\r\nJoin Trainers from around the world as they head for Aeos Island to compete in Unite Battles! In Unite Battles, Trainers face off in 5-on-5 team battles to see who can score the most points within the allotted time. Teamwork is key as you and your teammates defeat wild Pokémon, level up, evolve your own Pokémon, and work to prevent the opposing team from scoring points. Put your teamwork to the test, and take home the win! \r\n\r\nKey Features: \r\n•\tBATTLE IN STYLE: Take to the field while looking your best in Holowear! Thanks to a special technology developed using Aeos energy, Trainers can deck out their Pokémon in a variety of holographic outfits—with new styles arriving regularly! \r\n \r\n•\tUNITE MOVES: Unleash the true power of your Pokémon with Unite Moves! Leverage these all-new Pokémon moves, which are only possible while in Unite Battles, and turn the tide of even the direst situations. \r\n \r\n•\tRANK UP: Looking to prove how skilled you are? Participate in ranked matches, and earn points as you climb up the global leaderboard! \r\n \r\n•\tCOMMUNICATION IS KEY: Even the most skilled Trainers recognize how important communication is to their team’s success. Leverage signals, quick-chat messages, and—for the first time in a Pokémon title—voice chat to communicate and stay in sync with your team. \r\n \r\n•\tCROSS-PLATFORM PLAY: Challenge Trainers from around the world to Unite Battles on the Nintendo SwitchTM system or on a compatible mobile device thanks to cross-platform support. Trainers may use their Pokémon Trainer Club account or Nintendo Account on both Nintendo Switch and mobile to easily keep their progress synced between devices. \r\n\r\n\r\nCheck out the official website for more information, and follow Pokémon UNITE on Twitter for all the latest news. \r\n------------------------------------------------------------\r\nOfficial Website: http://PokemonUNITE.com/\r\nOfficial Twitter: https://twitter.com/PokemonUNITE/\r\n\r\nLegal:\r\n•\tThis is a free-to-start game; optional in-game purchases available. Data charges may apply.\r\n•\tAn internet connection is required to play the game.', + 'descriptionHTML': 'Headline:

Pokémon UNITE:
Team up and take down the opposition in Pokémon’s first 5-on-5 strategic team battle game!

Join Trainers from around the world as they head for Aeos Island to compete in Unite Battles! In Unite Battles, Trainers face off in 5-on-5 team battles to see who can score the most points within the allotted time. Teamwork is key as you and your teammates defeat wild Pokémon, level up, evolve your own Pokémon, and work to prevent the opposing team from scoring points. Put your teamwork to the test, and take home the win!

Key Features:
•\tBATTLE IN STYLE: Take to the field while looking your best in Holowear! Thanks to a special technology developed using Aeos energy, Trainers can deck out their Pokémon in a variety of holographic outfits—with new styles arriving regularly!

•\tUNITE MOVES: Unleash the true power of your Pokémon with Unite Moves! Leverage these all-new Pokémon moves, which are only possible while in Unite Battles, and turn the tide of even the direst situations.

•\tRANK UP: Looking to prove how skilled you are? Participate in ranked matches, and earn points as you climb up the global leaderboard!

•\tCOMMUNICATION IS KEY: Even the most skilled Trainers recognize how important communication is to their team’s success. Leverage signals, quick-chat messages, and—for the first time in a Pokémon title—voice chat to communicate and stay in sync with your team.

•\tCROSS-PLATFORM PLAY: Challenge Trainers from around the world to Unite Battles on the Nintendo SwitchTM system or on a compatible mobile device thanks to cross-platform support. Trainers may use their Pokémon Trainer Club account or Nintendo Account on both Nintendo Switch and mobile to easily keep their progress synced between devices.


Check out the official website for more information, and follow Pokémon UNITE on Twitter for all the latest news.
------------------------------------------------------------
Official Website: http://PokemonUNITE.com/
Official Twitter: https://twitter.com/PokemonUNITE/

Legal:
•\tThis is a free-to-start game; optional in-game purchases available. Data charges may apply.
•\tAn internet connection is required to play the game.', + 'developer': 'The Pokemon Company', + 'installs': '10,000,000+'}, + {'appId': 'com.dena.a12026418', + 'icon': 'https://play-lh.googleusercontent.com/h4dRm7zBF605F3rNY-KdMlTIGatw4csK1HSUEBit7-PtqPmYuXxzP-Wooy8hRI8YTA', + 'screenshots': ['https://play-lh.googleusercontent.com/82gD-bWWy0B9SHVaPqTnvCNo_SBk0ssGyI2ZrbgOvNQ6FK6guz20aKPKhLcCCUv_SP8', + 'https://play-lh.googleusercontent.com/ysrmlowWJCm5nF-i-nAezyDr_jHlfe0tCOLOSzsIVyGTMQnDxoO5h30uCk5DgYDY6A', + 'https://play-lh.googleusercontent.com/Xj85MdUloyyfLNjud73TBcJL3j9r97O3lEWjwnTyk4hF00gqQb58x64Bx2HoJlmBW5Oi', + 'https://play-lh.googleusercontent.com/J7tY8gJtd5pyiGe-To-Amfbc7aiWqzLqm3Msg0UnLSp0DCtX9mwxS4xAisliQw2OfA0', + 'https://play-lh.googleusercontent.com/u_od4LQquoRSoZF5hA9dAH0dB41illZ6ouYxIl49bH8yHoQulcUslwxy-b9nWxCiOJtM', + 'https://play-lh.googleusercontent.com/wIRwnAKtqBD6GL2Lxnz8K-1jZlZ9qbBUXD5tMToxF-sUyWNBxUD5m_rR8bwXR98oGls', + 'https://play-lh.googleusercontent.com/I-wGFjAD7ut2YGNze8xDVaiR89HCAxKPEOgfYcGpR3Ka5vKjQPH5M4BXti2xWJqEpA', + 'https://play-lh.googleusercontent.com/9cap7BX24s5T_RNPDIXN6rykD0J4LMOhaC1JCPjcRGhkcTO32JNX2GD88Hw5usFjbgo', + 'https://play-lh.googleusercontent.com/j3024cER2J5EIyNIWybWFDqfxuAkvJqrRxTKxAx55eWilRoY7aOF2JvK_yFNMm1CXAkU', + 'https://play-lh.googleusercontent.com/6zEEW5lScq4uIw-7B4w19dDVglcTBRHRG0pUdRHjLpULuUw9hKmLnu8mDonkmlYqTA'], + 'title': 'Pokémon Masters EX', + 'score': 4.3176017, + 'genre': 'Role Playing', + 'price': 0, + 'free': True, + 'currency': 'USD', + 'video': 'https://www.youtube.com/embed/tPN87sf7hyU?ps=play&vq=large&rel=0&autohide=1&showinfo=0', + 'videoImage': 'https://i.ytimg.com/vi/tPN87sf7hyU/hqdefault.jpg', + 'description': 'DYNAMAX! \r\nThe ability to Dynamax comes to Pokémon Masters EX! Now your Pokémon can drastically multiply in size once per battle to unleash a powerful max move on your opponents!\r\n\r\nTRAINERS DON SPECIAL OUTFITS!\r\nEnjoy special and seasonal Trainer outfits—exclusive to Pokémon Masters EX!\r\n\r\nHATCH EGGS & TEAM UP!\r\nHatch Eggs to get new Pokémon! Add hatched Pokémon to your team, and battle your way to the top!\r\n\r\nBUILD THE ULTIMATE TEAM FOR 3-ON-3 BATTLE!\r\nAssemble Trainers and Pokémon to take on battles! Create a team all your own, and aim for victory!\r\n\r\nTRAINERS FROM THE PAST COME TOGETHER!\r\nChampions, Elite Four members, and Gym Leaders from the past have come together! Team up with Trainers and their Pokémon, and go on adventures!\r\n\r\nNEW STORIES WITH YOUR FAVORITE CHARACTERS\r\nIn Pokémon Masters EX, experience an original story that crosses generations—along with familiar Trainers!\r\n\r\n\r\n・We recommend a device with at least 2GB of RAM.\r\n・Android OS 7.0 or higher is recommended.\r\n・Android OS 5.0 or above\r\nNote: \r\n・We do not guarantee functionality on all devices listed above.\r\n・There may be cases where the app does not function properly due to your device’s capabilities, specifications, or particular conditions for using apps.\r\n・It may take time to become compatible with the latest OS.', + 'descriptionHTML': 'DYNAMAX!
The ability to Dynamax comes to Pokémon Masters EX! Now your Pokémon can drastically multiply in size once per battle to unleash a powerful max move on your opponents!

TRAINERS DON SPECIAL OUTFITS!
Enjoy special and seasonal Trainer outfits—exclusive to Pokémon Masters EX!

HATCH EGGS & TEAM UP!
Hatch Eggs to get new Pokémon! Add hatched Pokémon to your team, and battle your way to the top!

BUILD THE ULTIMATE TEAM FOR 3-ON-3 BATTLE!
Assemble Trainers and Pokémon to take on battles! Create a team all your own, and aim for victory!

TRAINERS FROM THE PAST COME TOGETHER!
Champions, Elite Four members, and Gym Leaders from the past have come together! Team up with Trainers and their Pokémon, and go on adventures!

NEW STORIES WITH YOUR FAVORITE CHARACTERS
In Pokémon Masters EX, experience an original story that crosses generations—along with familiar Trainers!


・We recommend a device with at least 2GB of RAM.
・Android OS 7.0 or higher is recommended.
・Android OS 5.0 or above
Note:
・We do not guarantee functionality on all devices listed above.
・There may be cases where the app does not function properly due to your device’s capabilities, specifications, or particular conditions for using apps.
・It may take time to become compatible with the latest OS.', + 'developer': 'DeNA Co., Ltd.', + 'installs': '10,000,000+'}] +``` ## Changes Change logs are here : [CHANGELOG.md](CHANGELOG.md)