Skip to content

Commit

Permalink
Merge branch 'Python-2.0.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
Matthew17-21 committed Dec 11, 2022
2 parents fb60b6e + 3da04a9 commit a1ccd5a
Show file tree
Hide file tree
Showing 12 changed files with 806 additions and 409 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
__pycache__/
build/
dist/
*.egg*/
186 changes: 118 additions & 68 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,104 +13,154 @@ pip3 install captchatools
pip3 install -U captchatools
```
# How to use
### Getting reCAPTCHA Tokens
### Basic usage
```python
import captchatools
solver = captchatools.captcha_harvesters(solving_site="capmonster", api_key="YOUR API KEY", sitekey="6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-", captcha_url="https://www.google.com/recaptcha/api2/demo")
solver = captchatools.new_harvester(solving_site="capmonster", api_key="YOUR API KEY", sitekey="6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-", captcha_url="https://www.google.com/recaptcha/api2/demo")
captcha_answer = solver.get_token()
```
or
```python
from captchatools import captcha_harvesters, exceptions
solver = captcha_harvesters(solving_site=1, api_key="YOUR API KEY", sitekey="6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-", captcha_url="https://www.google.com/recaptcha/api2/demo")
from captchatools import new_harvester
solver = new_harvester(solving_site=1, api_key="YOUR API KEY", sitekey="6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-", captcha_url="https://www.google.com/recaptcha/api2/demo")
captcha_answer = solver.get_token()
```

### Getting Normal Captcha Tokens
```python
import captchatools
solver = captchatools.captcha_harvesters(solving_site=2, captcha_type="normal", api_key="YOUR API KEY HERE")
url = "https://www.scienceabc.com/wp-content/uploads/ext-www.scienceabc.com/wp-content/uploads/2016/07/Captcha-ex.jpg-.jpg"
text_cap_answer = solver.get_normal(url)
```

### new_harvester() Parameters:
| Parameter | Required | Type | Default | Description|
| :-------------: |:-------------:| :-----:| :-----:| :-----:|
| api_key | true | String| -| The API Key for the captcha solving site|
| solving_site| true| String (name of site) or int (site ID) | "capmonster"| Captcha solving site|
| solving_site| true| String (name of site) or int (site ID) | "capmonster"| The captcha solving site that will be used. Refer to [the site IDs](https://github.com/Matthew17-21/Captcha-Tools/tree/main/captchatools-go#site-specific-support)|
| sitekey| true | String | - | Sitekey from the site where captcha is loaded|
| captcha_url | true| String | - | URL where the captcha is located|
| captcha_type| false| String | "v2" | Type of captcha you are solving. Either captcha `v2`, `v3` or `hcaptcha` (`hcap` works aswell)|
| captcha_type| false| String | "v2" | Type of captcha you are solving. Either captcha `image`, `v2`, `v3` or `hcaptcha` (`hcap` works aswell)|
| invisible_captcha| false | bool | false | If the captcha is invisible or not.<br />__This param is only required when solving invisible captchas__|
| min_score | false | double |0.7 | Minimum score for v3 captchas.<br />__This param is only required when solving V3 and it needs a higher / lower score__|
| action | false | String | "verify" | Action that is associated with the V3 captcha.<br />__This param is only required when solving V3 captchas__|
| soft_id | false | int | 4782723 |2captcha Developer ID. <br /> Developers get 10% of spendings of their software users. |
| soft_id | false | int | - |2captcha Developer ID. <br /> Developers get 10% of spendings of their software users. |
### get_token() Parameters:
| Field | Required | Type | Description|
| :-------------: |:-------------:| :-----:| :-----:|
| b64_img | false | string | Base64 encoded captcha image<br />__This param is only required when solving image captchas__|
| proxy| false | string | Proxy to be used to solve captchas.<br />This will make the captcha be solved from the proxy ip<br /><br />Format: `ip:port:user:pass` |
| proxy_type | false | string | Type of the proxy being used. Options are:<br /> `HTTP`, `HTTPS`, `SOCKS4`, `SOCKS5`|
| user_agent | false | string | UserAgent that will be passed to the service and used to solve the captcha |
### Examples
##### Example - V2 Captcha / Basic usage
```python
from captchatools import new_harvester

