Spaces:
Sleeping
Sleeping
Upload scraper_template.py with huggingface_hub
Browse files- scraper_template.py +26 -29
scraper_template.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
| 1 |
-
|
| 2 |
# PMC Sniper v13.0 — injected by HF Worker Space
|
| 3 |
SESSION_ID = __SESSION_ID__
|
| 4 |
RESUME_FROM_PAGE = __RESUME_FROM_PAGE__
|
|
@@ -7,10 +6,11 @@ TOTAL_SESSIONS = __TOTAL_SESSIONS__
|
|
| 7 |
|
| 8 |
import subprocess, sys
|
| 9 |
def _install():
|
| 10 |
-
subprocess.run(['apt-get','install','-y','-q','xvfb','xauth',
|
| 11 |
-
'libnss3','libatk1.0-0','libatk-bridge2.0-0',
|
| 12 |
-
'
|
| 13 |
-
'
|
|
|
|
| 14 |
check=False, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
| 15 |
subprocess.run([sys.executable,'-m','pip','install','-q',
|
| 16 |
'playwright','pyvirtualdisplay','beautifulsoup4'], check=True)
|
|
@@ -27,8 +27,7 @@ from typing import Optional, Set
|
|
| 27 |
from collections import deque
|
| 28 |
try:
|
| 29 |
import nest_asyncio; nest_asyncio.apply()
|
| 30 |
-
except ImportError:
|
| 31 |
-
pass
|
| 32 |
from playwright.async_api import async_playwright
|
| 33 |
from pyvirtualdisplay import Display
|
| 34 |
from bs4 import BeautifulSoup
|
|
@@ -129,8 +128,10 @@ def write_state(last_page, reason, stats):
|
|
| 129 |
}
|
| 130 |
OUTPUT_DIR.mkdir(parents=True,exist_ok=True)
|
| 131 |
(OUTPUT_DIR/'run_state.json').write_text(json.dumps(state,indent=2))
|
| 132 |
-
|
| 133 |
-
|
|
|
|
|
|
|
| 134 |
return state
|
| 135 |
|
| 136 |
def _parse_cookies(raw):
|
|
@@ -155,15 +156,15 @@ def get_cookies():
|
|
| 155 |
except: continue
|
| 156 |
return []
|
| 157 |
|
| 158 |
-
STEALTH=
|
| 159 |
-
Object.defineProperty(navigator,
|
| 160 |
-
window.chrome={runtime:{},loadTimes:function(){},csi:function(){},app:{}};
|
| 161 |
-
Object.defineProperty(navigator,
|
| 162 |
-
Object.defineProperty(screen,
|
| 163 |
-
Object.defineProperty(screen,
|
| 164 |
-
Object.defineProperty(navigator,
|
| 165 |
-
Object.defineProperty(navigator,
|
| 166 |
-
|
| 167 |
|
| 168 |
async def block_ads(route):
|
| 169 |
try:
|
|
@@ -201,7 +202,8 @@ async def dismiss_popup(page):
|
|
| 201 |
try:
|
| 202 |
p=await page.query_selector('div.popup_wrap')
|
| 203 |
if not p or not await p.is_visible(): return
|
| 204 |
-
for sel in ['div.popup_wrap a.btn:not(.cancel)',
|
|
|
|
| 205 |
for el in await page.query_selector_all(sel):
|
| 206 |
try:
|
| 207 |
txt=(await el.inner_text()).strip().lower()
|
|
@@ -229,7 +231,7 @@ async def clear_cf(ctx, page):
|
|
| 229 |
(OUTPUT_DIR/'fresh_cookies.json').write_text(json.dumps(fresh,indent=2))
|
| 230 |
except: pass
|
| 231 |
return True
|
| 232 |
-
for sel in ["#challenge-stage input[type='checkbox']",'.cf-turnstile input']:
|
| 233 |
try:
|
| 234 |
el=await page.query_selector(sel)
|
| 235 |
if el: await el.click(); await page.wait_for_timeout(1000)
|
|
@@ -294,7 +296,6 @@ DL_SELS=[
|
|
| 294 |
async def download_build(page, entry, out, log, diag):
|
| 295 |
safe=re.sub(r'[^\w\-]','_',entry.name)[:40]
|
| 296 |
folder=out/f'{entry.id[:40]}_{safe}'
|
| 297 |
-
meta=None
|
| 298 |
if not diag[0]:
|
| 299 |
diag[0]=True
|
| 300 |
try:
|
|
@@ -304,8 +305,7 @@ async def download_build(page, entry, out, log, diag):
|
|
| 304 |
await page.screenshot(path=str(out/'diag.png'),full_page=True)
|
| 305 |
already=True
|
| 306 |
except: already=False
|
| 307 |
-
else:
|
| 308 |
-
already=False
|
| 309 |
try:
|
| 310 |
if not already:
|
| 311 |
await page.goto(entry.project_url,wait_until='domcontentloaded',timeout=25000)
|
|
@@ -403,8 +403,7 @@ async def run_worker(wid, page, tracker, queue, out, stop_ev, col_done, stats, d
|
|
| 403 |
queue.task_done()
|
| 404 |
if n>0 and n%50==0:
|
| 405 |
p=random.randint(30,60); log(f'Think {p}s'); await asyncio.sleep(p)
|
| 406 |
-
else:
|
| 407 |
-
await asyncio.sleep(random.uniform(5.0,12.0))
|
| 408 |
log(f'Done ok={stats["success"]}'); await page.close()
|
| 409 |
|
| 410 |
def parse_links(html):
|
|
@@ -485,15 +484,13 @@ async def main():
|
|
| 485 |
'last_page':START_PAGE,'stop_reason':'RUNNING','t0':time.time()}
|
| 486 |
if tracker.total>0: print(f'Resuming — {tracker.total} in log.csv')
|
| 487 |
rate=RateTracker(max_hr=MAX_RATE_PER_HR); diag=[False]
|
| 488 |
-
print(f'
|
| 489 |
-
f'Slice {SLICE_START}–{SLICE_END} | Start page {START_PAGE}\n{"="*55}')
|
| 490 |
async with async_playwright() as pw:
|
| 491 |
br,ctx=await setup_browser(pw)
|
| 492 |
cfp=await ctx.new_page()
|
| 493 |
if not await clear_cf(ctx,cfp):
|
| 494 |
write_state(START_PAGE-1,'CF_FAILED',stats); await br.close(); return
|
| 495 |
await cfp.close()
|
| 496 |
-
print(f'Starting {DL_WORKERS} workers...')
|
| 497 |
wps=[]
|
| 498 |
for i in range(DL_WORKERS):
|
| 499 |
wp=await new_tab(ctx)
|
|
@@ -531,4 +528,4 @@ def run():
|
|
| 531 |
try: asyncio.get_event_loop().run_until_complete(main())
|
| 532 |
finally: d.stop()
|
| 533 |
|
| 534 |
-
run()
|
|
|
|
|
|
|
| 1 |
# PMC Sniper v13.0 — injected by HF Worker Space
|
| 2 |
SESSION_ID = __SESSION_ID__
|
| 3 |
RESUME_FROM_PAGE = __RESUME_FROM_PAGE__
|
|
|
|
| 6 |
|
| 7 |
import subprocess, sys
|
| 8 |
def _install():
|
| 9 |
+
subprocess.run(['apt-get','install','-y','-q','xvfb','xauth',
|
| 10 |
+
'x11-utils','libnss3','libatk1.0-0','libatk-bridge2.0-0',
|
| 11 |
+
'libcups2','libxcomposite1','libxdamage1','libxfixes3',
|
| 12 |
+
'libxrandr2','libgbm1','libpango-1.0-0','libcairo2',
|
| 13 |
+
'libasound2','libx11-xcb1','libxcb-dri3-0'],
|
| 14 |
check=False, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
| 15 |
subprocess.run([sys.executable,'-m','pip','install','-q',
|
| 16 |
'playwright','pyvirtualdisplay','beautifulsoup4'], check=True)
|
|
|
|
| 27 |
from collections import deque
|
| 28 |
try:
|
| 29 |
import nest_asyncio; nest_asyncio.apply()
|
| 30 |
+
except ImportError: pass
|
|
|
|
| 31 |
from playwright.async_api import async_playwright
|
| 32 |
from pyvirtualdisplay import Display
|
| 33 |
from bs4 import BeautifulSoup
|
|
|
|
| 128 |
}
|
| 129 |
OUTPUT_DIR.mkdir(parents=True,exist_ok=True)
|
| 130 |
(OUTPUT_DIR/'run_state.json').write_text(json.dumps(state,indent=2))
|
| 131 |
+
import sys as _sys
|
| 132 |
+
_sys.stdout.write(f'\n##RUN_STATE##{json.dumps(state)}##RUN_STATE##\n')
|
| 133 |
+
_sys.stdout.flush()
|
| 134 |
+
print(f'DONE {RUN_ID} | page {last_page} | {remaining} left | {reason}')
|
| 135 |
return state
|
| 136 |
|
| 137 |
def _parse_cookies(raw):
|
|
|
|
| 156 |
except: continue
|
| 157 |
return []
|
| 158 |
|
| 159 |
+
STEALTH = (
|
| 160 |
+
'Object.defineProperty(navigator,"webdriver",{get:()=>undefined});'
|
| 161 |
+
'window.chrome={runtime:{},loadTimes:function(){},csi:function(){},app:{}};'
|
| 162 |
+
'Object.defineProperty(navigator,"languages",{get:()=>["en-US","en"]});'
|
| 163 |
+
'Object.defineProperty(screen,"width",{get:()=>1920});'
|
| 164 |
+
'Object.defineProperty(screen,"height",{get:()=>1080});'
|
| 165 |
+
'Object.defineProperty(navigator,"hardwareConcurrency",{get:()=>4});'
|
| 166 |
+
'Object.defineProperty(navigator,"platform",{get:()=>"Win32"});'
|
| 167 |
+
)
|
| 168 |
|
| 169 |
async def block_ads(route):
|
| 170 |
try:
|
|
|
|
| 202 |
try:
|
| 203 |
p=await page.query_selector('div.popup_wrap')
|
| 204 |
if not p or not await p.is_visible(): return
|
| 205 |
+
for sel in ['div.popup_wrap a.btn:not(.cancel)',
|
| 206 |
+
'div.popup_wrap button:not(.cancel)']:
|
| 207 |
for el in await page.query_selector_all(sel):
|
| 208 |
try:
|
| 209 |
txt=(await el.inner_text()).strip().lower()
|
|
|
|
| 231 |
(OUTPUT_DIR/'fresh_cookies.json').write_text(json.dumps(fresh,indent=2))
|
| 232 |
except: pass
|
| 233 |
return True
|
| 234 |
+
for sel in ["#challenge-stage input[type='checkbox']",' .cf-turnstile input']:
|
| 235 |
try:
|
| 236 |
el=await page.query_selector(sel)
|
| 237 |
if el: await el.click(); await page.wait_for_timeout(1000)
|
|
|
|
| 296 |
async def download_build(page, entry, out, log, diag):
|
| 297 |
safe=re.sub(r'[^\w\-]','_',entry.name)[:40]
|
| 298 |
folder=out/f'{entry.id[:40]}_{safe}'
|
|
|
|
| 299 |
if not diag[0]:
|
| 300 |
diag[0]=True
|
| 301 |
try:
|
|
|
|
| 305 |
await page.screenshot(path=str(out/'diag.png'),full_page=True)
|
| 306 |
already=True
|
| 307 |
except: already=False
|
| 308 |
+
else: already=False
|
|
|
|
| 309 |
try:
|
| 310 |
if not already:
|
| 311 |
await page.goto(entry.project_url,wait_until='domcontentloaded',timeout=25000)
|
|
|
|
| 403 |
queue.task_done()
|
| 404 |
if n>0 and n%50==0:
|
| 405 |
p=random.randint(30,60); log(f'Think {p}s'); await asyncio.sleep(p)
|
| 406 |
+
else: await asyncio.sleep(random.uniform(5.0,12.0))
|
|
|
|
| 407 |
log(f'Done ok={stats["success"]}'); await page.close()
|
| 408 |
|
| 409 |
def parse_links(html):
|
|
|
|
| 484 |
'last_page':START_PAGE,'stop_reason':'RUNNING','t0':time.time()}
|
| 485 |
if tracker.total>0: print(f'Resuming — {tracker.total} in log.csv')
|
| 486 |
rate=RateTracker(max_hr=MAX_RATE_PER_HR); diag=[False]
|
| 487 |
+
print(f'PMC v13.0 | {RUN_ID} | s{SESSION_ID}/{TOTAL_SESSIONS-1}')
|
|
|
|
| 488 |
async with async_playwright() as pw:
|
| 489 |
br,ctx=await setup_browser(pw)
|
| 490 |
cfp=await ctx.new_page()
|
| 491 |
if not await clear_cf(ctx,cfp):
|
| 492 |
write_state(START_PAGE-1,'CF_FAILED',stats); await br.close(); return
|
| 493 |
await cfp.close()
|
|
|
|
| 494 |
wps=[]
|
| 495 |
for i in range(DL_WORKERS):
|
| 496 |
wp=await new_tab(ctx)
|
|
|
|
| 528 |
try: asyncio.get_event_loop().run_until_complete(main())
|
| 529 |
finally: d.stop()
|
| 530 |
|
| 531 |
+
run()
|