craftllc-api 0.1.2__py3-none-any.whl
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.
- craftapi/__init__.py +5 -0
- craftapi/nytgames.py +13 -0
- craftapi/requests.py +177 -0
- craftapi/vartools.py +47 -0
- craftllc_api-0.1.2.dist-info/METADATA +166 -0
- craftllc_api-0.1.2.dist-info/RECORD +8 -0
- craftllc_api-0.1.2.dist-info/WHEEL +5 -0
- craftllc_api-0.1.2.dist-info/top_level.txt +1 -0
craftapi/__init__.py
ADDED
craftapi/nytgames.py
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import requests
|
|
2
|
+
import bs4
|
|
3
|
+
|
|
4
|
+
class Wordle:
|
|
5
|
+
@property
|
|
6
|
+
def answer(self):
|
|
7
|
+
"""Отримує відповідь на сьогоднішнє слово Wordle."""
|
|
8
|
+
link = "https://www.tomsguide.com/news/what-is-todays-wordle-answer"
|
|
9
|
+
req = requests.get(link)
|
|
10
|
+
soup = bs4.BeautifulSoup(req.text, "html.parser")
|
|
11
|
+
word = soup.find_all("strong")[7].text
|
|
12
|
+
word = word.upper().replace(".", "")
|
|
13
|
+
return word
|
craftapi/requests.py
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import requests
|
|
2
|
+
import bs4
|
|
3
|
+
from urllib.parse import quote as url
|
|
4
|
+
|
|
5
|
+
class UnknownMethod(Exception):
|
|
6
|
+
"""Виключення для невідомих HTTP методів."""
|
|
7
|
+
pass
|
|
8
|
+
|
|
9
|
+
class ReqTools:
|
|
10
|
+
def __init__(self):
|
|
11
|
+
pass
|
|
12
|
+
|
|
13
|
+
def whois(self, address):
|
|
14
|
+
address = url(address)
|
|
15
|
+
r = requests.get(f"https://who.is/whois-ip/ip-address/{address}")
|
|
16
|
+
soup = bs4.BeautifulSoup(r.text, "html.parser")
|
|
17
|
+
text = soup.find("pre").text
|
|
18
|
+
text_lines = text.splitlines()
|
|
19
|
+
toReturn = {}
|
|
20
|
+
for text in text_lines:
|
|
21
|
+
option = text[:15].replace(" ", "").replace(":", "").strip()
|
|
22
|
+
value = text[15:]
|
|
23
|
+
toReturn[option] = value
|
|
24
|
+
try:
|
|
25
|
+
del toReturn["Comment"]
|
|
26
|
+
except:
|
|
27
|
+
pass
|
|
28
|
+
return toReturn
|
|
29
|
+
|
|
30
|
+
def find_all_images_url(self, site_url, method="GET", **kwargs):
|
|
31
|
+
"""Знаходить всі URL-адреси зображень на вказаному сайті."""
|
|
32
|
+
if method.upper() == "GET":
|
|
33
|
+
req = requests.get(site_url, **kwargs)
|
|
34
|
+
elif method.upper() == "POST":
|
|
35
|
+
req = requests.post(site_url, **kwargs)
|
|
36
|
+
elif method.upper() == "PUT":
|
|
37
|
+
req = requests.put(site_url, **kwargs)
|
|
38
|
+
elif method.upper() == "DELETE":
|
|
39
|
+
req = requests.delete(site_url, **kwargs)
|
|
40
|
+
elif method.upper() == "PATCH":
|
|
41
|
+
req = requests.patch(site_url, **kwargs)
|
|
42
|
+
elif method.upper() == "OPTIONS":
|
|
43
|
+
req = requests.options(site_url, **kwargs)
|
|
44
|
+
elif method.upper() == "HEAD":
|
|
45
|
+
req = requests.head(site_url, **kwargs)
|
|
46
|
+
elif method.upper() == "TRACE":
|
|
47
|
+
req = requests.trace(site_url, **kwargs)
|
|
48
|
+
else:
|
|
49
|
+
raise UnknownMethod("Please input correct HTTP method.")
|
|
50
|
+
|
|
51
|
+
req.raise_for_status()
|
|
52
|
+
|
|
53
|
+
if method.upper() == "OPTIONS":
|
|
54
|
+
return req.headers
|
|
55
|
+
|
|
56
|
+
soup = bs4.BeautifulSoup(req.text, "html.parser")
|
|
57
|
+
images_urls = []
|
|
58
|
+
images = soup.find_all("img")
|
|
59
|
+
|
|
60
|
+
for img in images:
|
|
61
|
+
src = img.get("src")
|
|
62
|
+
if src:
|
|
63
|
+
if src.startswith("/"):
|
|
64
|
+
src = f"{site_url}{src}"
|
|
65
|
+
images_urls.append(src)
|
|
66
|
+
|
|
67
|
+
return images_urls
|
|
68
|
+
|
|
69
|
+
def get_page_title(self, site_url):
|
|
70
|
+
"""Отримує заголовок сторінки."""
|
|
71
|
+
req = requests.get(site_url)
|
|
72
|
+
req.raise_for_status()
|
|
73
|
+
soup = bs4.BeautifulSoup(req.text, "html.parser")
|
|
74
|
+
return soup.title.string.strip() if soup.title else "No title found"
|
|
75
|
+
|
|
76
|
+
def get_all_links(self, site_url):
|
|
77
|
+
"""Отримує всі посилання на сторінці."""
|
|
78
|
+
req = requests.get(site_url)
|
|
79
|
+
req.raise_for_status()
|
|
80
|
+
soup = bs4.BeautifulSoup(req.text, "html.parser")
|
|
81
|
+
links = []
|
|
82
|
+
for a in soup.find_all("a", href=True):
|
|
83
|
+
href = a["href"]
|
|
84
|
+
if href.startswith("/"):
|
|
85
|
+
href = f"{site_url}{href}"
|
|
86
|
+
links.append(href)
|
|
87
|
+
return links
|
|
88
|
+
|
|
89
|
+
def check_http_status(self, site_url):
|
|
90
|
+
"""Перевіряє HTTP статус-код для вказаного сайту."""
|
|
91
|
+
try:
|
|
92
|
+
req = requests.get(site_url)
|
|
93
|
+
return req.status_code
|
|
94
|
+
except requests.exceptions.RequestException as e:
|
|
95
|
+
return f"Error: {e}"
|
|
96
|
+
|
|
97
|
+
def extract_paragraphs(self, site_url):
|
|
98
|
+
"""Витягує всі абзаци з вказаного сайту."""
|
|
99
|
+
req = requests.get(site_url)
|
|
100
|
+
req.raise_for_status()
|
|
101
|
+
soup = bs4.BeautifulSoup(req.text, "html.parser")
|
|
102
|
+
paragraphs = [p.get_text() for p in soup.find_all("p")]
|
|
103
|
+
return paragraphs
|
|
104
|
+
|
|
105
|
+
def get_meta_tags(self, site_url):
|
|
106
|
+
"""Отримує всі мета-теги з веб-сторінки."""
|
|
107
|
+
req = requests.get(site_url)
|
|
108
|
+
req.raise_for_status()
|
|
109
|
+
soup = bs4.BeautifulSoup(req.text, "html.parser")
|
|
110
|
+
meta_tags = {meta.get("name"): meta.get("content") for meta in soup.find_all("meta") if meta.get("name")}
|
|
111
|
+
return meta_tags
|
|
112
|
+
|
|
113
|
+
def check_ssl_certificate(self, site_url):
|
|
114
|
+
"""Перевіряє SSL сертифікат для HTTPS-з'єднань."""
|
|
115
|
+
try:
|
|
116
|
+
req = requests.get(site_url)
|
|
117
|
+
if req.url.startswith("https"):
|
|
118
|
+
return "SSL certificate is valid."
|
|
119
|
+
else:
|
|
120
|
+
return "SSL certificate is not valid."
|
|
121
|
+
except requests.exceptions.SSLError as e:
|
|
122
|
+
return f"SSL error: {e}"
|
|
123
|
+
except requests.exceptions.RequestException as e:
|
|
124
|
+
return f"Error: {e}"
|
|
125
|
+
|
|
126
|
+
def save_html_to_file(self, site_url, filename="output.html"):
|
|
127
|
+
"""Зберігає HTML-код сторінки у файл."""
|
|
128
|
+
req = requests.get(site_url)
|
|
129
|
+
req.raise_for_status()
|
|
130
|
+
with open(filename, "w", encoding="utf-8") as file:
|
|
131
|
+
file.write(req.text)
|
|
132
|
+
return f"HTML content saved to {filename}"
|
|
133
|
+
|
|
134
|
+
def extract_list_items(self, site_url):
|
|
135
|
+
"""Витягує всі елементи списку з веб-сторінки."""
|
|
136
|
+
req = requests.get(site_url)
|
|
137
|
+
req.raise_for_status()
|
|
138
|
+
soup = bs4.BeautifulSoup(req.text, "html.parser")
|
|
139
|
+
list_items = [li.get_text() for li in soup.find_all("li")]
|
|
140
|
+
return list_items
|
|
141
|
+
|
|
142
|
+
def get_first_h1(self, site_url):
|
|
143
|
+
"""Отримує перший заголовок <h1> з веб-сторінки."""
|
|
144
|
+
req = requests.get(site_url)
|
|
145
|
+
req.raise_for_status()
|
|
146
|
+
soup = bs4.BeautifulSoup(req.text, "html.parser")
|
|
147
|
+
h1 = soup.find("h1")
|
|
148
|
+
return h1.get_text().strip() if h1 else "No <h1> tag found"
|
|
149
|
+
|
|
150
|
+
def get_all_scripts(self, site_url):
|
|
151
|
+
"""Отримує всі скрипти з веб-сторінки."""
|
|
152
|
+
req = requests.get(site_url)
|
|
153
|
+
req.raise_for_status()
|
|
154
|
+
soup = bs4.BeautifulSoup(req.text, "html.parser")
|
|
155
|
+
scripts = [script.get("src") for script in soup.find_all("script") if script.get("src")]
|
|
156
|
+
return scripts
|
|
157
|
+
|
|
158
|
+
def extract_form_data(self, site_url):
|
|
159
|
+
"""Витягує дані з форм на веб-сторінці."""
|
|
160
|
+
req = requests.get(site_url)
|
|
161
|
+
req.raise_for_status()
|
|
162
|
+
soup = bs4.BeautifulSoup(req.text, "html.parser")
|
|
163
|
+
forms = []
|
|
164
|
+
for form in soup.find_all("form"):
|
|
165
|
+
action = form.get("action")
|
|
166
|
+
method = form.get("method", "GET").upper()
|
|
167
|
+
inputs = {input.get("name"): input.get("type") for input in form.find_all("input")}
|
|
168
|
+
forms.append({"action": action, "method": method, "inputs": inputs})
|
|
169
|
+
return forms
|
|
170
|
+
|
|
171
|
+
def get_css_links(self, site_url):
|
|
172
|
+
"""Отримує всі посилання на CSS файли з веб-сторінки."""
|
|
173
|
+
req = requests.get(site_url)
|
|
174
|
+
req.raise_for_status()
|
|
175
|
+
soup = bs4.BeautifulSoup(req.text, "html.parser")
|
|
176
|
+
css_links = [link.get("href") for link in soup.find_all("link", rel="stylesheet")]
|
|
177
|
+
return css_links
|
craftapi/vartools.py
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
class VarTools:
|
|
2
|
+
def __init__(self, varlist):
|
|
3
|
+
self.varlist = varlist
|
|
4
|
+
|
|
5
|
+
def get_var_value(self, var):
|
|
6
|
+
return self.varlist[var]
|
|
7
|
+
|
|
8
|
+
def clean_type(self, var):
|
|
9
|
+
var_type = str(type(self.varlist[var]))
|
|
10
|
+
result = var_type.split("'")[1]
|
|
11
|
+
return result
|
|
12
|
+
|
|
13
|
+
def format_time(self, seconds):
|
|
14
|
+
endings = {
|
|
15
|
+
"секунда": ["секунда", "секунди", "секунд"],
|
|
16
|
+
"хвилина": ["хвилина", "хвилини", "хвилин"],
|
|
17
|
+
"година": ["година", "години", "годин"],
|
|
18
|
+
"день": ["день", "дня", "днів"],
|
|
19
|
+
"тиждень": ["тиждень", "тижня", "тижнів"],
|
|
20
|
+
"місяць": ["місяць", "місяця", "місяців"],
|
|
21
|
+
"рік": ["рік", "роки", "років"]
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
units = [
|
|
25
|
+
("рік", 365 * 24 * 60 * 60),
|
|
26
|
+
("місяць", 30 * 24 * 60 * 60),
|
|
27
|
+
("тиждень", 7 * 24 * 60 * 60),
|
|
28
|
+
("день", 24 * 60 * 60),
|
|
29
|
+
("година", 60 * 60),
|
|
30
|
+
("хвилина", 60),
|
|
31
|
+
("секунда", 1)
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
for unit, duration in units:
|
|
35
|
+
if seconds >= duration:
|
|
36
|
+
number = seconds // duration
|
|
37
|
+
if 11 <= number % 100 <= 19:
|
|
38
|
+
form = endings[unit][2]
|
|
39
|
+
else:
|
|
40
|
+
last_digit = number % 10
|
|
41
|
+
if last_digit == 1:
|
|
42
|
+
form = endings[unit][0]
|
|
43
|
+
elif 2 <= last_digit <= 4:
|
|
44
|
+
form = endings[unit][1]
|
|
45
|
+
else:
|
|
46
|
+
form = endings[unit][2]
|
|
47
|
+
return f"{number} {form}"
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: craftllc-api
|
|
3
|
+
Version: 0.1.2
|
|
4
|
+
Summary: CraftLLC API
|
|
5
|
+
Author-email: CraftLLC <craftllcompany@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Keywords: api,craftapi,craftllc,craftllc-api
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
Requires-Dist: requests
|
|
13
|
+
Requires-Dist: bs4
|
|
14
|
+
|
|
15
|
+
# CraftAPI
|
|
16
|
+
|
|
17
|
+
CraftAPI is a simple-to-use Python library providing a set of tools for interacting with websites and retrieving various types of information, as well as utility functions for variable manipulation and time formatting.
|
|
18
|
+
|
|
19
|
+
## Installation
|
|
20
|
+
|
|
21
|
+
Install the package using pip:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
pip install craftapi
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Usage
|
|
28
|
+
|
|
29
|
+
### `ReqTools` Class
|
|
30
|
+
|
|
31
|
+
This class provides methods for web scraping and making HTTP requests.
|
|
32
|
+
|
|
33
|
+
```python
|
|
34
|
+
from craftapi import ReqTools, UnknownMethod
|
|
35
|
+
|
|
36
|
+
req_tools = ReqTools()
|
|
37
|
+
|
|
38
|
+
# Get page title
|
|
39
|
+
title = req_tools.get_page_title("https://www.python.org/")
|
|
40
|
+
print(f"Page Title: {title}")
|
|
41
|
+
|
|
42
|
+
# Get all links on a page
|
|
43
|
+
links = req_tools.get_all_links("https://www.python.org/")
|
|
44
|
+
print("All Links:")
|
|
45
|
+
for link in links[:5]: # Print first 5 links
|
|
46
|
+
print(link)
|
|
47
|
+
|
|
48
|
+
# Check HTTP status code
|
|
49
|
+
status_code = req_tools.check_http_status("https://www.python.org/")
|
|
50
|
+
print(f"HTTP Status Code: {status_code}")
|
|
51
|
+
|
|
52
|
+
# Extract all paragraphs
|
|
53
|
+
paragraphs = req_tools.extract_paragraphs("https://www.python.org/")
|
|
54
|
+
print("First Paragraph:")
|
|
55
|
+
if paragraphs:
|
|
56
|
+
print(paragraphs[0])
|
|
57
|
+
|
|
58
|
+
# Get meta tags
|
|
59
|
+
meta_tags = req_tools.get_meta_tags("https://www.python.org/")
|
|
60
|
+
print("Meta Tags:")
|
|
61
|
+
for name, content in meta_tags.items():
|
|
62
|
+
print(f" {name}: {content}")
|
|
63
|
+
|
|
64
|
+
# Check SSL certificate (basic check)
|
|
65
|
+
ssl_status = req_tools.check_ssl_certificate("https://www.google.com/")
|
|
66
|
+
print(f"SSL Status: {ssl_status}")
|
|
67
|
+
|
|
68
|
+
# Save HTML content to a file
|
|
69
|
+
save_status = req_tools.save_html_to_file("https://www.python.org/", "python_org.html")
|
|
70
|
+
print(save_status)
|
|
71
|
+
|
|
72
|
+
# Extract list items
|
|
73
|
+
list_items = req_tools.extract_list_items("https://www.python.org/")
|
|
74
|
+
print("First List Item:")
|
|
75
|
+
if list_items:
|
|
76
|
+
print(list_items[0])
|
|
77
|
+
|
|
78
|
+
# Get the first H1 tag
|
|
79
|
+
h1_tag = req_tools.get_first_h1("https://www.python.org/")
|
|
80
|
+
print(f"First H1 Tag: {h1_tag}")
|
|
81
|
+
|
|
82
|
+
# Get all script URLs
|
|
83
|
+
scripts = req_tools.get_all_scripts("https://www.python.org/")
|
|
84
|
+
print("First Script URL:")
|
|
85
|
+
if scripts:
|
|
86
|
+
print(scripts[0])
|
|
87
|
+
|
|
88
|
+
# Extract form data
|
|
89
|
+
form_data = req_tools.extract_form_data("https://www.w3schools.com/html/html_forms.asp")
|
|
90
|
+
print("Form Data (first form):")
|
|
91
|
+
if form_data:
|
|
92
|
+
print(form_data[0])
|
|
93
|
+
|
|
94
|
+
# Get CSS links
|
|
95
|
+
css_links = req_tools.get_css_links("https://www.python.org/")
|
|
96
|
+
print("First CSS Link:")
|
|
97
|
+
if css_links:
|
|
98
|
+
print(css_links[0])
|
|
99
|
+
|
|
100
|
+
# Find all image URLs
|
|
101
|
+
image_urls = req_tools.find_all_images_url("https://www.python.org/")
|
|
102
|
+
print("First Image URL:")
|
|
103
|
+
if image_urls:
|
|
104
|
+
print(image_urls[0])
|
|
105
|
+
|
|
106
|
+
# WHOIS lookup
|
|
107
|
+
whois_info = req_tools.whois("8.8.8.8")
|
|
108
|
+
print("WHOIS Info for 8.8.8.8:")
|
|
109
|
+
for key, value in whois_info.items():
|
|
110
|
+
print(f" {key}: {value}")
|
|
111
|
+
|
|
112
|
+
# Example of UnknownMethod exception
|
|
113
|
+
try:
|
|
114
|
+
req_tools.find_all_images_url("https://example.com", method="INVALID")
|
|
115
|
+
except UnknownMethod as e:
|
|
116
|
+
print(f"Caught expected exception: {e}")
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### `Wordle` Class (from `nytgames` module)
|
|
120
|
+
|
|
121
|
+
This class provides methods related to New York Times games, specifically Wordle.
|
|
122
|
+
|
|
123
|
+
```python
|
|
124
|
+
from craftapi import Wordle
|
|
125
|
+
|
|
126
|
+
wordle_game = Wordle()
|
|
127
|
+
|
|
128
|
+
# Get today's Wordle answer
|
|
129
|
+
wordle_answer = wordle_game.answer
|
|
130
|
+
print(f"Today's Wordle Answer: {wordle_answer}")
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### `VarTools` Class
|
|
134
|
+
|
|
135
|
+
This class provides utility methods for variable inspection and time formatting.
|
|
136
|
+
|
|
137
|
+
```python
|
|
138
|
+
from craftapi import VarTools
|
|
139
|
+
|
|
140
|
+
my_vars = {"name": "CraftAPI", "version": 0.1, "is_active": True}
|
|
141
|
+
var_tools = VarTools(my_vars)
|
|
142
|
+
|
|
143
|
+
# Get variable value
|
|
144
|
+
name_value = var_tools.get_var_value("name")
|
|
145
|
+
print(f"Value of 'name': {name_value}")
|
|
146
|
+
|
|
147
|
+
# Clean variable type
|
|
148
|
+
name_type = var_tools.clean_type("name")
|
|
149
|
+
version_type = var_tools.clean_type("version")
|
|
150
|
+
print(f"Type of 'name': {name_type}")
|
|
151
|
+
print(f"Type of 'version': {version_type}")
|
|
152
|
+
|
|
153
|
+
# Format time in seconds
|
|
154
|
+
formatted_time_seconds = var_tools.format_time(30)
|
|
155
|
+
formatted_time_minutes = var_tools.format_time(150)
|
|
156
|
+
formatted_time_hours = var_tools.format_time(7200)
|
|
157
|
+
formatted_time_days = var_tools.format_time(90000)
|
|
158
|
+
print(f"30 seconds: {formatted_time_seconds}")
|
|
159
|
+
print(f"150 seconds: {formatted_time_minutes}")
|
|
160
|
+
print(f"7200 seconds: {formatted_time_hours}")
|
|
161
|
+
print(f"90000 seconds: {formatted_time_days}")
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## License
|
|
165
|
+
|
|
166
|
+
This project is licensed under the MIT License.
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
craftapi/__init__.py,sha256=4xOHinhyYJ8_TH-8S9yUd7sMZE0higCzOSylcx1qn04,168
|
|
2
|
+
craftapi/nytgames.py,sha256=MbQxdSRaJzmq2eVHnkMnuRYiw-fS7waCrvgbRZOuJuA,453
|
|
3
|
+
craftapi/requests.py,sha256=XTSefwlUrMpD5tgXdVwaR7knA8rH9zCqRTc3PzFX63I,7066
|
|
4
|
+
craftapi/vartools.py,sha256=GQcdpArp2ljDyByviTwfdPejigCXn9CqEquiIyQGYaI,1783
|
|
5
|
+
craftllc_api-0.1.2.dist-info/METADATA,sha256=SfXWtGH_epvKjzl7AZrbcyo2PxLHrpolXOht4-EOY5k,4535
|
|
6
|
+
craftllc_api-0.1.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
7
|
+
craftllc_api-0.1.2.dist-info/top_level.txt,sha256=-FJLUCUwjYRmLTITEExlxuanZxZ98cJawflmrfEP2qY,9
|
|
8
|
+
craftllc_api-0.1.2.dist-info/RECORD,,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
craftapi
|