def main():
harvester = new_harvester(
api_key="CHANGE THIS",
solving_site="capsolver",
captcha_type="v2",
sitekey="6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-",
captcha_url="https://www.google.com/recaptcha/api2/demo"
)
answer = harvester.get_token()
```
##### Example - V3 Captcha
```python
from captchatools import new_harvester

def main():
harvester = new_harvester(

api_key="CHANGE THIS",
solving_site="capsolver",

captcha_type="v3",
sitekey="6LcR_okUAAAAAPYrPe-HK_0RULO1aZM15ENyM-Mf",
captcha_url="https://antcpt.com/score_detector/",
action="homepage",
min_score=0.7
)
token = harvester.get_token()
```
##### Example - Image captcha
```python
from captchatools import new_harvester

def main():
harvester = new_harvester(
api_key="CHANGE THIS",
solving_site="capsolver",
captcha_type="image",
)
token = harvester.get_token(b64_img="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")
```
##### Example - Additional captcha data
```python
from captchatools import new_harvester

def main():
harvester = new_harvester(
api_key="CHANGE THIS",
solving_site="capsolver",
captcha_type="v2",
sitekey="6Le-wvkSAAAAAPBMRTvw0Q4Muexq9bi0DJwx_mJ-",
captcha_url="https://www.google.com/recaptcha/api2/demo"
)

