Spaces:
Running
Running
from pathlib import Path | |
import os | |
import requests | |
from playwright.async_api import BrowserContext as ASyncContext, async_playwright | |
import hcaptcha_challenger as solver | |
from hcaptcha_challenger.agents import AgentT, Malenia | |
# Init local-side of the ModelHub | |
solver.install(upgrade=True) | |
# Save dataset to current working directory | |
user_data_dir = Path(__file__).parent.joinpath("user_data_dir") | |
context_dir = user_data_dir.joinpath("context") | |
tmp_dir = Path(__file__).parent.joinpath("tmp_dir") | |
async def hit_challenge(context: ASyncContext, host, sitekey, times: int = 8): | |
await context.route('**/*', lambda route, request: route_continuation(route, request, host, sitekey)) | |
page = context.pages[0] | |
agent = AgentT.from_page(page=page, tmp_dir=tmp_dir) | |
await page.goto(f"https://{host}") | |
await agent.handle_checkbox() | |
for pth in range(1, times): | |
result = await agent() | |
print(f">> {pth} - Challenge Result: {result}") | |
match result: | |
case agent.status.CHALLENGE_BACKCALL: | |
await page.wait_for_timeout(500) | |
fl = page.frame_locator(agent.HOOK_CHALLENGE) | |
await fl.locator("//div[@class='refresh button']").click() | |
case agent.status.CHALLENGE_SUCCESS: | |
rqdata = agent.cr.__dict__ | |
print(os.system(f"rm -rf {tmp_dir}")) | |
print(os.system(f"rm -rf {user_data_dir}")) | |
return rqdata["generated_pass_UUID"] | |
async def route_continuation(route, request, host, sitekey): | |
# 检查请求的URL,只拦截特定网站的请求 | |
if request.url == f"https://{host}/": | |
print("start to solve") | |
# 修改DNS解析结果 | |
await route.fulfill(status=200, | |
body=""" | |
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<title>hCAPTCHA 演示</title> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | |
<meta name="viewport" content="width=device-width, user-scalable=yes"> | |
<script src="https://js.hcaptcha.com/1/api.js?reportapi=https%3A%2F%2Faccounts.hcaptcha.com&custom=False&pstissuer=https://pst-issuer.hcaptcha.com" type="text/javascript" async defer></script> | |
<script src="/static/js/b.js" type="text/javascript" async defer></script> | |
<style type="text/css"> | |
html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,font,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td{margin:0;padding:0;border:0;outline:0;font-family:-apple-system,helvetica,arial,sans-serif;font-size:14px;vertical-align:baseline}fieldset{border:1px solid #ebebeb;padding:16px}form label{display:block;line-height:29px}form ul li{margin-bottom:10px}input{font-family:-apple-system,helvetica,arial,sans-serif;font-size:14px}ul{list-style:none}.sample-form{width:335px;padding:16px}.hcaptcha-error{border:1px solid #dd4b39;padding:5px}.hcaptcha-error-message{color:#dd4b39;font-size:24px;padding:10px 0}.hcaptcha-success{margin:20px; font-size: 24px;}.smsg{color:green;}.wrap{overflow-wrap: anywhere;}.warning{padding: 10px 10px 0px 10px;} | |
code { font-family: 'Courier New', Courier, monospace; background-color: lightgrey;} | |
} | |
} | |
</style> | |
</head> | |
<body> | |
<div aria-hidden="true" class="warning"><code>?hl=XXX</code> 使用它来更改 hl JS API 参数。</div> | |
<div aria-hidden="true" class="warning"><code>?sitekey=XXX</code> 用它来更改站点密钥。</div> | |
<div aria-hidden="true" class="warning"><code>?secret=XXX</code> 用它来更改站点验证秘密。</div> | |
<div aria-hidden="true" class="warning"><code>?sitekey=XXX&secret=XXX</code> 用它来改变两者。</div> | |
<br><br> | |
<div class="sample-form"> | |
<form id="hcaptcha-demo-form" method="POST"> | |
<fieldset> | |
<legend>带 hCAPTCHA 的示例表单</legend> | |
<ul> | |
<li role="presentation"> | |
<label for="ignored1" aria-hidden="true">表单字段(可选)</label> | |
<input class="textinput" id="ignored1" name="email" type="text" tabindex="-1" aria-hidden="true" aria-label="表单字段(可选)" aria-required="false"> | |
</li> | |
<li role="presentation"> | |
<div class> | |
<div id="hcaptcha-demo" class="h-captcha" data-sitekey="%%%%%%%%%%%" data-callback="onSuccess" data-expired-callback="onExpire"></div> | |
<script> | |
// success callback | |
var onSuccess = function(response) { | |
var errorDivs = document.getElementsByClassName("hcaptcha-error"); | |
if (errorDivs.length) { | |
errorDivs[0].className = ""; | |
} | |
var errorMsgs = document.getElementsByClassName("hcaptcha-error-message"); | |
if (errorMsgs.length) { | |
errorMsgs[0].parentNode.removeChild(errorMsgs[0]); | |
} | |
var logEl = document.querySelector(".hcaptcha-success"); | |
logEl.innerHTML = "挑战成功!" | |
}; | |
var onExpire = function(response) { | |
var logEl = document.querySelector(".hcaptcha-success"); | |
logEl.innerHTML = "令牌已过期。" | |
}; | |
</script> | |
</div> | |
</li> | |
<li> | |
<input id="hcaptcha-demo-submit" type="submit" value="Submit"> | |
</li> | |
</ul> | |
</fieldset> | |
</form> | |
<div class="hcaptcha-success smsg" aria-live="polite"></div> | |
</div> | |
</body> | |
<script type="text/javascript"> | |
// beacon example | |
function addEventHandler(object,szEvent,cbCallback){ | |
if(!!object.addEventListener){ // for modern browsers or IE9+ | |
return object.addEventListener(szEvent,cbCallback); | |
} | |
if(!!object.attachEvent){ // for IE <=8 | |
return object.attachEvent(szEvent,cbCallback); | |
} | |
}; | |
// Ex: triggers pageview beacon | |
addEventHandler(window,'load',function(){b();}); | |
// Ex: triggers event beacon without pageview | |
addEventHandler(window,'load',function(){b({"vt": "e", "ec": "test_cat", "ea": "test_action"});}); | |
</script> | |
</html> | |
""".replace("%%%%%%%%%%%", sitekey)) | |
else: | |
# 对于其他网站的请求,不做修改 | |
await route.continue_() | |
async def bytedance(host, sitekey): | |
# playwright install firefox --with-deps | |
async with async_playwright() as p: | |
context = await p.firefox.launch_persistent_context( | |
user_data_dir=context_dir, | |
headless=True, | |
locale="en-US" | |
) | |
await Malenia.apply_stealth(context) | |
token = await hit_challenge(context, host, sitekey) | |
return token |