apksearch 1.0.0__tar.gz
Sign up to get free protection for your applications and to get access to all the features.
- apksearch-1.0.0/LICENSE +21 -0
- apksearch-1.0.0/PKG-INFO +150 -0
- apksearch-1.0.0/README.md +98 -0
- apksearch-1.0.0/apksearch/__init__.py +4 -0
- apksearch-1.0.0/apksearch/__main__.py +4 -0
- apksearch-1.0.0/apksearch/cli.py +79 -0
- apksearch-1.0.0/apksearch/sites/__init__.py +0 -0
- apksearch-1.0.0/apksearch/sites/apkmirror.py +79 -0
- apksearch-1.0.0/apksearch/sites/apkpure.py +108 -0
- apksearch-1.0.0/apksearch.egg-info/PKG-INFO +150 -0
- apksearch-1.0.0/apksearch.egg-info/SOURCES.txt +17 -0
- apksearch-1.0.0/apksearch.egg-info/dependency_links.txt +1 -0
- apksearch-1.0.0/apksearch.egg-info/entry_points.txt +2 -0
- apksearch-1.0.0/apksearch.egg-info/requires.txt +7 -0
- apksearch-1.0.0/apksearch.egg-info/top_level.txt +1 -0
- apksearch-1.0.0/pyproject.toml +46 -0
- apksearch-1.0.0/setup.cfg +4 -0
- apksearch-1.0.0/tests/test_apkmirror.py +45 -0
- apksearch-1.0.0/tests/test_apkpure.py +38 -0
apksearch-1.0.0/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2024 Abhi
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
apksearch-1.0.0/PKG-INFO
ADDED
@@ -0,0 +1,150 @@
|
|
1
|
+
Metadata-Version: 2.1
|
2
|
+
Name: apksearch
|
3
|
+
Version: 1.0.0
|
4
|
+
Summary: Search for apks on varius websites
|
5
|
+
Author-email: Abhi <allinoneallinone00@gmail.com>
|
6
|
+
License: MIT License
|
7
|
+
|
8
|
+
Copyright (c) 2024 Abhi
|
9
|
+
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
12
|
+
in the Software without restriction, including without limitation the rights
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
15
|
+
furnished to do so, subject to the following conditions:
|
16
|
+
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
18
|
+
copies or substantial portions of the Software.
|
19
|
+
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
26
|
+
SOFTWARE.
|
27
|
+
|
28
|
+
Project-URL: homepage, https://github.com/AbhiTheModder/apksearch.git
|
29
|
+
Project-URL: source, https://github.com/AbhiTheModder/apksearch.git
|
30
|
+
Project-URL: issues, https://github.com/AbhiTheModder/apksearch.git/issues
|
31
|
+
Classifier: Development Status :: 4 - Beta
|
32
|
+
Classifier: Natural Language :: English
|
33
|
+
Classifier: Intended Audience :: Developers
|
34
|
+
Classifier: License :: OSI Approved :: MIT License
|
35
|
+
Classifier: Programming Language :: Python :: 3
|
36
|
+
Classifier: Programming Language :: Python :: 3.10
|
37
|
+
Classifier: Programming Language :: Python :: 3.11
|
38
|
+
Classifier: Programming Language :: Python :: 3.12
|
39
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
40
|
+
Classifier: Topic :: Text Processing :: General
|
41
|
+
Classifier: Topic :: Utilities
|
42
|
+
Classifier: Operating System :: OS Independent
|
43
|
+
Requires-Python: >=3.10
|
44
|
+
Description-Content-Type: text/markdown
|
45
|
+
License-File: LICENSE
|
46
|
+
Requires-Dist: beautifulsoup4>=4.12.3
|
47
|
+
Requires-Dist: requests>=2.32.3
|
48
|
+
Provides-Extra: dev
|
49
|
+
Requires-Dist: pytest>=7.4.3; extra == "dev"
|
50
|
+
Requires-Dist: black>=23.12.1; extra == "dev"
|
51
|
+
Requires-Dist: flake8>=6.1.0; extra == "dev"
|
52
|
+
|
53
|
+
# apksearch
|
54
|
+
|
55
|
+
`apksearch` is a Python library designed to search for APK files on different APK websites, such as APKPure and APKMirror. It allows users to find APKs, check for available versions, and retrieve download links.
|
56
|
+
|
57
|
+
**The Inspiration:**
|
58
|
+
There were countless occasions when I needed a specific APK for a package name, only to find it unavailable on popular platforms. This led to the tedious task of manually visiting multiple websites and searching one by one.
|
59
|
+
|
60
|
+
# Features
|
61
|
+
|
62
|
+
- **Search APKs:** The library provides methods to search for APKs using package names.
|
63
|
+
- **Retrieve APK Versions and Download Links:** It can fetch available versions and their download links for a given APK from APKPure and APKMirror.
|
64
|
+
- **Command-Line Interface:** A CLI is available for users to search for APKs directly from the command line.
|
65
|
+
|
66
|
+
## Installation
|
67
|
+
|
68
|
+
To install the `apksearch` library, use the following command:
|
69
|
+
|
70
|
+
```sh
|
71
|
+
pip install git+https://github.com/AbhiTheModder/apksearch.git
|
72
|
+
```
|
73
|
+
|
74
|
+
OR, through pip:
|
75
|
+
|
76
|
+
```sh
|
77
|
+
pip install apksearch
|
78
|
+
```
|
79
|
+
|
80
|
+
## Usage
|
81
|
+
|
82
|
+
### Command-Line Interface
|
83
|
+
|
84
|
+
To use the CLI, run the following command:
|
85
|
+
|
86
|
+
```sh
|
87
|
+
apksearch <package_name> [--version <version>]
|
88
|
+
```
|
89
|
+
|
90
|
+
Example:
|
91
|
+
|
92
|
+
```sh
|
93
|
+
apksearch com.roblox.client --version 2.652.765
|
94
|
+
```
|
95
|
+
|
96
|
+
### Library Usage
|
97
|
+
|
98
|
+
You can also use the library programmatically in your Python code:
|
99
|
+
|
100
|
+
```python
|
101
|
+
from apksearch import APKPure, APKMirror
|
102
|
+
|
103
|
+
# Searching on APKPure
|
104
|
+
apkpure = APKPure("com.roblox.client")
|
105
|
+
result = apkpure.search_apk()
|
106
|
+
if result:
|
107
|
+
title, link = result
|
108
|
+
print(f"Found on APKPure: {title} - {link}")
|
109
|
+
|
110
|
+
# Searching on APKMirror
|
111
|
+
apkmirror = APKMirror("com.roblox.client")
|
112
|
+
result = apkmirror.search_apk()
|
113
|
+
if result:
|
114
|
+
title, link = result
|
115
|
+
print(f"Found on APKMirror: {title} - {link}")
|
116
|
+
```
|
117
|
+
|
118
|
+
### Classes and Methods
|
119
|
+
|
120
|
+
#### `APKPure`
|
121
|
+
|
122
|
+
- **`__init__(self, pkg_name: str)`**: Initializes with the package name.
|
123
|
+
- **`search_apk(self) -> None | tuple[str, str]`**: Searches for the APK on APKPure and returns the title and link if found.
|
124
|
+
- **`find_versions(self, apk_link: str) -> list[tuple[str, str]]`**: Finds and returns a list of versions and their download links for the given APK link.
|
125
|
+
|
126
|
+
#### `APKMirror`
|
127
|
+
|
128
|
+
- **`__init__(self, pkg_name: str)`**: Initializes with the package name.
|
129
|
+
- **`search_apk(self) -> None | tuple[str, str]`**: Searches for the APK on APKMirror and returns the title and link if found.
|
130
|
+
- **`find_version(self, apk_link: str, version: str) -> str`**: Finds and returns the download link for the given APK link and version.
|
131
|
+
|
132
|
+
### Testing
|
133
|
+
|
134
|
+
The project includes tests for the `sites` classes. To run the tests, use the following command:
|
135
|
+
|
136
|
+
```sh
|
137
|
+
pytest
|
138
|
+
```
|
139
|
+
|
140
|
+
## TODO
|
141
|
+
|
142
|
+
- [ ] Add more websites to search for APKs.
|
143
|
+
|
144
|
+
## License
|
145
|
+
|
146
|
+
This project is licensed under the MIT License. See the [LICENSE](https://github.com/AbhiTheModder/apksearch/blob/main/LICENSE) file for more details.
|
147
|
+
|
148
|
+
## Contributing
|
149
|
+
|
150
|
+
Contributions are welcome! Please open an issue or submit a pull request on [GitHub](https://github.com/AbhiTheModder/apksearch).
|
@@ -0,0 +1,98 @@
|
|
1
|
+
# apksearch
|
2
|
+
|
3
|
+
`apksearch` is a Python library designed to search for APK files on different APK websites, such as APKPure and APKMirror. It allows users to find APKs, check for available versions, and retrieve download links.
|
4
|
+
|
5
|
+
**The Inspiration:**
|
6
|
+
There were countless occasions when I needed a specific APK for a package name, only to find it unavailable on popular platforms. This led to the tedious task of manually visiting multiple websites and searching one by one.
|
7
|
+
|
8
|
+
# Features
|
9
|
+
|
10
|
+
- **Search APKs:** The library provides methods to search for APKs using package names.
|
11
|
+
- **Retrieve APK Versions and Download Links:** It can fetch available versions and their download links for a given APK from APKPure and APKMirror.
|
12
|
+
- **Command-Line Interface:** A CLI is available for users to search for APKs directly from the command line.
|
13
|
+
|
14
|
+
## Installation
|
15
|
+
|
16
|
+
To install the `apksearch` library, use the following command:
|
17
|
+
|
18
|
+
```sh
|
19
|
+
pip install git+https://github.com/AbhiTheModder/apksearch.git
|
20
|
+
```
|
21
|
+
|
22
|
+
OR, through pip:
|
23
|
+
|
24
|
+
```sh
|
25
|
+
pip install apksearch
|
26
|
+
```
|
27
|
+
|
28
|
+
## Usage
|
29
|
+
|
30
|
+
### Command-Line Interface
|
31
|
+
|
32
|
+
To use the CLI, run the following command:
|
33
|
+
|
34
|
+
```sh
|
35
|
+
apksearch <package_name> [--version <version>]
|
36
|
+
```
|
37
|
+
|
38
|
+
Example:
|
39
|
+
|
40
|
+
```sh
|
41
|
+
apksearch com.roblox.client --version 2.652.765
|
42
|
+
```
|
43
|
+
|
44
|
+
### Library Usage
|
45
|
+
|
46
|
+
You can also use the library programmatically in your Python code:
|
47
|
+
|
48
|
+
```python
|
49
|
+
from apksearch import APKPure, APKMirror
|
50
|
+
|
51
|
+
# Searching on APKPure
|
52
|
+
apkpure = APKPure("com.roblox.client")
|
53
|
+
result = apkpure.search_apk()
|
54
|
+
if result:
|
55
|
+
title, link = result
|
56
|
+
print(f"Found on APKPure: {title} - {link}")
|
57
|
+
|
58
|
+
# Searching on APKMirror
|
59
|
+
apkmirror = APKMirror("com.roblox.client")
|
60
|
+
result = apkmirror.search_apk()
|
61
|
+
if result:
|
62
|
+
title, link = result
|
63
|
+
print(f"Found on APKMirror: {title} - {link}")
|
64
|
+
```
|
65
|
+
|
66
|
+
### Classes and Methods
|
67
|
+
|
68
|
+
#### `APKPure`
|
69
|
+
|
70
|
+
- **`__init__(self, pkg_name: str)`**: Initializes with the package name.
|
71
|
+
- **`search_apk(self) -> None | tuple[str, str]`**: Searches for the APK on APKPure and returns the title and link if found.
|
72
|
+
- **`find_versions(self, apk_link: str) -> list[tuple[str, str]]`**: Finds and returns a list of versions and their download links for the given APK link.
|
73
|
+
|
74
|
+
#### `APKMirror`
|
75
|
+
|
76
|
+
- **`__init__(self, pkg_name: str)`**: Initializes with the package name.
|
77
|
+
- **`search_apk(self) -> None | tuple[str, str]`**: Searches for the APK on APKMirror and returns the title and link if found.
|
78
|
+
- **`find_version(self, apk_link: str, version: str) -> str`**: Finds and returns the download link for the given APK link and version.
|
79
|
+
|
80
|
+
### Testing
|
81
|
+
|
82
|
+
The project includes tests for the `sites` classes. To run the tests, use the following command:
|
83
|
+
|
84
|
+
```sh
|
85
|
+
pytest
|
86
|
+
```
|
87
|
+
|
88
|
+
## TODO
|
89
|
+
|
90
|
+
- [ ] Add more websites to search for APKs.
|
91
|
+
|
92
|
+
## License
|
93
|
+
|
94
|
+
This project is licensed under the MIT License. See the [LICENSE](https://github.com/AbhiTheModder/apksearch/blob/main/LICENSE) file for more details.
|
95
|
+
|
96
|
+
## Contributing
|
97
|
+
|
98
|
+
Contributions are welcome! Please open an issue or submit a pull request on [GitHub](https://github.com/AbhiTheModder/apksearch).
|
@@ -0,0 +1,79 @@
|
|
1
|
+
import argparse
|
2
|
+
|
3
|
+
from apksearch import APKPure, APKMirror
|
4
|
+
from requests.exceptions import ConnectionError, ConnectTimeout
|
5
|
+
|
6
|
+
# Color codes
|
7
|
+
BOLD = "\033[1m"
|
8
|
+
RED = "\033[91m"
|
9
|
+
GREEN = "\033[92m"
|
10
|
+
YELLOW = "\033[93m"
|
11
|
+
NC = "\033[0m"
|
12
|
+
|
13
|
+
|
14
|
+
def search_apkpure(pkg_name: str, version: str | None) -> None:
|
15
|
+
apkpure = APKPure(pkg_name)
|
16
|
+
try:
|
17
|
+
result_apkpure: tuple[str, str] | None = apkpure.search_apk()
|
18
|
+
except (ConnectionError, ConnectTimeout):
|
19
|
+
result_apkpure = None
|
20
|
+
print(f"{RED}Failed to resolve 'apkpure.net'!{NC}")
|
21
|
+
if result_apkpure:
|
22
|
+
title, apk_link = result_apkpure
|
23
|
+
print(f"{BOLD}APKPure:{NC} Found {GREEN}{title}{NC}") if title else None
|
24
|
+
print(f" ╰─> {BOLD}Link: {YELLOW}{apk_link}{NC}") if not version else None
|
25
|
+
versions: list[tuple[str, str]] = apkpure.find_versions(apk_link)
|
26
|
+
if version:
|
27
|
+
for version_tuple in versions:
|
28
|
+
if version_tuple[0] == version:
|
29
|
+
print(
|
30
|
+
f" ╰─> {BOLD}Version: {GREEN}{version}{NC} - {YELLOW}{version_tuple[1]}{NC}"
|
31
|
+
)
|
32
|
+
break
|
33
|
+
else:
|
34
|
+
print(f"{BOLD}APKPure:{NC} Version {RED}{version}{NC} not found!")
|
35
|
+
else:
|
36
|
+
print(f"{BOLD}APKPure:{NC} No Results!")
|
37
|
+
|
38
|
+
|
39
|
+
def search_apkmirror(pkg_name: str, version: str | None) -> None:
|
40
|
+
apkmirror = APKMirror(pkg_name)
|
41
|
+
try:
|
42
|
+
result_apkpure: tuple[str, str] | None = apkmirror.search_apk()
|
43
|
+
except (ConnectionError, ConnectTimeout):
|
44
|
+
result_apkpure = None
|
45
|
+
print(f"{RED}Failed to resolve 'apkmirror.com'!{NC}")
|
46
|
+
if result_apkpure:
|
47
|
+
title, apk_link = result_apkpure
|
48
|
+
print(f"{BOLD}APKMirror:{NC} Found {GREEN}{title}{NC}") if title else None
|
49
|
+
print(f" ╰─> {BOLD}Link: {YELLOW}{apk_link}{NC}") if not version else None
|
50
|
+
if version:
|
51
|
+
download_link = apkmirror.find_version(apk_link, version)
|
52
|
+
if download_link:
|
53
|
+
print(
|
54
|
+
f" ╰─> {BOLD}Version: {GREEN}{version}{NC} - {YELLOW}{download_link}{NC}"
|
55
|
+
)
|
56
|
+
else:
|
57
|
+
print(f"{BOLD}APKMirror:{NC} Version {RED}{version}{NC} not found!")
|
58
|
+
else:
|
59
|
+
print(f"{BOLD}APKMirror:{NC} No Results!")
|
60
|
+
|
61
|
+
|
62
|
+
def main():
|
63
|
+
parser = argparse.ArgumentParser(
|
64
|
+
prog="APKSearch", description="Search for APKs on various websites"
|
65
|
+
)
|
66
|
+
parser.add_argument("pkg_name", help="The package name of the APK")
|
67
|
+
parser.add_argument("--version", help="The version of the APK", required=False)
|
68
|
+
args = parser.parse_args()
|
69
|
+
|
70
|
+
pkg_name = args.pkg_name
|
71
|
+
version = args.version
|
72
|
+
print(f"{BOLD}Searching for {YELLOW}{pkg_name}{NC}...")
|
73
|
+
# Initiate search on apkpure
|
74
|
+
search_apkpure(pkg_name, version)
|
75
|
+
# Initiate search on apkmirror
|
76
|
+
search_apkmirror(pkg_name, version)
|
77
|
+
|
78
|
+
if __name__ == "__main__":
|
79
|
+
main()
|
File without changes
|
@@ -0,0 +1,79 @@
|
|
1
|
+
import requests
|
2
|
+
|
3
|
+
|
4
|
+
class APKMirror:
|
5
|
+
"""
|
6
|
+
This class provides methods to search for an APK on APKMirror based on package name,
|
7
|
+
and to find available versions and their download links for a given APK link.
|
8
|
+
|
9
|
+
Parameters:
|
10
|
+
pkg_name (str): The package name of the APK to search for.
|
11
|
+
|
12
|
+
Attributes:
|
13
|
+
pkg_name (str): The package name of the APK to search for.
|
14
|
+
base_url (str): The base URL of the APKMirror website.
|
15
|
+
search_url (str): The URL used to search for APKs on APKMirror.
|
16
|
+
headers (dict): The headers used for making HTTP requests.
|
17
|
+
session (requests.Session): The session object used for making HTTP requests.
|
18
|
+
|
19
|
+
Methods:
|
20
|
+
search_apk() -> None | tuple[str, str]:
|
21
|
+
Searches for the APK on APKMirror and returns the title and link if found.
|
22
|
+
|
23
|
+
find_versions(apk_link: str) -> list[tuple[str, str]]:
|
24
|
+
Finds and returns a list of versions and their download links for the given APK link.
|
25
|
+
"""
|
26
|
+
|
27
|
+
def __init__(self, pkg_name: str):
|
28
|
+
self.pkg_name = pkg_name
|
29
|
+
self.base_url = "https://www.apkmirror.com"
|
30
|
+
self.api_url = self.base_url + "/wp-json/apkm/v1"
|
31
|
+
# https://github.com/rumboalla/apkupdater/blob/3.x/app/src/main/kotlin/com/apkupdater/service/ApkMirrorService.kt
|
32
|
+
self.headers = {
|
33
|
+
"User-Agent": "APKUpdater-v3.0.3",
|
34
|
+
"Authorization": "Basic YXBpLWFwa3VwZGF0ZXI6cm01cmNmcnVVakt5MDRzTXB5TVBKWFc4",
|
35
|
+
"Content-Type": "application/json",
|
36
|
+
}
|
37
|
+
self.session = requests.Session()
|
38
|
+
|
39
|
+
def search_apk(self) -> None | tuple[str, str]:
|
40
|
+
"""
|
41
|
+
Searches for the APK on APKMirror and returns the title and link if found.
|
42
|
+
|
43
|
+
Returns:
|
44
|
+
None: If no matching APK is found.
|
45
|
+
tuple[str, str]: A tuple containing the title and link of the matching APK if found.
|
46
|
+
"""
|
47
|
+
pkg_name = self.pkg_name
|
48
|
+
url = self.api_url + "/app_exists"
|
49
|
+
json = {"pnames": pkg_name}
|
50
|
+
response: requests.Response = self.session.post(
|
51
|
+
url, json=json, headers=self.headers
|
52
|
+
)
|
53
|
+
result = response.json()["data"][0]
|
54
|
+
if result and result["exists"]:
|
55
|
+
pname = result["pname"]
|
56
|
+
if pname == pkg_name:
|
57
|
+
title = result["app"]["name"]
|
58
|
+
apk_link = self.base_url + result["app"]["link"]
|
59
|
+
return title, apk_link
|
60
|
+
return None
|
61
|
+
|
62
|
+
def find_version(self, apk_link: str, version: str) -> str:
|
63
|
+
"""
|
64
|
+
Finds and returns the download link for the given APK link and version.
|
65
|
+
|
66
|
+
Parameters:
|
67
|
+
apk_link (str): The link to the APK on the APKMirror website.
|
68
|
+
version (str): The version number of the APK to find.
|
69
|
+
|
70
|
+
Returns:
|
71
|
+
str: The download link for the specified version of the APK.
|
72
|
+
"""
|
73
|
+
name = apk_link.split("/")[-2]
|
74
|
+
version = version.replace(".", "-")
|
75
|
+
url = apk_link + name + "-" + version + "-release"
|
76
|
+
response = self.session.get(url, headers=self.headers)
|
77
|
+
if response.status_code == 404:
|
78
|
+
return None
|
79
|
+
return url
|
@@ -0,0 +1,108 @@
|
|
1
|
+
import re
|
2
|
+
from bs4 import BeautifulSoup
|
3
|
+
import requests
|
4
|
+
|
5
|
+
|
6
|
+
class APKPure:
|
7
|
+
"""
|
8
|
+
This class provides methods to search for an APK on APKPure based on package name,
|
9
|
+
and to find available versions and their download links for a given APK link.
|
10
|
+
|
11
|
+
Parameters:
|
12
|
+
pkg_name (str): The package name of the APK to search for.
|
13
|
+
|
14
|
+
Attributes:
|
15
|
+
pkg_name (str): The package name of the APK to search for.
|
16
|
+
base_url (str): The base URL of the APKPure website.
|
17
|
+
search_url (str): The URL used to search for APKs on APKPure.
|
18
|
+
headers (dict): The headers used for making HTTP requests.
|
19
|
+
session (requests.Session): The session object used for making HTTP requests.
|
20
|
+
|
21
|
+
Methods:
|
22
|
+
search_apk() -> None | tuple[str, str]:
|
23
|
+
Searches for the APK on APKPure and returns the title and link if found.
|
24
|
+
|
25
|
+
find_versions(apk_link: str) -> list[tuple[str, str]]:
|
26
|
+
Finds and returns a list of versions and their download links for the given APK link.
|
27
|
+
"""
|
28
|
+
|
29
|
+
def __init__(self, pkg_name: str):
|
30
|
+
self.pkg_name = pkg_name
|
31
|
+
self.base_url = "https://apkpure.net"
|
32
|
+
self.search_url = self.base_url + "/search?q="
|
33
|
+
self.headers = {
|
34
|
+
"accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
|
35
|
+
"accept-language": "en-US,en;q=0.9,en-IN;q=0.8",
|
36
|
+
"cache-control": "no-cache",
|
37
|
+
"dnt": "1",
|
38
|
+
"pragma": "no-cache",
|
39
|
+
"priority": "u=0, i",
|
40
|
+
"referer": "https://apkpure.net/",
|
41
|
+
"sec-ch-ua": '"Microsoft Edge";v="131", "Chromium";v="131", "Not_A Brand";v="24"',
|
42
|
+
"sec-ch-ua-mobile": "?0",
|
43
|
+
"sec-ch-ua-platform": '"Windows"',
|
44
|
+
"sec-fetch-dest": "document",
|
45
|
+
"sec-fetch-mode": "navigate",
|
46
|
+
"sec-fetch-site": "same-origin",
|
47
|
+
"sec-fetch-user": "?1",
|
48
|
+
"upgrade-insecure-requests": "1",
|
49
|
+
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36 Edg/131.0.0.0",
|
50
|
+
}
|
51
|
+
self.session = requests.Session()
|
52
|
+
|
53
|
+
def search_apk(self) -> None | tuple[str, str]:
|
54
|
+
"""
|
55
|
+
Searches for the APK on APKPure and returns the title and link if found.
|
56
|
+
|
57
|
+
Returns:
|
58
|
+
None: If no matching APK is found.
|
59
|
+
tuple[str, str]: A tuple containing the title and link of the matching APK if found.
|
60
|
+
"""
|
61
|
+
pkg_name = self.pkg_name
|
62
|
+
url = self.search_url + pkg_name
|
63
|
+
response: requests.Response = self.session.get(url, headers=self.headers)
|
64
|
+
soup = BeautifulSoup(response.text, "html.parser")
|
65
|
+
search_results = soup.find("div", {"class": "apk-list"})
|
66
|
+
if search_results:
|
67
|
+
apk_items = search_results.find_all("a", {"class": "apk-item"})
|
68
|
+
if apk_items:
|
69
|
+
for apk_item in apk_items:
|
70
|
+
apk_link = self.base_url + apk_item["href"]
|
71
|
+
apk_title = apk_item["title"]
|
72
|
+
apk_package_name = apk_item["data-dt-pkg"]
|
73
|
+
if apk_package_name == pkg_name:
|
74
|
+
return apk_title, apk_link
|
75
|
+
return None
|
76
|
+
|
77
|
+
def find_versions(self, apk_link: str) -> list[tuple[str, str]]:
|
78
|
+
"""
|
79
|
+
Finds and returns a list of versions and their download links for the given APK link.
|
80
|
+
|
81
|
+
Parameters:
|
82
|
+
apk_link (str): The link to the APK on the APKPure website.
|
83
|
+
|
84
|
+
Returns:
|
85
|
+
list[tuple[str, str]]: A list of tuples, where each tuple contains the version number
|
86
|
+
and its corresponding download link. If no versions are found, an empty list is returned.
|
87
|
+
"""
|
88
|
+
url = apk_link + "/versions"
|
89
|
+
response: requests.Response = self.session.get(url, headers=self.headers)
|
90
|
+
soup = BeautifulSoup(response.text, "html.parser")
|
91
|
+
versions_list = soup.find("ul", {"class": "version-list"})
|
92
|
+
versions_info = []
|
93
|
+
|
94
|
+
if versions_list:
|
95
|
+
versions = versions_list.find_all(
|
96
|
+
"li", {"class": re.compile("^version dt-version-item.*")}
|
97
|
+
)
|
98
|
+
for version in versions:
|
99
|
+
version_icon = version.find("a", {"class": "dt-version-icon"})
|
100
|
+
version_info = version.find("div", {"class": "version-info"})
|
101
|
+
if version_icon and version_info:
|
102
|
+
version_number = version_info.find(
|
103
|
+
"span", {"class": "name one-line"}
|
104
|
+
).text
|
105
|
+
download_url = self.base_url + version_icon["href"]
|
106
|
+
versions_info.append((version_number, download_url))
|
107
|
+
|
108
|
+
return versions_info
|
@@ -0,0 +1,150 @@
|
|
1
|
+
Metadata-Version: 2.1
|
2
|
+
Name: apksearch
|
3
|
+
Version: 1.0.0
|
4
|
+
Summary: Search for apks on varius websites
|
5
|
+
Author-email: Abhi <allinoneallinone00@gmail.com>
|
6
|
+
License: MIT License
|
7
|
+
|
8
|
+
Copyright (c) 2024 Abhi
|
9
|
+
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
12
|
+
in the Software without restriction, including without limitation the rights
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
15
|
+
furnished to do so, subject to the following conditions:
|
16
|
+
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
18
|
+
copies or substantial portions of the Software.
|
19
|
+
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
26
|
+
SOFTWARE.
|
27
|
+
|
28
|
+
Project-URL: homepage, https://github.com/AbhiTheModder/apksearch.git
|
29
|
+
Project-URL: source, https://github.com/AbhiTheModder/apksearch.git
|
30
|
+
Project-URL: issues, https://github.com/AbhiTheModder/apksearch.git/issues
|
31
|
+
Classifier: Development Status :: 4 - Beta
|
32
|
+
Classifier: Natural Language :: English
|
33
|
+
Classifier: Intended Audience :: Developers
|
34
|
+
Classifier: License :: OSI Approved :: MIT License
|
35
|
+
Classifier: Programming Language :: Python :: 3
|
36
|
+
Classifier: Programming Language :: Python :: 3.10
|
37
|
+
Classifier: Programming Language :: Python :: 3.11
|
38
|
+
Classifier: Programming Language :: Python :: 3.12
|
39
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
40
|
+
Classifier: Topic :: Text Processing :: General
|
41
|
+
Classifier: Topic :: Utilities
|
42
|
+
Classifier: Operating System :: OS Independent
|
43
|
+
Requires-Python: >=3.10
|
44
|
+
Description-Content-Type: text/markdown
|
45
|
+
License-File: LICENSE
|
46
|
+
Requires-Dist: beautifulsoup4>=4.12.3
|
47
|
+
Requires-Dist: requests>=2.32.3
|
48
|
+
Provides-Extra: dev
|
49
|
+
Requires-Dist: pytest>=7.4.3; extra == "dev"
|
50
|
+
Requires-Dist: black>=23.12.1; extra == "dev"
|
51
|
+
Requires-Dist: flake8>=6.1.0; extra == "dev"
|
52
|
+
|
53
|
+
# apksearch
|
54
|
+
|
55
|
+
`apksearch` is a Python library designed to search for APK files on different APK websites, such as APKPure and APKMirror. It allows users to find APKs, check for available versions, and retrieve download links.
|
56
|
+
|
57
|
+
**The Inspiration:**
|
58
|
+
There were countless occasions when I needed a specific APK for a package name, only to find it unavailable on popular platforms. This led to the tedious task of manually visiting multiple websites and searching one by one.
|
59
|
+
|
60
|
+
# Features
|
61
|
+
|
62
|
+
- **Search APKs:** The library provides methods to search for APKs using package names.
|
63
|
+
- **Retrieve APK Versions and Download Links:** It can fetch available versions and their download links for a given APK from APKPure and APKMirror.
|
64
|
+
- **Command-Line Interface:** A CLI is available for users to search for APKs directly from the command line.
|
65
|
+
|
66
|
+
## Installation
|
67
|
+
|
68
|
+
To install the `apksearch` library, use the following command:
|
69
|
+
|
70
|
+
```sh
|
71
|
+
pip install git+https://github.com/AbhiTheModder/apksearch.git
|
72
|
+
```
|
73
|
+
|
74
|
+
OR, through pip:
|
75
|
+
|
76
|
+
```sh
|
77
|
+
pip install apksearch
|
78
|
+
```
|
79
|
+
|
80
|
+
## Usage
|
81
|
+
|
82
|
+
### Command-Line Interface
|
83
|
+
|
84
|
+
To use the CLI, run the following command:
|
85
|
+
|
86
|
+
```sh
|
87
|
+
apksearch <package_name> [--version <version>]
|
88
|
+
```
|
89
|
+
|
90
|
+
Example:
|
91
|
+
|
92
|
+
```sh
|
93
|
+
apksearch com.roblox.client --version 2.652.765
|
94
|
+
```
|
95
|
+
|
96
|
+
### Library Usage
|
97
|
+
|
98
|
+
You can also use the library programmatically in your Python code:
|
99
|
+
|
100
|
+
```python
|
101
|
+
from apksearch import APKPure, APKMirror
|
102
|
+
|
103
|
+
# Searching on APKPure
|
104
|
+
apkpure = APKPure("com.roblox.client")
|
105
|
+
result = apkpure.search_apk()
|
106
|
+
if result:
|
107
|
+
title, link = result
|
108
|
+
print(f"Found on APKPure: {title} - {link}")
|
109
|
+
|
110
|
+
# Searching on APKMirror
|
111
|
+
apkmirror = APKMirror("com.roblox.client")
|
112
|
+
result = apkmirror.search_apk()
|
113
|
+
if result:
|
114
|
+
title, link = result
|
115
|
+
print(f"Found on APKMirror: {title} - {link}")
|
116
|
+
```
|
117
|
+
|
118
|
+
### Classes and Methods
|
119
|
+
|
120
|
+
#### `APKPure`
|
121
|
+
|
122
|
+
- **`__init__(self, pkg_name: str)`**: Initializes with the package name.
|
123
|
+
- **`search_apk(self) -> None | tuple[str, str]`**: Searches for the APK on APKPure and returns the title and link if found.
|
124
|
+
- **`find_versions(self, apk_link: str) -> list[tuple[str, str]]`**: Finds and returns a list of versions and their download links for the given APK link.
|
125
|
+
|
126
|
+
#### `APKMirror`
|
127
|
+
|
128
|
+
- **`__init__(self, pkg_name: str)`**: Initializes with the package name.
|
129
|
+
- **`search_apk(self) -> None | tuple[str, str]`**: Searches for the APK on APKMirror and returns the title and link if found.
|
130
|
+
- **`find_version(self, apk_link: str, version: str) -> str`**: Finds and returns the download link for the given APK link and version.
|
131
|
+
|
132
|
+
### Testing
|
133
|
+
|
134
|
+
The project includes tests for the `sites` classes. To run the tests, use the following command:
|
135
|
+
|
136
|
+
```sh
|
137
|
+
pytest
|
138
|
+
```
|
139
|
+
|
140
|
+
## TODO
|
141
|
+
|
142
|
+
- [ ] Add more websites to search for APKs.
|
143
|
+
|
144
|
+
## License
|
145
|
+
|
146
|
+
This project is licensed under the MIT License. See the [LICENSE](https://github.com/AbhiTheModder/apksearch/blob/main/LICENSE) file for more details.
|
147
|
+
|
148
|
+
## Contributing
|
149
|
+
|
150
|
+
Contributions are welcome! Please open an issue or submit a pull request on [GitHub](https://github.com/AbhiTheModder/apksearch).
|
@@ -0,0 +1,17 @@
|
|
1
|
+
LICENSE
|
2
|
+
README.md
|
3
|
+
pyproject.toml
|
4
|
+
apksearch/__init__.py
|
5
|
+
apksearch/__main__.py
|
6
|
+
apksearch/cli.py
|
7
|
+
apksearch.egg-info/PKG-INFO
|
8
|
+
apksearch.egg-info/SOURCES.txt
|
9
|
+
apksearch.egg-info/dependency_links.txt
|
10
|
+
apksearch.egg-info/entry_points.txt
|
11
|
+
apksearch.egg-info/requires.txt
|
12
|
+
apksearch.egg-info/top_level.txt
|
13
|
+
apksearch/sites/__init__.py
|
14
|
+
apksearch/sites/apkmirror.py
|
15
|
+
apksearch/sites/apkpure.py
|
16
|
+
tests/test_apkmirror.py
|
17
|
+
tests/test_apkpure.py
|
@@ -0,0 +1 @@
|
|
1
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
apksearch
|
@@ -0,0 +1,46 @@
|
|
1
|
+
[build-system]
|
2
|
+
requires = ["setuptools", "wheel"]
|
3
|
+
build-backend = "setuptools.build_meta"
|
4
|
+
|
5
|
+
[project]
|
6
|
+
name = "apksearch"
|
7
|
+
version = "1.0.0"
|
8
|
+
description = "Search for apks on varius websites"
|
9
|
+
authors = [{ name = "Abhi", email = "allinoneallinone00@gmail.com" }]
|
10
|
+
license = { file = "LICENSE" }
|
11
|
+
readme = "README.md"
|
12
|
+
requires-python = ">=3.10"
|
13
|
+
dependencies = ["beautifulsoup4>=4.12.3", "requests>=2.32.3"]
|
14
|
+
classifiers = [
|
15
|
+
"Development Status :: 4 - Beta",
|
16
|
+
"Natural Language :: English",
|
17
|
+
"Intended Audience :: Developers",
|
18
|
+
"License :: OSI Approved :: MIT License",
|
19
|
+
"Programming Language :: Python :: 3",
|
20
|
+
"Programming Language :: Python :: 3.10",
|
21
|
+
"Programming Language :: Python :: 3.11",
|
22
|
+
"Programming Language :: Python :: 3.12",
|
23
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
24
|
+
"Topic :: Text Processing :: General",
|
25
|
+
"Topic :: Utilities",
|
26
|
+
"Operating System :: OS Independent",
|
27
|
+
]
|
28
|
+
|
29
|
+
|
30
|
+
[project.urls]
|
31
|
+
homepage = "https://github.com/AbhiTheModder/apksearch.git"
|
32
|
+
source = "https://github.com/AbhiTheModder/apksearch.git"
|
33
|
+
issues = "https://github.com/AbhiTheModder/apksearch.git/issues"
|
34
|
+
|
35
|
+
[project.optional-dependencies]
|
36
|
+
dev = ["pytest>=7.4.3", "black>=23.12.1", "flake8>=6.1.0"]
|
37
|
+
|
38
|
+
[tool.pytest.ini_options]
|
39
|
+
minversion = "7.4.3"
|
40
|
+
testpaths = ["tests"]
|
41
|
+
|
42
|
+
[project.scripts]
|
43
|
+
apksearch = "apksearch.cli:main"
|
44
|
+
|
45
|
+
[tool.setuptools]
|
46
|
+
packages = ["apksearch", "apksearch.sites"]
|
@@ -0,0 +1,45 @@
|
|
1
|
+
from apksearch import APKMirror
|
2
|
+
|
3
|
+
|
4
|
+
def test_search_apk():
|
5
|
+
query = "com.roblox.client"
|
6
|
+
apkmirror = APKMirror(query)
|
7
|
+
result = apkmirror.search_apk()
|
8
|
+
|
9
|
+
assert result is not None, "No APK found for the query."
|
10
|
+
assert isinstance(result, tuple), "Result should be a tuple."
|
11
|
+
assert len(result) == 2, "Tuple should contain two elements."
|
12
|
+
assert isinstance(result[0], str), "First element of the tuple should be a string."
|
13
|
+
assert isinstance(result[1], str), "Second element of the tuple should be a string."
|
14
|
+
|
15
|
+
|
16
|
+
def test_find_versions_nfound():
|
17
|
+
query = "com.roblox.client"
|
18
|
+
version = "1.2.3"
|
19
|
+
apkmirror = APKMirror(query)
|
20
|
+
result = apkmirror.search_apk()
|
21
|
+
|
22
|
+
if result:
|
23
|
+
apk_link = result[1]
|
24
|
+
|
25
|
+
assert apk_link.startswith("https://"), "APK link should be a valid URL."
|
26
|
+
|
27
|
+
download_link = apkmirror.find_version(apk_link, version)
|
28
|
+
|
29
|
+
assert download_link is None, "Version not found."
|
30
|
+
|
31
|
+
|
32
|
+
def test_find_versions_found():
|
33
|
+
query = "com.roblox.client"
|
34
|
+
version = "2.652.765"
|
35
|
+
apkmirror = APKMirror(query)
|
36
|
+
result = apkmirror.search_apk()
|
37
|
+
|
38
|
+
if result:
|
39
|
+
apk_link = result[1]
|
40
|
+
download_link = apkmirror.find_version(apk_link, version)
|
41
|
+
|
42
|
+
assert isinstance(download_link, str), "Download link should be a string."
|
43
|
+
assert download_link.startswith(
|
44
|
+
"https://"
|
45
|
+
), "Download link should be a valid URL."
|
@@ -0,0 +1,38 @@
|
|
1
|
+
from apksearch.sites.apkpure import APKPure
|
2
|
+
|
3
|
+
|
4
|
+
def test_search_apk():
|
5
|
+
query = "com.roblox.client"
|
6
|
+
apkpure = APKPure(query)
|
7
|
+
result = apkpure.search_apk()
|
8
|
+
|
9
|
+
assert result is not None, "No APK found for the query."
|
10
|
+
assert isinstance(result, tuple), "Result should be a tuple."
|
11
|
+
assert len(result) == 2, "Tuple should contain two elements."
|
12
|
+
assert isinstance(result[0], str), "First element of the tuple should be a string."
|
13
|
+
assert isinstance(result[1], str), "Second element of the tuple should be a string."
|
14
|
+
|
15
|
+
|
16
|
+
def test_find_versions():
|
17
|
+
query = "com.roblox.client"
|
18
|
+
apkpure = APKPure(query)
|
19
|
+
result = apkpure.search_apk()
|
20
|
+
|
21
|
+
if result:
|
22
|
+
apk_link = result[1]
|
23
|
+
versions = apkpure.find_versions(apk_link)
|
24
|
+
|
25
|
+
assert isinstance(versions, list), "Versions should be a list."
|
26
|
+
assert len(versions) > 0, "No versions found."
|
27
|
+
assert all(
|
28
|
+
isinstance(version, tuple) for version in versions
|
29
|
+
), "Each version should be a tuple."
|
30
|
+
assert all(
|
31
|
+
len(version) == 2 for version in versions
|
32
|
+
), "Each version tuple should contain two elements."
|
33
|
+
assert all(
|
34
|
+
isinstance(version[0], str) for version in versions
|
35
|
+
), "First element of each version tuple should be a string."
|
36
|
+
assert all(
|
37
|
+
isinstance(version[1], str) for version in versions
|
38
|
+
), "Second element of each version tuple should be a string."
|