token = harvester.get_token(
proxy="ip:port:user:pass",
proxy_type="http",
user_agent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"
)
```

# Supported Sites
- **[Capmonster](https://capmonster.cloud/)**
- **[2Captcha](https://www.2captcha.com/)**
- **[Anticaptcha](https://www.anti-captcha.com/)**
- **[Capsolver](https://www.capsolver.com/)**

### Site-Specific Support:
| Site | Site ID |Captcha Types Supported | Task Types Supported|
| :-------------: |:-------------:| :-----:| :-----:|
| Capmonster | captchatools.CapmonsterSite| Image captchas,<br/> Recaptcha V2,<br />Recaptcha V3,<br />HCaptcha | ImageToTextTask,<br/>NoCaptchaTask,<br/> NoCaptchaTaskProxyless,<br/> RecaptchaV3TaskProxyless,<br />HCaptchaTaskProxyless |
| Anticaptcha | captchatools.AnticaptchaSite| Image captchas,<br/> Recaptcha V2,<br />Recaptcha V3,<br />HCaptcha | ImageToTextTask,<br/> RecaptchaV2Task<br/> RecaptchaV2TaskProxyless,<br />RecaptchaV3TaskProxyless,<br />HCaptchaTaskProxyless |
| 2Captcha | captchatools.TwoCaptchaSite| Image captchas,<br/> Recaptcha V2,<br />Recaptcha V3,<br />HCaptcha | - |

##### Site-Specific Support:
| Site |Site ID| Captcha Types Supported | Task Types Supported|
| :-------------: |:-------------:|:-------------:| :-----:|
| Capmonster |1| Recaptcha V2,<br />Recaptcha V3,<br />HCaptcha | RecaptchaV2TaskProxyless,<br />RecaptchaV3TaskProxyless,<br />HCaptchaTaskProxyless, <br />ImageToTextTask<br />|
| Anticaptcha |2| Recaptcha V2,<br />Recaptcha V3,<br />HCaptcha | RecaptchaV2TaskProxyless,<br />RecaptchaV3TaskProxyless,<br />HCaptchaTaskProxyless <br />ImageToTextTask<br />|
| 2Captcha |3| Recaptcha V2,<br />Recaptcha V3,<br />HCaptcha | - |


# Recommendations
1. For 2Captcha, don't run more than 60 tasks per API key.
2. Handle exceptions appropriately.
* If a `NoBalanceException` is thrown, tasks should stop. Some sites will temporarily ban IP's if constant requests come in.
2. Handle errors appropriately.
* If a `ErrNoBalance` is thrown, tasks should stop. Some sites will temporarily ban IP's if constant requests come in.

# Exceptions
| Exception | Raised |
# Errors
| Errors | Returned When |
| :--------:| :-----:|
| `NoBalanceException` | Balance is below 0 for captcha solving site|
| `WrongAPIKeyExceptionException` | Incorrect API Key for captcha solving site|
| `WrongSitekeyException` | Incorrect sitekey |
| `NoHarvesterException` | When the user did not / incorrectly chose a captcha harvester. Refer to the [guide](https://github.com/Matthew17-21/Captcha-Tools#how-to-use) |
| `CaptchaIMGTooBig` | The size of the captcha image is too big for the solving service. |
| `FailedToGetCapIMG`| Failed to get the captcha image from the URL. <br />**Tries 3 times before getting thrown.**<br />
| `ErrNoBalance` | Balance is below 0 for captcha solving site|
| `ErrWrongAPIKey` | Incorrect API Key for captcha solving site|
| `ErrWrongSitekey` | Incorrect sitekey |
| `ErrIncorrectCapType` | Incorrectly chose a captcha type. When initializing a new harvester. Refer to [the captcha types](https://github.com/Matthew17-21/Captcha-Tools/tree/main/captchatools-go#config-struct-fields) |
| `ErrNoHarvester` | When the user did not / incorrectly chose a captcha harvester. Refer to the ["how to use" guide](https://github.com/Matthew17-21/Captcha-Tools/tree/main/captchatools-go#how-to-use) |

##### Error Handling
```python
from captchatools import captcha_harvesters, exceptions as captchaExceptions
try:
...
except captchaExceptions.NoBalanceException:
print("No balance.")
```
or
```python
import captchatools
try:
...
except captchatools.NoBalanceException:
print("No balance.")
from captchatools import new_harvester, exceptions as captchaExceptions,

