Skip to content

Commit 643ee10

Browse files
authored
Merge pull request #138 from AndreiDrang/main
Upd docs
2 parents 5bf9495 + 991e41a commit 643ee10

15 files changed

Lines changed: 330 additions & 13 deletions

.github/workflows/build_sphinx.yml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
name: Sphinx docs
2+
3+
on:
4+
push:
5+
branches: [ "main" ]
6+
paths:
7+
- '.github/workflows/build_sphinx.yml'
8+
- 'src/**'
9+
- 'docs/**'
10+
- 'files/**'
11+
12+
jobs:
13+
docs:
14+
runs-on: ubuntu-latest
15+
16+
steps:
17+
- uses: actions/checkout@v4
18+
- name: Set up Python 3.11
19+
uses: actions/setup-python@v5
20+
with:
21+
python-version: 3.11.6
22+
23+
- name: Build docs requirements
24+
run: pip install -r docs/requirements.txt
25+
26+
- name: Build docs
27+
run: make doc

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
[![Downloads](https://static.pepy.tech/badge/python3-capsolver/month)](https://pepy.tech/project/python3-capsolver)
1010
[![Static Badge](https://img.shields.io/badge/docs-Sphinx-green?label=Documentation&labelColor=gray)](https://andreidrang.github.io/python3-capsolver/)
1111

12+
[![Maintainability](https://api.codeclimate.com/v1/badges/3c30167b5fb37a0775ea/maintainability)](https://codeclimate.com/github/AndreiDrang/python3-capsolver/maintainability)
1213
[![Codacy Badge](https://app.codacy.com/project/badge/Grade/323d4eda0fe1477bbea8fe8902b9e97e)](https://www.codacy.com/gh/AndreiDrang/python3-capsolver/dashboard?utm_source=github.com&utm_medium=referral&utm_content=AndreiDrang/python3-capsolver&utm_campaign=Badge_Grade)
1314
[![codecov](https://codecov.io/gh/AndreiDrang/python3-capsolver/branch/main/graph/badge.svg?token=2L4VVIF4G8)](https://codecov.io/gh/AndreiDrang/python3-capsolver)
1415

src/python3_capsolver/cloudflare.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,42 @@ class Cloudflare(CaptchaParams):
7979
}
8080
}
8181
82+
>>> import asyncio
83+
>>> from python3_capsolver.cloudflare import Cloudflare
84+
>>> from python3_capsolver.core.enum import CaptchaTypeEnm
85+
>>> asyncio.run(Cloudflare(api_key="CAI-12345....",
86+
... captcha_type=CaptchaTypeEnm.AntiCloudflareTask)
87+
... .aio_captcha_handler(task_payload={
88+
... "websiteURL": "https://www.yourwebsite.com",
89+
... "proxy": "ip:port:user:pass",
90+
... }))
91+
{
92+
"errorId":0,
93+
"errorCode":"None",
94+
"errorDescription":"None",
95+
"taskId":"db0a3153-621d-4f5e-8554-a1c032597ee7",
96+
"status":"ready",
97+
"solution":{
98+
"cookies": "cf_clearance=_VPxxxx",
99+
"headers": {
100+
"sec-ch-ua": "\"Chromium\";v=\"130\", \"Google Chrome\";v=\"130\", \"Not?A_Brand\";v=\"99\"",
101+
"sec-ch-ua-platform": "\"Windows\"",
102+
"accept": "text/html,axxxx",
103+
"User-Agent": "Mozilla/5.0xxxx",
104+
"sec-ch-ua-mobile": "?0",
105+
"sec-fetch-user": "?1",
106+
"referer": "https://www.yourwebsite.com",
107+
"Sec-Fetch-Dest": "document",
108+
"Sec-Fetch-Mode": "navigate",
109+
"Sec-Fetch-Site": "same-origin",
110+
"accept-language": "en",
111+
},
112+
"page_url": "https://www.yourwebsite.com",
113+
"proxy": "your proxyxxxx",
114+
"token": "_VPCTZXP5bhinxxxx"
115+
}
116+
}
117+
82118
Notes:
83119
https://docs.capsolver.com/en/guide/captcha/cloudflare_turnstile/
84120

src/python3_capsolver/datadome_slider.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,28 @@ class DatadomeSlider(CaptchaParams):
3939
}
4040
}
4141
42+
>>> import asyncio
43+
>>> from python3_capsolver.datadome_slider import DatadomeSlider
44+
>>> from python3_capsolver.core.enum import CaptchaTypeEnm
45+
>>> asyncio.run(DatadomeSlider(api_key="CAI-12345....",
46+
... captcha_type=CaptchaTypeEnm.DatadomeSliderTask)
47+
... .aio_captcha_handler(task_payload={
48+
... "captchaUrl": "https://geo.captchaxxxxxx",
49+
... "userAgent": "Mozilla/5.0 xxxx",
50+
... "proxy": "0.0.0.0:334:user:pass"
51+
... }))
52+
{
53+
"errorId":0,
54+
"errorCode":"None",
55+
"errorDescription":"None",
56+
"taskId":"db0a3153-621d-4f5e-8554-a1c032597ee7",
57+
"status":"ready",
58+
"solution":{
59+
"userAgent": "Mozilla/5.0 xxxx",
60+
"cookie": "datadome=yzj_BK..xxxx"
61+
}
62+
}
63+
4264
Notes:
4365
https://docs.capsolver.com/en/guide/captcha/datadome/
4466
"""

src/python3_capsolver/friendly_captcha.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,42 @@ class FriendlyCaptcha(CaptchaParams):
5555
}
5656
}
5757
58+
>>> import asyncio
59+
>>> from python3_capsolver.core.enum import CaptchaTypeEnm
60+
>>> from python3_capsolver.friendly_captcha import FriendlyCaptcha
61+
>>> asyncio.run(FriendlyCaptcha(api_key="CAP-XXXXX",
62+
... captcha_type=CaptchaTypeEnm.FriendlyCaptchaTaskProxyless,
63+
... ).aio_captcha_handler(task_payload={
64+
... "websiteURL": "https://www.yourwebsite.com",
65+
... "proxy": "ip:port:user:pass"
66+
... }))
67+
{
68+
"errorId":0,
69+
"errorCode":"None",
70+
"errorDescription":"None",
71+
"taskId":"db0a3153-621d-4f5e-8554-a1c032597ee7",
72+
"status":"ready",
73+
"solution":{
74+
"cookies": "cf_clearance=_VPxxxx",
75+
"headers": {
76+
"sec-ch-ua": "\"Chromium\";v=\"130\", \"Google Chrome\";v=\"130\", \"Not?A_Brand\";v=\"99\"",
77+
"sec-ch-ua-platform": "\"Windows\"",
78+
"accept": "text/html,axxxx",
79+
"User-Agent": "Mozilla/5.0xxxx",
80+
"sec-ch-ua-mobile": "?0",
81+
"sec-fetch-user": "?1",
82+
"referer": "https://www.yourwebsite.com",
83+
"Sec-Fetch-Dest": "document",
84+
"Sec-Fetch-Mode": "navigate",
85+
"Sec-Fetch-Site": "same-origin",
86+
"accept-language": "en",
87+
},
88+
"page_url": "https://www.yourwebsite.com",
89+
"proxy": "your proxyxxxx",
90+
"token": "_VPCTZXP5bhinxxxx"
91+
}
92+
}
93+
5894
Notes:
5995
https://docs.capsolver.com/en/guide/captcha/FriendlyCaptcha/
6096
"""

src/python3_capsolver/mt_captcha.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,23 @@ class MtCaptcha(CaptchaParams):
3838
}
3939
}
4040
41+
>>> import asyncio
42+
>>> from python3_capsolver.mt_captcha import MtCaptcha
43+
>>> from python3_capsolver.core.enum import CaptchaTypeEnm
44+
>>> asyncio.run(MtCaptcha(api_key="CAI-12345....",
45+
... captcha_type=CaptchaTypeEnm.MtCaptchaTaskProxyLess)
46+
... .aio_captcha_handler(task_payload={"websiteURL": "some-url"}))
47+
{
48+
"errorId":0,
49+
"errorCode":"None",
50+
"errorDescription":"None",
51+
"taskId":"db0a3153-621d-4f5e-8554-a1c032597ee7",
52+
"status":"ready",
53+
"solution":{
54+
"token": ""
55+
}
56+
}
57+
4158
Notes:
4259
https://docs.capsolver.com/en/guide/captcha/MtCaptcha/
4360
"""

src/python3_capsolver/yandex.py

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ class YandexCaptcha(CaptchaParams):
1212
1313
Args:
1414
api_key: Capsolver API key
15-
captcha_type: Captcha type name, like ``FriendlyCaptchaTaskProxyless`` and etc.
15+
captcha_type: Captcha type name, like ``YandexCaptchaTaskProxyLess`` and etc.
1616
kwargs: additional params for client, like captcha waiting time
1717
available keys:
1818
- sleep_time: int - captcha solution waintig time in sec
@@ -39,14 +39,34 @@ class YandexCaptcha(CaptchaParams):
3939
}
4040
}
4141
42+
>>> import asyncio
43+
>>> from python3_capsolver.core.enum import CaptchaTypeEnm
44+
>>> from python3_capsolver.yandex import YandexCaptcha
45+
>>> asyncio.run(YandexCaptcha(api_key="CAP-XXXXX",
46+
... captcha_type=CaptchaTypeEnm.YandexCaptchaTaskProxyLess,
47+
... ).aio_captcha_handler(task_payload={
48+
... "websiteURL": "https://www.yourwebsite.com",
49+
... "websiteKey": "ysc1_bFdbbET5WBnPTvoE5jTXxxxx"
50+
... }))
51+
{
52+
"errorId":0,
53+
"errorCode":"None",
54+
"errorDescription":"None",
55+
"taskId":"db0a3153-621d-4f5e-8554-a1c032597ee7",
56+
"status":"ready",
57+
"solution":{
58+
"token": "dD0xNzMzMjc0MjkzO2k9Nxxxx"
59+
}
60+
}
61+
4262
Notes:
43-
https://docs.capsolver.com/en/guide/captcha/FriendlyCaptcha/
63+
https://docs.capsolver.com/en/guide/captcha/YandexCaptcha/
4464
"""
4565

4666
def __init__(
4767
self,
4868
api_key: str,
49-
captcha_type: Union[CaptchaTypeEnm, str] = CaptchaTypeEnm.FriendlyCaptchaTaskProxyless,
69+
captcha_type: Union[CaptchaTypeEnm, str] = CaptchaTypeEnm.YandexCaptchaTaskProxyLess,
5070
**kwargs,
5171
):
5272

tests/files/fun_class.png

-103 KB
Binary file not shown.

tests/files/hcap_select.png

-140 KB
Binary file not shown.

tests/test_cloudflare.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import pytest
2+
3+
from tests.conftest import BaseTest
4+
from python3_capsolver.core.enum import CaptchaTypeEnm
5+
from python3_capsolver.cloudflare import Cloudflare
6+
7+
8+
class TestCloudflare(BaseTest):
9+
captcha_types = (
10+
CaptchaTypeEnm.AntiCloudflareTask,
11+
CaptchaTypeEnm.AntiTurnstileTaskProxyLess,
12+
)
13+
14+
@pytest.mark.parametrize("captcha_type", captcha_types)
15+
def test_captcha_handler_exist(self, captcha_type):
16+
instance = Cloudflare(api_key=self.get_random_string(36), captcha_type=captcha_type)
17+
assert "captcha_handler" in instance.__dir__()
18+
assert "aio_captcha_handler" in instance.__dir__()
19+
20+
@pytest.mark.parametrize("captcha_type", captcha_types)
21+
def test_api_key_err(self, captcha_type):
22+
result = Cloudflare(api_key=self.get_random_string(36), captcha_type=captcha_type).captcha_handler(
23+
task_payload={"some": "data"}
24+
)
25+
assert result["errorId"] == 1
26+
assert result["errorCode"] in ("ERROR_KEY_DENIED_ACCESS", "ERROR_INVALID_TASK_DATA")
27+
assert result["solution"] is None
28+
29+
@pytest.mark.parametrize("captcha_type", captcha_types)
30+
async def test_aio_api_key_err(self, captcha_type):
31+
result = await Cloudflare(api_key=self.get_random_string(36), captcha_type=captcha_type).aio_captcha_handler(
32+
task_payload={"some": "data"}
33+
)
34+
assert result["errorId"] == 1
35+
assert result["errorCode"] in ("ERROR_KEY_DENIED_ACCESS", "ERROR_INVALID_TASK_DATA")
36+
assert result["solution"] is None

0 commit comments

Comments
 (0)