hltv-async-api 0.3.0__tar.gz → 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {hltv_async_api-0.3.0 → hltv_async_api-0.4.0}/PKG-INFO +44 -19
- hltv_async_api-0.4.0/README.md +195 -0
- {hltv_async_api-0.3.0 → hltv_async_api-0.4.0}/hltv_async_api/__init__.py +1 -1
- {hltv_async_api-0.3.0 → hltv_async_api-0.4.0}/hltv_async_api/aiohltv.py +175 -101
- {hltv_async_api-0.3.0 → hltv_async_api-0.4.0}/hltv_async_api.egg-info/PKG-INFO +44 -19
- {hltv_async_api-0.3.0 → hltv_async_api-0.4.0}/pyproject.toml +1 -1
- {hltv_async_api-0.3.0 → hltv_async_api-0.4.0}/setup.py +1 -2
- hltv_async_api-0.3.0/README.md +0 -170
- {hltv_async_api-0.3.0 → hltv_async_api-0.4.0}/LICENSE +0 -0
- {hltv_async_api-0.3.0 → hltv_async_api-0.4.0}/hltv_async_api.egg-info/SOURCES.txt +0 -0
- {hltv_async_api-0.3.0 → hltv_async_api-0.4.0}/hltv_async_api.egg-info/dependency_links.txt +0 -0
- {hltv_async_api-0.3.0 → hltv_async_api-0.4.0}/hltv_async_api.egg-info/top_level.txt +0 -0
- {hltv_async_api-0.3.0 → hltv_async_api-0.4.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: hltv_async_api
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Hltv-aio An unofficial asynchronous HLTV API Wrapper for Python
|
|
5
5
|
Home-page: https://github.com/akimerslys/aiohltv
|
|
6
6
|
Author: akimerslys
|
|
@@ -16,13 +16,20 @@ License-File: LICENSE
|
|
|
16
16
|
|
|
17
17
|
# hltv-async-api an unofficial asynchronous HLTV API Wrapper for Python
|
|
18
18
|
|
|
19
|
+
|
|
20
|
+
**This page not completed, not all methods and configs are written**
|
|
21
|
+
|
|
22
|
+
|
|
19
23
|
# Features
|
|
20
24
|
|
|
21
|
-
* New and modern fully async library
|
|
22
25
|
|
|
23
|
-
*
|
|
26
|
+
* **Simple Usage** (its realy simple)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
* **New and modern fully async library**
|
|
24
30
|
|
|
25
|
-
|
|
31
|
+
|
|
32
|
+
* **Supports proxy usage with huge amount of options**
|
|
26
33
|
|
|
27
34
|
|
|
28
35
|
---
|
|
@@ -64,13 +71,13 @@ hltv = Hltv(use_proxy=True, proxy_path='PATH_TO_PROXY.TXT')
|
|
|
64
71
|
```
|
|
65
72
|
|
|
66
73
|
|
|
67
|
-
**
|
|
74
|
+
**One-time proxy**
|
|
68
75
|
|
|
69
76
|
```
|
|
70
|
-
hltv = Hltv(use_proxy=True, proxy_path='PATH_TO_PROXY.TXT',
|
|
77
|
+
hltv = Hltv(use_proxy=True, proxy_path='PATH_TO_PROXY.TXT', proxy_one_time=True)
|
|
71
78
|
```
|
|
72
79
|
|
|
73
|
-
**
|
|
80
|
+
**Protocol usage**
|
|
74
81
|
|
|
75
82
|
```
|
|
76
83
|
proxy_list = ['120.234.203.171:9002', '110.38.68.38:80']
|
|
@@ -80,7 +87,8 @@ hltv = Hltv(use_proxy=True, proxy_list=proxy_list, proxy_protocol='http')
|
|
|
80
87
|
|
|
81
88
|
---
|
|
82
89
|
# Methods
|
|
83
|
-
|
|
90
|
+
|
|
91
|
+
* **get_upcoming_matches(days: int = 7, min_star_rating: int = 1)**
|
|
84
92
|
|
|
85
93
|
-days (the number of days into the future to fetch matches for)
|
|
86
94
|
|
|
@@ -89,29 +97,37 @@ hltv = Hltv(use_proxy=True, proxy_list=proxy_list, proxy_protocol='http')
|
|
|
89
97
|
```
|
|
90
98
|
await hltv.get_upcoming_matches(1, 5)
|
|
91
99
|
|
|
92
|
-
>>> ['date': '11
|
|
100
|
+
>>> ['date': '11-11', 'matches': [id: '1111', team1: 'Natus Vincere' | 'TBD', team2: 'FaZe' | 'TBD', time: '14:15', maps: '3', stars: 5, 'PGL CS2 Major Copenhagen 2024' | None]]```
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
* **get_events(outgoing=True, future=True, max_events=10) -> [('id', 'title', 'startdate', 'enddate')]**
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
await hltv.get_events(future=False)
|
|
107
|
+
|
|
108
|
+
>>>[{'id': '7620', 'name': 'ESL Challenger League Season 47 Europe', 'start_date': '26-2', 'end_date': '16-6'}, {'id': '7749', 'name': 'Thunderpick World Championship 2024 EU Closed Qualifier 1', 'start_date': '1-4', 'end_date': '22-4'}]
|
|
93
109
|
|
|
94
110
|
```
|
|
95
111
|
|
|
96
|
-
* get_event_results(event_id: int | str)
|
|
112
|
+
* **get_event_results(event_id: int | str)**
|
|
97
113
|
|
|
98
114
|
|
|
99
115
|
```
|
|
100
116
|
await get_event_results(7148)
|
|
101
117
|
|
|
102
|
-
>>> ['date': '31-3', 'team1': 'FaZe', 'team2': 'Natus Vincere', 'score1': '1', 'score2': '2']
|
|
118
|
+
>>> ['date': '31-3', 'matches': ['id': '1111', team1': 'FaZe', 'team2': 'Natus Vincere', 'score1': '1', 'score2': '2']]
|
|
103
119
|
|
|
104
120
|
```
|
|
105
121
|
|
|
106
|
-
* get_event_matches(event_id: str | int)
|
|
122
|
+
* **get_event_matches(event_id: str | int):**
|
|
107
123
|
|
|
108
124
|
```
|
|
109
125
|
await hltv.get_event_matches(7148)
|
|
110
126
|
|
|
111
|
-
>>>['
|
|
127
|
+
>>>['date': '1-1' | 'LIVE, 'matches': ['id': '1111', team1': 'Natus Vincere', 'team2': 'FaZe']
|
|
112
128
|
```
|
|
113
129
|
|
|
114
|
-
* get_event_info(event_id: str | int, event_title: str) -> (event_id, event_title, event_start, event_end, prize, team_num, location, groups)
|
|
130
|
+
* **get_event_info(event_id: str | int, event_title: str) -> (event_id, event_title, event_start, event_end, prize, team_num, location, groups)**
|
|
115
131
|
|
|
116
132
|
```
|
|
117
133
|
await hltv.get_event_info(7148, 'PGL CS2 Major Copenhagen2024')
|
|
@@ -120,15 +136,15 @@ await hltv.get_event_info(7148, 'PGL CS2 Major Copenhagen2024')
|
|
|
120
136
|
```
|
|
121
137
|
|
|
122
138
|
|
|
123
|
-
get_top_teams(max_teams=30) -> ['rank', 'title', 'points', 'change', 'id']
|
|
139
|
+
* **get_top_teams(max_teams=30) -> ['rank', 'title', 'points', 'change', 'id']**
|
|
124
140
|
|
|
125
141
|
```
|
|
126
142
|
await hltv.get_top_teams(2)
|
|
127
143
|
|
|
128
|
-
>>>[{'rank': '1', 'title': 'FaZe', 'points': '939', 'change': '-', 'id': '6667'}, {'rank': '2', 'title': 'Natus Vincere', 'points': '757', 'change': '+4', 'id': '4608'}]
|
|
144
|
+
>>>[{'id': '1111', 'rank': '1', 'title': 'FaZe', 'points': '939', 'change': '-', 'id': '6667'}, {'id': '1111', 'rank': '2', 'title': 'Natus Vincere', 'points': '757', 'change': '+4', 'id': '4608'}]
|
|
129
145
|
```
|
|
130
146
|
|
|
131
|
-
get_team_info(team_id: int | str, title: str) -> (team_id, team_title, rank, [players], coach, average_age, weeks_in_top_20, last_trophy, total_trophys)
|
|
147
|
+
* **get_team_info(team_id: int | str, title: str) -> (team_id, team_title, rank, [players], coach, average_age, weeks_in_top_20, last_trophy, total_trophys)**
|
|
132
148
|
|
|
133
149
|
```
|
|
134
150
|
await hltv.get_team_info(6667, 'faze')
|
|
@@ -136,13 +152,22 @@ await hltv.get_team_info(6667, 'faze')
|
|
|
136
152
|
>>>(6667, 'faze', '1', ['karrigan', 'rain', 'frozen', 'ropz', 'broky'], 'NEO', '26.5', '256', 'CS Asia Championships 2023', 21)
|
|
137
153
|
```
|
|
138
154
|
|
|
139
|
-
get_last_news(
|
|
155
|
+
* **get_last_news(max_reg_news=2, only_today=True, only_featured=False) -> [date, [featured_id, featured_title, featured_desciption], [regular_id, reg_title, reg_time]]**
|
|
140
156
|
|
|
141
157
|
```
|
|
142
158
|
await hltv.get_last_news(only_today=True, max_reg_news=1)
|
|
143
159
|
|
|
144
160
|
>>>[{'date': '02-04', 'f_news': [{'f_id': '38682', 'f_title': 'NIP confirm r1nkle signing', 'f_desc': "Ninjas in Pyjamas only have an anchor player left to sign following the young Ukrainian AWPer's addition."}], 'news': [{'id': '38685', 'title': 'Rounds add sLowi, p3kko', 'posted': 'an hour ago'}, {'id': '38690', 'title': 'n1ssim returns to Sharks after paiN loan deal expires', 'posted': 'an hour ago'}]}]
|
|
145
161
|
```
|
|
162
|
+
|
|
163
|
+
* **get_best_players(top=40) -> ('rank', 'name', 'team', 'maps', 'rating')**
|
|
164
|
+
|
|
165
|
+
```
|
|
166
|
+
await hltv.get_best_players(2)
|
|
167
|
+
|
|
168
|
+
>>>[{'rank': 1, 'name': 'donk', 'team': 'Spirit', 'maps': '33', 'rating': '1.52'}, {'rank': 2, 'name': 'm0NESY', 'team': 'G2', 'maps': '34', 'rating': '1.38'}]
|
|
169
|
+
```
|
|
170
|
+
|
|
146
171
|
---
|
|
147
172
|
# Examples
|
|
148
173
|
|
|
@@ -169,7 +194,7 @@ from hltv_async_api import Hltv
|
|
|
169
194
|
|
|
170
195
|
async def test():
|
|
171
196
|
|
|
172
|
-
hltv = Hltv(debug=True, use_proxy=True, proxy_path='proxy_test.txt', timeout=1,
|
|
197
|
+
hltv = Hltv(debug=True, use_proxy=True, proxy_path='proxy_test.txt', timeout=1, proxy_one_time=True, proxy_protocol='http')
|
|
173
198
|
|
|
174
199
|
print(await hltv.get_event_info(7148, 'pgl-cs2-major-copenhagen-2024'))
|
|
175
200
|
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# hltv-async-api an unofficial asynchronous HLTV API Wrapper for Python
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
**This page not completed, not all methods and configs are written**
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
# Features
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
* **Simple Usage** (its realy simple)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
* **New and modern fully async library**
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
* **Supports proxy usage with huge amount of options**
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
# Installation
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
pip install hltv-async-api
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
# Simple Usage
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
from hltv_async_api import Hltv
|
|
34
|
+
|
|
35
|
+
hltv = Hltv()
|
|
36
|
+
live_matches = await hltv.get_live_matches()
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
# Proxy Usage
|
|
42
|
+
|
|
43
|
+
**Load Proxies from list**
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
proxy_list = ['http://120.234.203.171:9002', 'http://110.38.68.38:80']
|
|
47
|
+
|
|
48
|
+
hltv = Hltv(use_proxy=True, proxy_list=proxy_list)
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**Load Proxies from file**
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
hltv = Hltv(use_proxy=True, proxy_path='PATH_TO_PROXY.TXT')
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
**One-time proxy**
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
hltv = Hltv(use_proxy=True, proxy_path='PATH_TO_PROXY.TXT', proxy_one_time=True)
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
**Protocol usage**
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
proxy_list = ['120.234.203.171:9002', '110.38.68.38:80']
|
|
68
|
+
|
|
69
|
+
hltv = Hltv(use_proxy=True, proxy_list=proxy_list, proxy_protocol='http')
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
# Methods
|
|
74
|
+
|
|
75
|
+
* **get_upcoming_matches(days: int = 7, min_star_rating: int = 1)**
|
|
76
|
+
|
|
77
|
+
-days (the number of days into the future to fetch matches for)
|
|
78
|
+
|
|
79
|
+
-min_star_rating (the minimum star rating for matches to include)
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
await hltv.get_upcoming_matches(1, 5)
|
|
83
|
+
|
|
84
|
+
>>> ['date': '11-11', 'matches': [id: '1111', team1: 'Natus Vincere' | 'TBD', team2: 'FaZe' | 'TBD', time: '14:15', maps: '3', stars: 5, 'PGL CS2 Major Copenhagen 2024' | None]]```
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
* **get_events(outgoing=True, future=True, max_events=10) -> [('id', 'title', 'startdate', 'enddate')]**
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
await hltv.get_events(future=False)
|
|
91
|
+
|
|
92
|
+
>>>[{'id': '7620', 'name': 'ESL Challenger League Season 47 Europe', 'start_date': '26-2', 'end_date': '16-6'}, {'id': '7749', 'name': 'Thunderpick World Championship 2024 EU Closed Qualifier 1', 'start_date': '1-4', 'end_date': '22-4'}]
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
* **get_event_results(event_id: int | str)**
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
await get_event_results(7148)
|
|
101
|
+
|
|
102
|
+
>>> ['date': '31-3', 'matches': ['id': '1111', team1': 'FaZe', 'team2': 'Natus Vincere', 'score1': '1', 'score2': '2']]
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
* **get_event_matches(event_id: str | int):**
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
await hltv.get_event_matches(7148)
|
|
110
|
+
|
|
111
|
+
>>>['date': '1-1' | 'LIVE, 'matches': ['id': '1111', team1': 'Natus Vincere', 'team2': 'FaZe']
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
* **get_event_info(event_id: str | int, event_title: str) -> (event_id, event_title, event_start, event_end, prize, team_num, location, groups)**
|
|
115
|
+
|
|
116
|
+
```
|
|
117
|
+
await hltv.get_event_info(7148, 'PGL CS2 Major Copenhagen2024')
|
|
118
|
+
|
|
119
|
+
(7148, 'PGL CS2 Major Copenhagen2024', '21-3', '31-3', '$1,250,000', '16', 'Copenhagen, Denmark', [])
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
* **get_top_teams(max_teams=30) -> ['rank', 'title', 'points', 'change', 'id']**
|
|
124
|
+
|
|
125
|
+
```
|
|
126
|
+
await hltv.get_top_teams(2)
|
|
127
|
+
|
|
128
|
+
>>>[{'id': '1111', 'rank': '1', 'title': 'FaZe', 'points': '939', 'change': '-', 'id': '6667'}, {'id': '1111', 'rank': '2', 'title': 'Natus Vincere', 'points': '757', 'change': '+4', 'id': '4608'}]
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
* **get_team_info(team_id: int | str, title: str) -> (team_id, team_title, rank, [players], coach, average_age, weeks_in_top_20, last_trophy, total_trophys)**
|
|
132
|
+
|
|
133
|
+
```
|
|
134
|
+
await hltv.get_team_info(6667, 'faze')
|
|
135
|
+
|
|
136
|
+
>>>(6667, 'faze', '1', ['karrigan', 'rain', 'frozen', 'ropz', 'broky'], 'NEO', '26.5', '256', 'CS Asia Championships 2023', 21)
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
* **get_last_news(max_reg_news=2, only_today=True, only_featured=False) -> [date, [featured_id, featured_title, featured_desciption], [regular_id, reg_title, reg_time]]**
|
|
140
|
+
|
|
141
|
+
```
|
|
142
|
+
await hltv.get_last_news(only_today=True, max_reg_news=1)
|
|
143
|
+
|
|
144
|
+
>>>[{'date': '02-04', 'f_news': [{'f_id': '38682', 'f_title': 'NIP confirm r1nkle signing', 'f_desc': "Ninjas in Pyjamas only have an anchor player left to sign following the young Ukrainian AWPer's addition."}], 'news': [{'id': '38685', 'title': 'Rounds add sLowi, p3kko', 'posted': 'an hour ago'}, {'id': '38690', 'title': 'n1ssim returns to Sharks after paiN loan deal expires', 'posted': 'an hour ago'}]}]
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
* **get_best_players(top=40) -> ('rank', 'name', 'team', 'maps', 'rating')**
|
|
148
|
+
|
|
149
|
+
```
|
|
150
|
+
await hltv.get_best_players(2)
|
|
151
|
+
|
|
152
|
+
>>>[{'rank': 1, 'name': 'donk', 'team': 'Spirit', 'maps': '33', 'rating': '1.52'}, {'rank': 2, 'name': 'm0NESY', 'team': 'G2', 'maps': '34', 'rating': '1.38'}]
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
# Examples
|
|
157
|
+
|
|
158
|
+
****Simple Example****
|
|
159
|
+
|
|
160
|
+
```
|
|
161
|
+
from hltv_async_api import Hltv
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
async def test():
|
|
165
|
+
|
|
166
|
+
hltv = Hltv()
|
|
167
|
+
|
|
168
|
+
print(await hltv.get_event_info(7148, 'pgl-cs2-major-copenhagen-2024'))
|
|
169
|
+
|
|
170
|
+
if __name__ == "__main__":
|
|
171
|
+
asyncio.run(test())
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
****Proxy Parser****
|
|
175
|
+
```
|
|
176
|
+
from hltv_async_api import Hltv
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
async def test():
|
|
180
|
+
|
|
181
|
+
hltv = Hltv(debug=True, use_proxy=True, proxy_path='proxy_test.txt', timeout=1, proxy_one_time=True, proxy_protocol='http')
|
|
182
|
+
|
|
183
|
+
print(await hltv.get_event_info(7148, 'pgl-cs2-major-copenhagen-2024'))
|
|
184
|
+
|
|
185
|
+
if __name__ == "__main__":
|
|
186
|
+
asyncio.run(test())
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
# Requirements:
|
|
191
|
+
|
|
192
|
+
Python 3.9+
|
|
193
|
+
|
|
194
|
+
License:
|
|
195
|
+
HLTV Async is licensed under the MIT License, allowing for personal and commercial use with minimal restrictions.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from typing import Any, List
|
|
2
2
|
from datetime import date, datetime, timedelta
|
|
3
3
|
import pytz
|
|
4
|
-
|
|
4
|
+
|
|
5
5
|
from bs4 import BeautifulSoup
|
|
6
6
|
import asyncio
|
|
7
7
|
from asyncio import get_running_loop
|
|
@@ -10,6 +10,8 @@ from functools import partial
|
|
|
10
10
|
from aiohttp import ClientSession, ClientTimeout
|
|
11
11
|
from aiohttp.client_exceptions import ClientProxyConnectionError, ClientResponseError, ClientOSError, \
|
|
12
12
|
ServerDisconnectedError, ClientHttpProxyError
|
|
13
|
+
import re
|
|
14
|
+
|
|
13
15
|
|
|
14
16
|
import logging
|
|
15
17
|
|
|
@@ -23,7 +25,8 @@ class Hltv:
|
|
|
23
25
|
debug: bool = False,
|
|
24
26
|
max_retries: int = 0,
|
|
25
27
|
proxy_protocol: str | None = None,
|
|
26
|
-
|
|
28
|
+
proxy_one_time: bool = False,
|
|
29
|
+
true_session: bool = False,
|
|
27
30
|
):
|
|
28
31
|
self.headers = {
|
|
29
32
|
"referer": "https://www.hltv.org/stats",
|
|
@@ -37,7 +40,7 @@ class Hltv:
|
|
|
37
40
|
self.PROXY_PATH = proxy_path
|
|
38
41
|
self.PROXY_LIST = proxy_list
|
|
39
42
|
self.PROXY_PROTOCOL = proxy_protocol
|
|
40
|
-
self.
|
|
43
|
+
self.PROXY_ONCE = proxy_one_time
|
|
41
44
|
self.DEBUG = debug
|
|
42
45
|
self._configure_logging()
|
|
43
46
|
self.logger = logging.getLogger(__name__)
|
|
@@ -46,10 +49,22 @@ class Hltv:
|
|
|
46
49
|
with open(self.PROXY_PATH, "r") as file:
|
|
47
50
|
self.PROXY_LIST = [line.strip() for line in file.readlines()]
|
|
48
51
|
|
|
52
|
+
self.TRUE_SESSION = true_session
|
|
53
|
+
self.session = None
|
|
54
|
+
|
|
49
55
|
def _configure_logging(self):
|
|
50
56
|
level = logging.DEBUG if self.DEBUG else logging.INFO
|
|
51
57
|
logging.basicConfig(level=level, format="%(message)s")
|
|
52
58
|
|
|
59
|
+
async def _create_session(self):
|
|
60
|
+
self.logger.debug('Creating Session')
|
|
61
|
+
self.session = ClientSession()
|
|
62
|
+
|
|
63
|
+
async def close_session(self):
|
|
64
|
+
if self.session:
|
|
65
|
+
self.logger.debug('Closing Session')
|
|
66
|
+
await self.session.close()
|
|
67
|
+
|
|
53
68
|
def config(self, max_delay: int | None = None,
|
|
54
69
|
timeout: int | None = None,
|
|
55
70
|
use_proxy: bool | None = None,
|
|
@@ -58,7 +73,7 @@ class Hltv:
|
|
|
58
73
|
debug: bool | None = None,
|
|
59
74
|
max_retries: int | None = None,
|
|
60
75
|
proxy_protocol: str | None = None,
|
|
61
|
-
|
|
76
|
+
proxy_one_time: bool | None = None,
|
|
62
77
|
):
|
|
63
78
|
if max_delay:
|
|
64
79
|
self.MAX_DELAY = max_delay
|
|
@@ -72,8 +87,8 @@ class Hltv:
|
|
|
72
87
|
self.max_retries = max_retries
|
|
73
88
|
if proxy_protocol:
|
|
74
89
|
self.PROXY_PROTOCOL = proxy_protocol
|
|
75
|
-
if
|
|
76
|
-
self.
|
|
90
|
+
if proxy_one_time:
|
|
91
|
+
self.PROXY_ONCE = proxy_one_time
|
|
77
92
|
if debug:
|
|
78
93
|
self.DEBUG = debug
|
|
79
94
|
self._configure_logging()
|
|
@@ -81,7 +96,7 @@ class Hltv:
|
|
|
81
96
|
with open(self.PROXY_PATH, "r") as file:
|
|
82
97
|
self.PROXY_LIST = [line.strip() for line in file.readlines()]
|
|
83
98
|
|
|
84
|
-
async def
|
|
99
|
+
async def _get_proxy(self):
|
|
85
100
|
proxy = self.PROXY_LIST[0]
|
|
86
101
|
|
|
87
102
|
if self.PROXY_PROTOCOL and proxy != '' and self.PROXY_PROTOCOL not in proxy:
|
|
@@ -89,30 +104,30 @@ class Hltv:
|
|
|
89
104
|
|
|
90
105
|
return proxy
|
|
91
106
|
|
|
92
|
-
async def
|
|
93
|
-
if self.
|
|
107
|
+
async def _switch_proxy(self):
|
|
108
|
+
if self.PROXY_ONCE:
|
|
94
109
|
self.logger.debug(f'Removing proxy {self.PROXY_LIST[0]}')
|
|
95
110
|
self.PROXY_LIST = self.PROXY_LIST[1:]
|
|
96
111
|
else:
|
|
97
|
-
self.logger.debug(f"Switching proxy {self.PROXY_LIST[0]}")
|
|
98
|
-
self.PROXY_LIST = self.PROXY_LIST[1:] + self.PROXY_LIST[0]
|
|
99
|
-
self.logger.info(f"New proxy: {self.PROXY_LIST[0]}")
|
|
112
|
+
self.logger.debug(f"Switching proxy {self.PROXY_LIST[0] if self.PROXY_LIST[0] else 'No Proxy'}")
|
|
113
|
+
self.PROXY_LIST = self.PROXY_LIST[1:] + [(self.PROXY_LIST[0])]
|
|
114
|
+
self.logger.info(f"New proxy: {self.PROXY_LIST[0] if self.PROXY_LIST[0] else 'No Proxy'}")
|
|
100
115
|
|
|
101
|
-
def
|
|
116
|
+
def _f(self, result):
|
|
102
117
|
return BeautifulSoup(result, "lxml")
|
|
103
118
|
|
|
104
|
-
async def
|
|
105
|
-
page = self.
|
|
119
|
+
async def _cloudflare_check(self, result) -> bool:
|
|
120
|
+
page = self._f(result)
|
|
106
121
|
challenge_page = page.find(id="challenge-error-title")
|
|
107
122
|
if challenge_page is not None:
|
|
108
123
|
if "Enable JavaScript and cookies to continue" in challenge_page.get_text():
|
|
109
|
-
self.logger.debug("Got cloudflare
|
|
124
|
+
self.logger.debug("Got cloudflare challenge page")
|
|
110
125
|
return True
|
|
111
126
|
return False
|
|
112
127
|
|
|
113
|
-
async def
|
|
128
|
+
async def _parse_error_handler(self, delay: int = 0) -> int:
|
|
114
129
|
if self.USE_PROXY:
|
|
115
|
-
await self.
|
|
130
|
+
await self._switch_proxy()
|
|
116
131
|
else:
|
|
117
132
|
if delay < self.MAX_DELAY:
|
|
118
133
|
delay += 1
|
|
@@ -122,61 +137,69 @@ class Hltv:
|
|
|
122
137
|
|
|
123
138
|
return delay
|
|
124
139
|
|
|
125
|
-
async def
|
|
140
|
+
async def _parse(self, url, delay):
|
|
126
141
|
proxy = ''
|
|
127
142
|
# setup new proxy, cuz old one was switched
|
|
128
143
|
if self.USE_PROXY:
|
|
129
|
-
proxy = await self.
|
|
144
|
+
proxy = await self._get_proxy()
|
|
130
145
|
else:
|
|
131
146
|
# delay, only for non proxy users. (default = 1-15s)
|
|
132
147
|
await asyncio.sleep(delay)
|
|
133
148
|
try:
|
|
134
|
-
async with session.get(url, headers=self.headers, proxy=proxy, timeout=self.timeout, ) as response:
|
|
149
|
+
async with self.session.get(url, headers=self.headers, proxy=proxy, timeout=self.timeout, ) as response:
|
|
135
150
|
self.logger.info(f"Fetching {url}, code: {response.status}")
|
|
136
151
|
if response.status == 403 or response.status == 404:
|
|
137
152
|
self.logger.debug("Got 403 forbitten")
|
|
138
|
-
return False, await self.
|
|
153
|
+
return False, await self._parse_error_handler(delay)
|
|
139
154
|
|
|
140
155
|
# checking for challenge page.
|
|
141
156
|
result = await response.text()
|
|
142
|
-
if await self.
|
|
143
|
-
return False, await self.
|
|
157
|
+
if await self._cloudflare_check(result):
|
|
158
|
+
return False, await self._parse_error_handler(delay)
|
|
144
159
|
|
|
145
160
|
return True, result
|
|
146
161
|
except (ClientProxyConnectionError, ClientResponseError, ClientOSError,
|
|
147
162
|
ServerDisconnectedError, TimeoutError, ClientHttpProxyError) as e:
|
|
148
|
-
delay = await self.
|
|
163
|
+
delay = await self._parse_error_handler(delay)
|
|
149
164
|
return False, delay
|
|
150
165
|
|
|
151
|
-
async def
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
166
|
+
async def _fetch(self, url, delay: int = 0):
|
|
167
|
+
if not self.session:
|
|
168
|
+
await self._create_session()
|
|
169
|
+
|
|
170
|
+
status = False
|
|
171
|
+
try_ = 1
|
|
172
|
+
result = None
|
|
173
|
+
while not status and (try_ != self.max_retries):
|
|
174
|
+
self.logger.debug(f'Trying connect to {url}, try {try_}/{self.max_retries}')
|
|
175
|
+
|
|
176
|
+
# if status = True, result = page,
|
|
177
|
+
# if status = False result = delay (default=0)
|
|
178
|
+
status, result = await self._parse(url, delay)
|
|
179
|
+
|
|
180
|
+
if not status and result:
|
|
181
|
+
delay = result
|
|
182
|
+
try_ += 1
|
|
183
|
+
|
|
184
|
+
# After Parse
|
|
185
|
+
if not self.TRUE_SESSION:
|
|
186
|
+
# Automaticaly close session after parse
|
|
187
|
+
await self.close_session()
|
|
188
|
+
|
|
189
|
+
if status:
|
|
190
|
+
loop = get_running_loop()
|
|
191
|
+
parsed = await loop.run_in_executor(None, partial(self._f, result))
|
|
192
|
+
return parsed
|
|
193
|
+
else:
|
|
194
|
+
self.logger.error('Connection failed')
|
|
195
|
+
return None
|
|
173
196
|
|
|
174
197
|
def save_error(self, page):
|
|
175
198
|
with open("error.html", "w") as file:
|
|
176
199
|
file.write(page.prettify())
|
|
177
200
|
|
|
178
201
|
@staticmethod
|
|
179
|
-
def
|
|
202
|
+
def _normalize_date(parts) -> str:
|
|
180
203
|
month_abbreviations = {
|
|
181
204
|
'Jan': '1', 'Feb': '2', 'Mar': '3', 'Apr': '4',
|
|
182
205
|
'May': '5', 'Jun': '6', 'Jul': '7', 'Aug': '8',
|
|
@@ -186,9 +209,10 @@ class Hltv:
|
|
|
186
209
|
day = parts[1][:-2]
|
|
187
210
|
return day + '-' + month
|
|
188
211
|
|
|
212
|
+
# TODO rewrite
|
|
189
213
|
async def get_live_matches(self):
|
|
190
214
|
"""returns a list of all LIVE matches on HLTV along with the maps being played and the star ratings"""
|
|
191
|
-
r = await self.
|
|
215
|
+
r = await self._fetch("https://www.hltv.org/matches")
|
|
192
216
|
if not r:
|
|
193
217
|
return
|
|
194
218
|
|
|
@@ -203,9 +227,9 @@ class Hltv:
|
|
|
203
227
|
stars = [line.get('stars') for line in liveMatchContainer]
|
|
204
228
|
return [{'teams': teams, 'maps': maps, 'stars': stars} for teams, maps, stars in zip(matches, maps, stars)]
|
|
205
229
|
|
|
206
|
-
async def get_upcoming_matches(self, days: int = 7,
|
|
230
|
+
async def get_upcoming_matches(self, days: int = 7, min_rating: int = 1):
|
|
207
231
|
"""returns a list of all upcoming matches on HLTV"""
|
|
208
|
-
r = await self.
|
|
232
|
+
r = await self._fetch("https://www.hltv.org/matches")
|
|
209
233
|
if not r:return
|
|
210
234
|
|
|
211
235
|
matches = []
|
|
@@ -221,7 +245,9 @@ class Hltv:
|
|
|
221
245
|
for match in date_div.find_all('div', {'class': 'upcomingMatch'}):
|
|
222
246
|
time_ = match.find('div', {'class': 'matchTime'}).text
|
|
223
247
|
rating = int(match['stars'])
|
|
224
|
-
if rating >=
|
|
248
|
+
if rating >= min_rating:
|
|
249
|
+
match_id_ = match.find('a')['href'].split('/')[2]
|
|
250
|
+
|
|
225
251
|
maps = match.find('div', {'class': 'matchMeta'}).text[-1:]
|
|
226
252
|
try:
|
|
227
253
|
teams = match.find_all('div', {'class': 'matchTeamName text-ellipsis'})
|
|
@@ -242,6 +268,7 @@ class Hltv:
|
|
|
242
268
|
event = ''
|
|
243
269
|
|
|
244
270
|
matches_today.append({
|
|
271
|
+
'match_id': match_id_,
|
|
245
272
|
'team1': team1,
|
|
246
273
|
'team2': team2,
|
|
247
274
|
'time': time_,
|
|
@@ -258,27 +285,62 @@ class Hltv:
|
|
|
258
285
|
return None
|
|
259
286
|
return matches
|
|
260
287
|
|
|
261
|
-
async def get_important_upcoming_matches(self, star_rating=1):
|
|
262
|
-
"""returns a list of all upcoming matches on HLTV with the star rating argument (should be between 0 and 5)"""
|
|
263
|
-
r = await self.fetch("https://www.hltv.org/matches")
|
|
264
|
-
if not r:
|
|
265
|
-
return
|
|
266
288
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
289
|
+
async def get_match_info(self, match_id: str, team1: str, team2: str, event_title: str, stats: bool = True):
|
|
290
|
+
r = await self._fetch(f"https://www.hltv.org/matches/{match_id}/"
|
|
291
|
+
f"{team1.replace(' ', '-')}-vs-"
|
|
292
|
+
f"{team2.replace(' ', '-')}-"
|
|
293
|
+
f"{event_title.replace(' ', '-')}")
|
|
294
|
+
|
|
295
|
+
|
|
296
|
+
status = r.find('div', {'class': 'countdown'}).text
|
|
297
|
+
|
|
298
|
+
score1, score2 = 0, 0
|
|
299
|
+
|
|
300
|
+
if status == 'Match over':
|
|
301
|
+
scores = r.find_all('div', class_='team')
|
|
302
|
+
score1 = scores[0].get_text().replace('\n', '')[-1]
|
|
303
|
+
score2 = scores[1].get_text().replace('\n', '')[-1]
|
|
304
|
+
|
|
305
|
+
|
|
306
|
+
maps = []
|
|
307
|
+
for map_div in r.find_all('div', {'class': 'mapholder'}):
|
|
308
|
+
|
|
309
|
+
mapname = map_div.find('div', {'class': 'mapname'}).text
|
|
310
|
+
try:
|
|
311
|
+
r_teams = map_div.find_all('div', {'class': 'results-team-score'})
|
|
312
|
+
r_team1 = r_teams[0].text
|
|
313
|
+
r_team2 = r_teams[1].text
|
|
314
|
+
except AttributeError:
|
|
315
|
+
r_team1 = '0'
|
|
316
|
+
r_team2 = '0'
|
|
317
|
+
maps.append({'mapname': mapname, 'r_team1': r_team1, 'r_team2': r_team2})
|
|
318
|
+
|
|
319
|
+
stats_ = []
|
|
320
|
+
if stats and status == 'Match over':
|
|
321
|
+
for table_div in r.find_all('table', {'class': 'table totalstats'})[:2]:
|
|
322
|
+
for player in table_div.find_all('tr')[1:]:
|
|
323
|
+
player_id = player.find('a', class_='flagAlign')['href'].split('/')[2]
|
|
324
|
+
player_name = player.find('div', class_='statsPlayerName').text.strip()
|
|
325
|
+
nickname = re.findall(r"'(.*?)'", player_name)[0]
|
|
326
|
+
|
|
327
|
+
kd = player.find('td', class_='kd').text.strip()
|
|
328
|
+
adr = player.find('td', class_='adr').text.strip()
|
|
329
|
+
rating = player.find('td', class_='rating').text.strip()
|
|
330
|
+
stats_.append({
|
|
331
|
+
'id': player_id,
|
|
332
|
+
'name': nickname,
|
|
333
|
+
'kd': kd,
|
|
334
|
+
'adr': adr,
|
|
335
|
+
'rating': rating
|
|
336
|
+
})
|
|
337
|
+
|
|
338
|
+
return match_id, score1, score2, status, maps, stats
|
|
339
|
+
|
|
278
340
|
|
|
279
341
|
async def get_big_results(self, offset=0) -> list[dict[str, Any]] | None:
|
|
280
|
-
"""returns a list of
|
|
281
|
-
r = await self.
|
|
342
|
+
"""returns a list of big event matches results"""
|
|
343
|
+
r = await self._fetch("https://www.hltv.org/results?offset=" + str(offset))
|
|
282
344
|
if not r:
|
|
283
345
|
return
|
|
284
346
|
|
|
@@ -304,7 +366,7 @@ class Hltv:
|
|
|
304
366
|
return big_results
|
|
305
367
|
|
|
306
368
|
async def get_event_results(self, event: int | str) -> list[dict[str, Any]] | None:
|
|
307
|
-
r = await self.
|
|
369
|
+
r = await self._fetch("https://www.hltv.org/results?event=" + str(event))
|
|
308
370
|
if not r:
|
|
309
371
|
return
|
|
310
372
|
|
|
@@ -312,9 +374,9 @@ class Hltv:
|
|
|
312
374
|
|
|
313
375
|
for result in r.find("div", {'class', 'results-holder'}).find_all("div", {'class', 'results-sublist'}):
|
|
314
376
|
date = result.find("span", class_="standard-headline").text.strip()
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
377
|
+
match_date = []
|
|
378
|
+
for match in result.find_all("a", class_="a-reset"):
|
|
379
|
+
id_ = match['href'].split('/')[2]
|
|
318
380
|
teams = match.find_all("div", class_="team")
|
|
319
381
|
team1 = teams[0].text.strip()
|
|
320
382
|
team2 = teams[1].text.strip()
|
|
@@ -323,18 +385,21 @@ class Hltv:
|
|
|
323
385
|
score_t1 = scores[0].strip()
|
|
324
386
|
score_t2 = scores[1].strip()
|
|
325
387
|
|
|
326
|
-
|
|
327
|
-
'
|
|
388
|
+
match_date.append({
|
|
389
|
+
'id': id_,
|
|
328
390
|
'team1': team1,
|
|
329
391
|
'team2': team2,
|
|
330
392
|
'score1': score_t1,
|
|
331
393
|
'score2': score_t2,
|
|
332
394
|
})
|
|
333
|
-
|
|
395
|
+
match_results.append({
|
|
396
|
+
'date': date,
|
|
397
|
+
'matches': match_date,
|
|
398
|
+
})
|
|
334
399
|
return match_results
|
|
335
400
|
|
|
336
401
|
async def get_event_matches(self, event_id: str | int):
|
|
337
|
-
r = await self.
|
|
402
|
+
r = await self._fetch("https://www.hltv.org/events/" + str(event_id) + "/matches")
|
|
338
403
|
if not r:
|
|
339
404
|
return
|
|
340
405
|
|
|
@@ -344,8 +409,9 @@ class Hltv:
|
|
|
344
409
|
live_matches = r.find("div", {'class', 'liveMatchesSection'}).find_all("div", {'class', 'liveMatch'})
|
|
345
410
|
except AttributeError:
|
|
346
411
|
live_matches = []
|
|
347
|
-
|
|
412
|
+
live_mat = []
|
|
348
413
|
for live in live_matches:
|
|
414
|
+
id_ = live.find('a', {'class': 'match a-reset'})['href'].split('/')[2]
|
|
349
415
|
teams = live.find_all("div", class_="matchTeamName text-ellipsis")
|
|
350
416
|
team1 = teams[0].text.strip()
|
|
351
417
|
team2 = teams[1].text.strip()
|
|
@@ -359,24 +425,30 @@ class Hltv:
|
|
|
359
425
|
score_team1 = 0
|
|
360
426
|
score_team2 = 0
|
|
361
427
|
|
|
362
|
-
|
|
428
|
+
live_mat.append({
|
|
429
|
+
'id': id_,
|
|
363
430
|
'team1': team1,
|
|
364
431
|
'team2': team2,
|
|
365
|
-
'date': 'LIVE'
|
|
366
432
|
})
|
|
367
433
|
|
|
434
|
+
matches.append({
|
|
435
|
+
'date': 'LIVE',
|
|
436
|
+
'matches': live_mat,
|
|
437
|
+
})
|
|
438
|
+
|
|
368
439
|
for date_sect in r.find_all('div', {'class': 'upcomingMatchesSection'}):
|
|
369
440
|
date_ = date_sect.find('span', {'class': 'matchDayHeadline'}).text.split(' ')[-1]
|
|
370
|
-
for match in date_sect.find_all('div', {'class': '
|
|
441
|
+
for match in date_sect.find_all('div', {'class': 'match a-reset'}):
|
|
371
442
|
teams = match.find_all("div", class_="matchTeamName text-ellipsis")
|
|
372
443
|
if teams or len(teams) > 1:
|
|
373
|
-
|
|
444
|
+
id_ = match['href'].split('/')[2]
|
|
374
445
|
team1 = teams[0].text.strip()
|
|
375
446
|
team2 = teams[1].text.strip()
|
|
376
447
|
|
|
377
448
|
time_ = match.find('div', {'class', 'matchTime'}).text
|
|
378
449
|
|
|
379
450
|
matches.append({
|
|
451
|
+
'id': id_,
|
|
380
452
|
'team1': team1,
|
|
381
453
|
'team2': team2,
|
|
382
454
|
'date': date_ + " " + time_
|
|
@@ -396,7 +468,7 @@ class Hltv:
|
|
|
396
468
|
[('id', 'title', 'startdate', 'enddate')]
|
|
397
469
|
"""
|
|
398
470
|
|
|
399
|
-
r = await self.
|
|
471
|
+
r = await self._fetch('https://www.hltv.org/events')
|
|
400
472
|
if not r:
|
|
401
473
|
return
|
|
402
474
|
|
|
@@ -405,10 +477,10 @@ class Hltv:
|
|
|
405
477
|
for event in r.find('div', {'class': 'tab-content', 'id': 'TODAY'}).find_all('a', {
|
|
406
478
|
'class': 'a-reset ongoing-event'}):
|
|
407
479
|
event_name = event.find('div', {'class': 'text-ellipsis'}).text.strip()
|
|
408
|
-
event_start_date = self.
|
|
480
|
+
event_start_date = self._normalize_date(
|
|
409
481
|
event.find('span', {'data-time-format': 'MMM do'}).text.strip().split())
|
|
410
482
|
|
|
411
|
-
event_end_date = self.
|
|
483
|
+
event_end_date = self._normalize_date(
|
|
412
484
|
event.find_all('span', {'data-time-format': 'MMM do'})[1].text.strip().split())
|
|
413
485
|
event_id = event['href'].split('/')[-2]
|
|
414
486
|
|
|
@@ -429,8 +501,8 @@ class Hltv:
|
|
|
429
501
|
event_id = event['href'].split('/')[-2]
|
|
430
502
|
event_name = event.find('div', {'class': 'big-event-name'}).text.strip()
|
|
431
503
|
# event_location = event.find('span', {'class': 'big-event-location'}).text.strip()
|
|
432
|
-
event_start_date = self.
|
|
433
|
-
event_end_date = self.
|
|
504
|
+
event_start_date = self._normalize_date(event.find('span', {'class': ''}).text.strip().split())
|
|
505
|
+
event_end_date = self._normalize_date(event.find('span', {'class': ''}).text.strip().split())
|
|
434
506
|
|
|
435
507
|
events.append({
|
|
436
508
|
'id': event_id,
|
|
@@ -442,14 +514,14 @@ class Hltv:
|
|
|
442
514
|
return events
|
|
443
515
|
|
|
444
516
|
async def get_event_info(self, event_id: str | int, event_title: str):
|
|
445
|
-
r = await self.
|
|
517
|
+
r = await self._fetch(f"https://www.hltv.org/events/{str(event_id)}/{event_title.replace(' ', '-')}")
|
|
446
518
|
if not r:
|
|
447
519
|
return
|
|
448
520
|
|
|
449
521
|
event_date_div = r.find('td', {'class', 'eventdate'}).find_all('span')
|
|
450
522
|
|
|
451
|
-
event_start = self.
|
|
452
|
-
event_end = self.
|
|
523
|
+
event_start = self._normalize_date(event_date_div[0].text.split())
|
|
524
|
+
event_end = self._normalize_date(event_date_div[1].text.split()[1:-1])
|
|
453
525
|
|
|
454
526
|
prize = r.find('td', {'class', 'prizepool text-ellipsis'}).text
|
|
455
527
|
|
|
@@ -486,7 +558,7 @@ class Hltv:
|
|
|
486
558
|
|
|
487
559
|
teams = []
|
|
488
560
|
|
|
489
|
-
r = await self.
|
|
561
|
+
r = await self._fetch("https://www.hltv.org/ranking/teams/" + last_monday.strftime('%Y/%B/%d').lower())
|
|
490
562
|
|
|
491
563
|
if not r:
|
|
492
564
|
return
|
|
@@ -506,7 +578,7 @@ class Hltv:
|
|
|
506
578
|
title = title_div.find('span', {'class': 'name'}).text
|
|
507
579
|
points = title_div.find('span', {'class': 'points'}).text.split(' ', 1)[0][1:]
|
|
508
580
|
|
|
509
|
-
|
|
581
|
+
id_ = team.find('a', {'class': 'details moreLink'})['href'].split('/')[-1]
|
|
510
582
|
|
|
511
583
|
changes = {'change positive', 'change neutral', 'change negative'}
|
|
512
584
|
change = ''
|
|
@@ -518,11 +590,11 @@ class Hltv:
|
|
|
518
590
|
pass
|
|
519
591
|
|
|
520
592
|
teams.append({
|
|
593
|
+
'id': id_,
|
|
521
594
|
'rank': rank,
|
|
522
595
|
'title': title,
|
|
523
596
|
'points': points,
|
|
524
597
|
'change': change,
|
|
525
|
-
'id': id
|
|
526
598
|
})
|
|
527
599
|
except AttributeError:
|
|
528
600
|
raise AttributeError("Parsing error, probably page not fully loaded")
|
|
@@ -539,7 +611,7 @@ class Hltv:
|
|
|
539
611
|
(team_id, title, rank, players, coach, age, weeks, last_trophy, total_trophys) | None
|
|
540
612
|
weeks - weeks in top 20
|
|
541
613
|
"""
|
|
542
|
-
r = await self.
|
|
614
|
+
r = await self._fetch("https://www.hltv.org/team/" + str(team_id) + '/' + title.replace(' ', '-'))
|
|
543
615
|
players = []
|
|
544
616
|
try:
|
|
545
617
|
for player in r.find_all('span', {'class': 'text-ellipsis bold'}):
|
|
@@ -582,7 +654,7 @@ class Hltv:
|
|
|
582
654
|
maps - maps played
|
|
583
655
|
"""
|
|
584
656
|
year = datetime.strftime(datetime.utcnow(), '%Y')
|
|
585
|
-
r = await self.
|
|
657
|
+
r = await self._fetch(
|
|
586
658
|
f"https://www.hltv.org/stats/players?startDate={year}-01-01&endDate={year}-12-31&rankingFilter=Top20")
|
|
587
659
|
|
|
588
660
|
if not r:
|
|
@@ -592,7 +664,9 @@ class Hltv:
|
|
|
592
664
|
rank = 1
|
|
593
665
|
try:
|
|
594
666
|
for player in r.find('tbody').find_all('tr'):
|
|
595
|
-
|
|
667
|
+
name_div = player.find('td', {'class', 'playerCol'}).find('a')
|
|
668
|
+
id_ = name_div['href'].split('/')[3]
|
|
669
|
+
name = name_div.text
|
|
596
670
|
team = player.find('td', {'class', 'teamCol'})['data-sort']
|
|
597
671
|
|
|
598
672
|
maps = player.find('td', {'class', 'statsDetail'}).text
|
|
@@ -608,6 +682,7 @@ class Hltv:
|
|
|
608
682
|
pass
|
|
609
683
|
|
|
610
684
|
players.append({
|
|
685
|
+
'id': id_,
|
|
611
686
|
'rank': rank,
|
|
612
687
|
'name': name,
|
|
613
688
|
'team': team,
|
|
@@ -623,7 +698,7 @@ class Hltv:
|
|
|
623
698
|
return players
|
|
624
699
|
|
|
625
700
|
async def get_last_news(self, max_reg_news=2, only_today=True, only_featured=False):
|
|
626
|
-
r = await self.
|
|
701
|
+
r = await self._fetch('https://www.hltv.org/')
|
|
627
702
|
|
|
628
703
|
today = datetime.now(tz=pytz.timezone('Europe/Copenhagen'))
|
|
629
704
|
article_days = {
|
|
@@ -678,9 +753,8 @@ class Hltv:
|
|
|
678
753
|
|
|
679
754
|
|
|
680
755
|
async def test():
|
|
681
|
-
hltv = Hltv(
|
|
682
|
-
print(await hltv.
|
|
683
|
-
|
|
756
|
+
hltv = Hltv(debug=True)
|
|
757
|
+
print(await hltv.get_match_info('2370727', 'faze', 'natus-vincere', 'pgl-cs2-major-copenhagen-2024'))
|
|
684
758
|
|
|
685
759
|
if __name__ == "__main__":
|
|
686
760
|
asyncio.run(test())
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: hltv_async_api
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Hltv-aio An unofficial asynchronous HLTV API Wrapper for Python
|
|
5
5
|
Home-page: https://github.com/akimerslys/aiohltv
|
|
6
6
|
Author: akimerslys
|
|
@@ -16,13 +16,20 @@ License-File: LICENSE
|
|
|
16
16
|
|
|
17
17
|
# hltv-async-api an unofficial asynchronous HLTV API Wrapper for Python
|
|
18
18
|
|
|
19
|
+
|
|
20
|
+
**This page not completed, not all methods and configs are written**
|
|
21
|
+
|
|
22
|
+
|
|
19
23
|
# Features
|
|
20
24
|
|
|
21
|
-
* New and modern fully async library
|
|
22
25
|
|
|
23
|
-
*
|
|
26
|
+
* **Simple Usage** (its realy simple)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
* **New and modern fully async library**
|
|
24
30
|
|
|
25
|
-
|
|
31
|
+
|
|
32
|
+
* **Supports proxy usage with huge amount of options**
|
|
26
33
|
|
|
27
34
|
|
|
28
35
|
---
|
|
@@ -64,13 +71,13 @@ hltv = Hltv(use_proxy=True, proxy_path='PATH_TO_PROXY.TXT')
|
|
|
64
71
|
```
|
|
65
72
|
|
|
66
73
|
|
|
67
|
-
**
|
|
74
|
+
**One-time proxy**
|
|
68
75
|
|
|
69
76
|
```
|
|
70
|
-
hltv = Hltv(use_proxy=True, proxy_path='PATH_TO_PROXY.TXT',
|
|
77
|
+
hltv = Hltv(use_proxy=True, proxy_path='PATH_TO_PROXY.TXT', proxy_one_time=True)
|
|
71
78
|
```
|
|
72
79
|
|
|
73
|
-
**
|
|
80
|
+
**Protocol usage**
|
|
74
81
|
|
|
75
82
|
```
|
|
76
83
|
proxy_list = ['120.234.203.171:9002', '110.38.68.38:80']
|
|
@@ -80,7 +87,8 @@ hltv = Hltv(use_proxy=True, proxy_list=proxy_list, proxy_protocol='http')
|
|
|
80
87
|
|
|
81
88
|
---
|
|
82
89
|
# Methods
|
|
83
|
-
|
|
90
|
+
|
|
91
|
+
* **get_upcoming_matches(days: int = 7, min_star_rating: int = 1)**
|
|
84
92
|
|
|
85
93
|
-days (the number of days into the future to fetch matches for)
|
|
86
94
|
|
|
@@ -89,29 +97,37 @@ hltv = Hltv(use_proxy=True, proxy_list=proxy_list, proxy_protocol='http')
|
|
|
89
97
|
```
|
|
90
98
|
await hltv.get_upcoming_matches(1, 5)
|
|
91
99
|
|
|
92
|
-
>>> ['date': '11
|
|
100
|
+
>>> ['date': '11-11', 'matches': [id: '1111', team1: 'Natus Vincere' | 'TBD', team2: 'FaZe' | 'TBD', time: '14:15', maps: '3', stars: 5, 'PGL CS2 Major Copenhagen 2024' | None]]```
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
* **get_events(outgoing=True, future=True, max_events=10) -> [('id', 'title', 'startdate', 'enddate')]**
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
await hltv.get_events(future=False)
|
|
107
|
+
|
|
108
|
+
>>>[{'id': '7620', 'name': 'ESL Challenger League Season 47 Europe', 'start_date': '26-2', 'end_date': '16-6'}, {'id': '7749', 'name': 'Thunderpick World Championship 2024 EU Closed Qualifier 1', 'start_date': '1-4', 'end_date': '22-4'}]
|
|
93
109
|
|
|
94
110
|
```
|
|
95
111
|
|
|
96
|
-
* get_event_results(event_id: int | str)
|
|
112
|
+
* **get_event_results(event_id: int | str)**
|
|
97
113
|
|
|
98
114
|
|
|
99
115
|
```
|
|
100
116
|
await get_event_results(7148)
|
|
101
117
|
|
|
102
|
-
>>> ['date': '31-3', 'team1': 'FaZe', 'team2': 'Natus Vincere', 'score1': '1', 'score2': '2']
|
|
118
|
+
>>> ['date': '31-3', 'matches': ['id': '1111', team1': 'FaZe', 'team2': 'Natus Vincere', 'score1': '1', 'score2': '2']]
|
|
103
119
|
|
|
104
120
|
```
|
|
105
121
|
|
|
106
|
-
* get_event_matches(event_id: str | int)
|
|
122
|
+
* **get_event_matches(event_id: str | int):**
|
|
107
123
|
|
|
108
124
|
```
|
|
109
125
|
await hltv.get_event_matches(7148)
|
|
110
126
|
|
|
111
|
-
>>>['
|
|
127
|
+
>>>['date': '1-1' | 'LIVE, 'matches': ['id': '1111', team1': 'Natus Vincere', 'team2': 'FaZe']
|
|
112
128
|
```
|
|
113
129
|
|
|
114
|
-
* get_event_info(event_id: str | int, event_title: str) -> (event_id, event_title, event_start, event_end, prize, team_num, location, groups)
|
|
130
|
+
* **get_event_info(event_id: str | int, event_title: str) -> (event_id, event_title, event_start, event_end, prize, team_num, location, groups)**
|
|
115
131
|
|
|
116
132
|
```
|
|
117
133
|
await hltv.get_event_info(7148, 'PGL CS2 Major Copenhagen2024')
|
|
@@ -120,15 +136,15 @@ await hltv.get_event_info(7148, 'PGL CS2 Major Copenhagen2024')
|
|
|
120
136
|
```
|
|
121
137
|
|
|
122
138
|
|
|
123
|
-
get_top_teams(max_teams=30) -> ['rank', 'title', 'points', 'change', 'id']
|
|
139
|
+
* **get_top_teams(max_teams=30) -> ['rank', 'title', 'points', 'change', 'id']**
|
|
124
140
|
|
|
125
141
|
```
|
|
126
142
|
await hltv.get_top_teams(2)
|
|
127
143
|
|
|
128
|
-
>>>[{'rank': '1', 'title': 'FaZe', 'points': '939', 'change': '-', 'id': '6667'}, {'rank': '2', 'title': 'Natus Vincere', 'points': '757', 'change': '+4', 'id': '4608'}]
|
|
144
|
+
>>>[{'id': '1111', 'rank': '1', 'title': 'FaZe', 'points': '939', 'change': '-', 'id': '6667'}, {'id': '1111', 'rank': '2', 'title': 'Natus Vincere', 'points': '757', 'change': '+4', 'id': '4608'}]
|
|
129
145
|
```
|
|
130
146
|
|
|
131
|
-
get_team_info(team_id: int | str, title: str) -> (team_id, team_title, rank, [players], coach, average_age, weeks_in_top_20, last_trophy, total_trophys)
|
|
147
|
+
* **get_team_info(team_id: int | str, title: str) -> (team_id, team_title, rank, [players], coach, average_age, weeks_in_top_20, last_trophy, total_trophys)**
|
|
132
148
|
|
|
133
149
|
```
|
|
134
150
|
await hltv.get_team_info(6667, 'faze')
|
|
@@ -136,13 +152,22 @@ await hltv.get_team_info(6667, 'faze')
|
|
|
136
152
|
>>>(6667, 'faze', '1', ['karrigan', 'rain', 'frozen', 'ropz', 'broky'], 'NEO', '26.5', '256', 'CS Asia Championships 2023', 21)
|
|
137
153
|
```
|
|
138
154
|
|
|
139
|
-
get_last_news(
|
|
155
|
+
* **get_last_news(max_reg_news=2, only_today=True, only_featured=False) -> [date, [featured_id, featured_title, featured_desciption], [regular_id, reg_title, reg_time]]**
|
|
140
156
|
|
|
141
157
|
```
|
|
142
158
|
await hltv.get_last_news(only_today=True, max_reg_news=1)
|
|
143
159
|
|
|
144
160
|
>>>[{'date': '02-04', 'f_news': [{'f_id': '38682', 'f_title': 'NIP confirm r1nkle signing', 'f_desc': "Ninjas in Pyjamas only have an anchor player left to sign following the young Ukrainian AWPer's addition."}], 'news': [{'id': '38685', 'title': 'Rounds add sLowi, p3kko', 'posted': 'an hour ago'}, {'id': '38690', 'title': 'n1ssim returns to Sharks after paiN loan deal expires', 'posted': 'an hour ago'}]}]
|
|
145
161
|
```
|
|
162
|
+
|
|
163
|
+
* **get_best_players(top=40) -> ('rank', 'name', 'team', 'maps', 'rating')**
|
|
164
|
+
|
|
165
|
+
```
|
|
166
|
+
await hltv.get_best_players(2)
|
|
167
|
+
|
|
168
|
+
>>>[{'rank': 1, 'name': 'donk', 'team': 'Spirit', 'maps': '33', 'rating': '1.52'}, {'rank': 2, 'name': 'm0NESY', 'team': 'G2', 'maps': '34', 'rating': '1.38'}]
|
|
169
|
+
```
|
|
170
|
+
|
|
146
171
|
---
|
|
147
172
|
# Examples
|
|
148
173
|
|
|
@@ -169,7 +194,7 @@ from hltv_async_api import Hltv
|
|
|
169
194
|
|
|
170
195
|
async def test():
|
|
171
196
|
|
|
172
|
-
hltv = Hltv(debug=True, use_proxy=True, proxy_path='proxy_test.txt', timeout=1,
|
|
197
|
+
hltv = Hltv(debug=True, use_proxy=True, proxy_path='proxy_test.txt', timeout=1, proxy_one_time=True, proxy_protocol='http')
|
|
173
198
|
|
|
174
199
|
print(await hltv.get_event_info(7148, 'pgl-cs2-major-copenhagen-2024'))
|
|
175
200
|
|
|
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
|
|
|
2
2
|
|
|
3
3
|
setup(
|
|
4
4
|
name='hltv_async_api',
|
|
5
|
-
version='0.
|
|
5
|
+
version='0.4.0',
|
|
6
6
|
author='akimerslys',
|
|
7
7
|
author_email='akimslys2003@gmail.com',
|
|
8
8
|
description='Hltv-aio: An unofficial asynchronous HLTV API Wrapper for Python',
|
|
@@ -14,7 +14,6 @@ setup(
|
|
|
14
14
|
install_requires=[
|
|
15
15
|
'aiohttp==3.9.3',
|
|
16
16
|
'aiosignal==1.3.1',
|
|
17
|
-
'aiofiles==23.2.1',
|
|
18
17
|
'attrs==23.2.0',
|
|
19
18
|
'beautifulsoup4==4.12.3',
|
|
20
19
|
'frozenlist==1.4.1',
|
hltv_async_api-0.3.0/README.md
DELETED
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
# hltv-async-api an unofficial asynchronous HLTV API Wrapper for Python
|
|
2
|
-
|
|
3
|
-
# Features
|
|
4
|
-
|
|
5
|
-
* New and modern fully async library
|
|
6
|
-
|
|
7
|
-
* Supports proxy usage for rate-limiting and privacy
|
|
8
|
-
|
|
9
|
-
* Automatically changes proxy if access is denied
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
---
|
|
13
|
-
|
|
14
|
-
# Installation
|
|
15
|
-
|
|
16
|
-
```
|
|
17
|
-
pip install hltv-async-api
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
---
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
# Simple Usage
|
|
24
|
-
|
|
25
|
-
```
|
|
26
|
-
from hltv_async_api import Hltv
|
|
27
|
-
|
|
28
|
-
hltv = Hltv()
|
|
29
|
-
live_matches = await hltv.get_live_matches()
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
---
|
|
33
|
-
|
|
34
|
-
# Proxy Usage
|
|
35
|
-
|
|
36
|
-
**Load Proxies from list**
|
|
37
|
-
|
|
38
|
-
```
|
|
39
|
-
proxy_list = ['http://120.234.203.171:9002', 'http://110.38.68.38:80']
|
|
40
|
-
|
|
41
|
-
hltv = Hltv(use_proxy=True, proxy_list=proxy_list)
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
**Load Proxies from file**
|
|
45
|
-
|
|
46
|
-
```
|
|
47
|
-
hltv = Hltv(use_proxy=True, proxy_path='PATH_TO_PROXY.TXT')
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
**Remove bad proxy from file**
|
|
52
|
-
|
|
53
|
-
```
|
|
54
|
-
hltv = Hltv(use_proxy=True, proxy_path='PATH_TO_PROXY.TXT', remove_proxy=True)
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
**Add proxy protocol**
|
|
58
|
-
|
|
59
|
-
```
|
|
60
|
-
proxy_list = ['120.234.203.171:9002', '110.38.68.38:80']
|
|
61
|
-
|
|
62
|
-
hltv = Hltv(use_proxy=True, proxy_list=proxy_list, proxy_protocol='http')
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
---
|
|
66
|
-
# Methods
|
|
67
|
-
* get_upcoming_matches(days: int = 7, min_star_rating: int = 1)
|
|
68
|
-
|
|
69
|
-
-days (the number of days into the future to fetch matches for)
|
|
70
|
-
|
|
71
|
-
-min_star_rating (the minimum star rating for matches to include)
|
|
72
|
-
|
|
73
|
-
```
|
|
74
|
-
await hltv.get_upcoming_matches(1, 5)
|
|
75
|
-
|
|
76
|
-
>>> ['date': '11/11/2024', 'matches': [team1: 'Natus Vincere' | 'TBD', team2: 'FaZe' | 'TBD', time: '14:15', maps: '3', stars: 5, 'PGL CS2 Major Copenhagen 2024' | None]]```
|
|
77
|
-
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
* get_event_results(event_id: int | str)
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
```
|
|
84
|
-
await get_event_results(7148)
|
|
85
|
-
|
|
86
|
-
>>> ['date': '31-3', 'team1': 'FaZe', 'team2': 'Natus Vincere', 'score1': '1', 'score2': '2']
|
|
87
|
-
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
* get_event_matches(event_id: str | int):
|
|
91
|
-
|
|
92
|
-
```
|
|
93
|
-
await hltv.get_event_matches(7148)
|
|
94
|
-
|
|
95
|
-
>>>['team1': 'Natus Vincere', 'team2': 'FaZe', 'date': '11-11' | 'LIVE']
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
* get_event_info(event_id: str | int, event_title: str) -> (event_id, event_title, event_start, event_end, prize, team_num, location, groups)
|
|
99
|
-
|
|
100
|
-
```
|
|
101
|
-
await hltv.get_event_info(7148, 'PGL CS2 Major Copenhagen2024')
|
|
102
|
-
|
|
103
|
-
(7148, 'PGL CS2 Major Copenhagen2024', '21-3', '31-3', '$1,250,000', '16', 'Copenhagen, Denmark', [])
|
|
104
|
-
```
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
get_top_teams(max_teams=30) -> ['rank', 'title', 'points', 'change', 'id']
|
|
108
|
-
|
|
109
|
-
```
|
|
110
|
-
await hltv.get_top_teams(2)
|
|
111
|
-
|
|
112
|
-
>>>[{'rank': '1', 'title': 'FaZe', 'points': '939', 'change': '-', 'id': '6667'}, {'rank': '2', 'title': 'Natus Vincere', 'points': '757', 'change': '+4', 'id': '4608'}]
|
|
113
|
-
```
|
|
114
|
-
|
|
115
|
-
get_team_info(team_id: int | str, title: str) -> (team_id, team_title, rank, [players], coach, average_age, weeks_in_top_20, last_trophy, total_trophys)
|
|
116
|
-
|
|
117
|
-
```
|
|
118
|
-
await hltv.get_team_info(6667, 'faze')
|
|
119
|
-
|
|
120
|
-
>>>(6667, 'faze', '1', ['karrigan', 'rain', 'frozen', 'ropz', 'broky'], 'NEO', '26.5', '256', 'CS Asia Championships 2023', 21)
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
get_last_news(self, max_reg_news=2, only_today=True, only_featured=False) -> [date, [featured_id, featured_title, featured_desciption], [regular_id, reg_title, reg_time]]
|
|
124
|
-
|
|
125
|
-
```
|
|
126
|
-
await hltv.get_last_news(only_today=True, max_reg_news=1)
|
|
127
|
-
|
|
128
|
-
>>>[{'date': '02-04', 'f_news': [{'f_id': '38682', 'f_title': 'NIP confirm r1nkle signing', 'f_desc': "Ninjas in Pyjamas only have an anchor player left to sign following the young Ukrainian AWPer's addition."}], 'news': [{'id': '38685', 'title': 'Rounds add sLowi, p3kko', 'posted': 'an hour ago'}, {'id': '38690', 'title': 'n1ssim returns to Sharks after paiN loan deal expires', 'posted': 'an hour ago'}]}]
|
|
129
|
-
```
|
|
130
|
-
---
|
|
131
|
-
# Examples
|
|
132
|
-
|
|
133
|
-
****Simple Example****
|
|
134
|
-
|
|
135
|
-
```
|
|
136
|
-
from hltv_async_api import Hltv
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
async def test():
|
|
140
|
-
|
|
141
|
-
hltv = Hltv()
|
|
142
|
-
|
|
143
|
-
print(await hltv.get_event_info(7148, 'pgl-cs2-major-copenhagen-2024'))
|
|
144
|
-
|
|
145
|
-
if __name__ == "__main__":
|
|
146
|
-
asyncio.run(test())
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
****Proxy Parser****
|
|
150
|
-
```
|
|
151
|
-
from hltv_async_api import Hltv
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
async def test():
|
|
155
|
-
|
|
156
|
-
hltv = Hltv(debug=True, use_proxy=True, proxy_path='proxy_test.txt', timeout=1, remove_proxy=True, proxy_protocol='http')
|
|
157
|
-
|
|
158
|
-
print(await hltv.get_event_info(7148, 'pgl-cs2-major-copenhagen-2024'))
|
|
159
|
-
|
|
160
|
-
if __name__ == "__main__":
|
|
161
|
-
asyncio.run(test())
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
# Requirements:
|
|
166
|
-
|
|
167
|
-
Python 3.9+
|
|
168
|
-
|
|
169
|
-
License:
|
|
170
|
-
HLTV Async is licensed under the MIT License, allowing for personal and commercial use with minimal restrictions.
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|