def main():
try:
harvester = new_harvester()
token harvester.get_token()
except captchaExceptions.NoHarvesterException:
print("I need to set my captcha harvester!")
```


# TO DO
1. [] Document code better
2. [] 2Captcha
* [] Clean up code
* [] Proxy support
* [] Cookie support
* [] User Agent Support
* [] Different type of captchas
3. [] Anticaptcha
* [] Clean up code
* [] Proxy support
* [] Cookie support
* [] User Agent Support
* [] Different type of captchas
4. [] Capmonster
* [] Clean up code
* [] Proxy support
* [] Cookie support
* [] User Agent Support
* [] Different type of captchas
5. [] Add DeathByCaptcha
6. [] Release in Go
7. [] Allow for refunds

# Changelog
### 1.3.0
##### What's new
1. Get Balance Support
2. Proxy Support
3. User Agent Support
4. Text image captcha support
5. Better internal handling
6. Capsolver support

##### Important Changes
* It is recommend to use the `new_harvester` function rather than the old `captcha_harvesters`
76 changes: 72 additions & 4 deletions captchatools/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,75 @@
2 = Anticaptcha
3 = 2captcha
'''
from .harvesters import captcha_harvesters
from .exceptions import(
WrongAPIKeyException, NoBalanceException, WrongSitekeyException, NoHarvesterException
)
__version__ = "2.0.0"
__author__ = "Matthew17-21"
__license__ = "MIT"

from abc import ABC, abstractmethod
from typing import Optional
from . import exceptions as captchaExceptions
class Harvester(ABC):
'''
Represents a captcha harvester.
'''
def __init__(self, **kwargs) -> None:
self.api_key = kwargs.get("api_key",None)
self.captcha_type = kwargs.get("captcha_type","v2").lower()
self.solving_site = kwargs.get("solving_site",None)
self.invisible_captcha = kwargs.get("invisible_captcha",False)
self.captcha_url = kwargs.get("captcha_url",None)
self.min_score = kwargs.get("min_score",0.7)
self.sitekey = kwargs.get("sitekey",None)
self.action = kwargs.get("action","verify")
self.soft_id = kwargs.get("soft_id",None)

# Validate Data
if self.api_key is None:
raise captchaExceptions.WrongAPIKeyException()
if self.solving_site is None:
raise captchaExceptions.NoHarvesterException("No solving site selected")
if self.captcha_type not in ["v2", "v3", "hcaptcha", "hcap", "image", "normal"]:
raise captchaExceptions.NoCaptchaType("Invalid captcha type")
if self.soft_id is None:
if self.solving_site == 3 or self.solving_site == "2captcha":
self.soft_id = 4782723

@abstractmethod
def get_balance(self) -> float:
'''
Returns the balance for the current captcha harvster
'''

@abstractmethod
def get_token(
self, b64_img: Optional[str]=None,
user_agent: Optional[str]=None,
proxy: Optional[str]=None,
proxy_type: Optional[str]=None
):
'''
Returns a captcha token
'''

def new_harvester(**kwargs) -> Harvester:
# Need to import here to prevent circular imports
from .twocap import Twocap
from .anticaptcha import Anticaptcha
from .capmonster import Capmonster
from .capsolver import Capsolver

site = kwargs.get("solving_site","").lower()
if site == 1 or site == "capmonster":
return Capmonster(**kwargs)
elif site == 2 or site == "anticaptcha":
return Anticaptcha(**kwargs)
elif site == 3 or site == "2captcha":
return Twocap(**kwargs)
elif site == 4 or site == "capsolver":
return Capsolver(**kwargs)
raise captchaExceptions.NoHarvesterException("No solving site selected")


# Just for backward compatibility
def captcha_harvesters(**kwargs) -> Harvester:
return new_harvester(**kwargs)
54 changes: 54 additions & 0 deletions captchatools/__init__.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
from abc import ABC, abstractmethod
from typing import Optional
class Harvester(ABC):
'''
Represents a captcha harvester.
'''
def __init__(
self,
api_key: Optional[str] = None,
captcha_type: Optional[str] = "v2",
solving_site: Optional[str] = None,
invisible_captcha: Optional[bool] = False,
captcha_url: Optional[str] = None,
min_score : Optional[float] = 0.7,
sitekey : Optional[str] = None,
action: Optional[str] = "verify",
soft_id: Optional[str] = None
) -> None: ...

@abstractmethod
def get_balance(self) -> float: ...

@abstractmethod
def get_token(
self, b64_img: Optional[str]=None,
user_agent: Optional[str]=None,
proxy: Optional[str]=None,
proxy_type: Optional[str]=None
): ...

def new_harvester(
api_key: Optional[str] = None,
captcha_type: Optional[str] = "v2",
solving_site: Optional[str] = None,
invisible_captcha: Optional[bool] = False,
captcha_url: Optional[str] = None,
min_score : Optional[float] = 0.7,
sitekey : Optional[str] = None,
action: Optional[str] = "verify",
soft_id: Optional[str] = None
) -> Harvester: ...

# Just for backward compatibility
def captcha_harvesters(
api_key: Optional[str] = None,
captcha_type: Optional[str] = "v2",
solving_site: Optional[str] = None,
invisible_captcha: Optional[bool] = False,
captcha_url: Optional[str] = None,
min_score : Optional[float] = 0.7,
sitekey : Optional[str] = None,
action: Optional[str] = "verify",
soft_id: Optional[str] = None
) -> Harvester: ...
Loading

0 comments on commit a1ccd5a

Please sign in to comment.