Files
xhs_crawler_claude/app/__pycache__/web.cpython-311.pyc
T

94 lines
23 KiB
Plaintext
Raw Normal View History

2026-01-12 18:58:23 +08:00
§
Ódiª4ã ó—dZddlmZddlZddlZddlZddlmZddlm Z m
Z
m Z m Z ddl
mZmZmZddlmZmZmZddlmZdd lmZdd
lmZdd lmZdd lmZdd
lm Z m!Z!ddl"m#Z#ddl$m%Z%ddl&m'Z'ddl"m(Z(ddl"m)Z)eGd„d¦«¦«Z*e*ej+¦«¬¦«Z,e%¦«Z-edd¬¦«Z"e" .edgddgdgdg¬¦«e" /deej0 1e#j2d¦«¬¦«d¬¦«eej0 1e#j2d ¦«¬¦«Z3e" 4d!¦«d"„¦«Z5e" 4d#¦«d$„¦«Z6Gd%„d&e¦«Z7Gd'„d(e¦«Z8Gd)„d*e¦«Z9Gd+„d,e¦«Z:Gd-„d.e¦«Z;e" <d/e¬0¦«ded3„¦«Z=dfd6„Z>dgd8„Z?dhd;„Z@did=„ZAe" <d>e8¬?¦«d@„¦«ZBe" CdA¦«dB„¦«ZDe" <dC¦«djdkdG„¦«ZEe" <dHe9¬?¦«dI„¦«ZFe" CdH¦«dldK„¦«ZGe" HdL¦«dldM„¦«ZIe" HdH¦«dN„¦«ZJe" <dO¦«dP„¦«ZKe" <dQe:¬?¦«dR„¦«ZLe" <dSe;¬?¦«dT„¦«ZMe" CdU¦«dV„¦«ZNe" CdW¦«dX„¦«ZOe" CdY¦«dZ„¦«ZPe" Cd[¦«dmd^„¦«ZQe" Cd_¦«d`„¦«ZRe" <da¦«dldb„¦«ZSe" <dc¦«dd„¦«ZTdS)nu€web.py - FastAPI å�Žç«¯
目标:
- �供基本的 Web UI + API(�动/�止采集�导入用户�登录/验��日志�SSE)
- �账�登录�长期�用(storage_state �存)
- txt 导入:支�“数字�红书��自动解�为 profile_id(并缓存,低频,�少风控)
- 移除无用/冗余的调试/自更新接�,代���清晰�维护
é)Ú annotationsN)Ú dataclass)ÚListÚOptionalÚDictÚAny)ÚFastAPIÚ
HTTPExceptionÚBackgroundTasks)Ú HTMLResponseÚStreamingResponseÚPlainTextResponse)Ú StaticFiles)ÚJinja2Templates)ÚRequest)ÚCORSMiddleware)Ú BaseModel)Úasync_playwrightÚBrowser)Úconfig)Ú
LogManager)ÚXiaoHongShuScraper)Ú auth_manager)Ú
user_resolvercóV—eZdZUdZded<dZded<dZded<dZd ed
<dZd ed <dS)
ÚAppStateFÚboolÚ
is_runningNzOptional[XiaoHongShuScraper]ÚscraperzOptional[asyncio.Queue]Ú event_queuerÚ
playwrightzOptional[Browser]Úbrowser) Ú__name__Ú
__module__Ú __qualname__rÚ__annotations__rr r!r"©óú/mnt/data/xhs_proj/app/web.pyrr(sg€€€€€€à€JÐÐÐÑØ,0€GÐ0Ð0Ð0Ñ0Ø+/€KÐ/Ð/Ð/Ñ/Ø€JÐÐÐÑØ!%€GÐ%Ð%Ð%Ñ%Ð%Ð%r(r)r uå°�红书数æ�®é‡‡é›†å™¨z1.1.0)ÚtitleÚversionÚ*T)Ú
allow_originsÚallow_credentialsÚ
allow_methodsÚ
allow_headersÚexpose_headersz/staticÚstatic)Ú directory)ÚnameÚ templatesÚstartupcƒóPK—t¦« ¦«ƒd{V—†t_tjj t jt j¬¦«ƒd{V—†t_ t  ddt j›d�¦«dS)N)ÚheadlessÚargsÚINFOzBrowser launched (headless=ú)) rÚstartÚ app_stater!ÚchromiumÚlaunchrÚHEADLESSÚ BROWSER_ARGSr"Ú log_managerÚappendr'r(r)Ú
on_startuprDIs­èè€õ"2Ñ!3Ô!3×!9Ò!9Ñ!;Ô!;Ð;Ð;Ð;Ð;Ð;Ð;…IÔÝ'Ô2Ô;×BÒBÝ”Ý
Ô
ðCñôðððððð…IÔõ×Ò�vÐO½V¼_ÐOÐOÐOÑPÔPÐPÐPÐPr(ÚshutdowncƒóDK— tjr$tj ¦«ƒd{V—†dt_n#dt_wxYw tjr$tj ¦«ƒd{V—†dt_dS#dt_wxYw)N)r=r"Úcloser!Ústopr'r(r)Ú on_shutdownrITsµèè€ð!Ý Ô ð ,ÝÔ#×)Ò)Ñ+Ô+Ð +Ð +Ð +Ð +Ð +Ð +Ð +à � ÔÐø˜D� ÔÐ Ð Ð Ð ð$Ý Ô ð .ÝÔ&×+Ò+Ñ-Ô-Ð -Ð -Ð -Ð -Ð -Ð -Ð -à#� ÔÐÐø˜t� ÔÐ#Ð#Ð#Ð#s„0AÁAÁ0BÂBcó,—eZdZUdZded<dZded<dS)Ú StartRequestÚsingleÚstrÚmodeéÚintÚ max_threadsN)r#r$r%rNr&rQr'r(r)rKrKhs4€€€€€€Ø€DÐÐÐÑØ€KÐÐÐÑÐÐr(rKcó6—eZdZUded<dZded<dZded<dS) ÚStatusResponserÚrunningNú
Optional[str]rNrrPÚ
user_count)r#r$r%r&rNrVr'r(r)rSrSms=€€€€€€Ø€M€M�MØ€DÐÐÐÑØ€JÐÐÐÑÐÐr(rScó$—eZdZUded<ded<dS)Ú
UsersResponseú List[str]ÚusersrPÚcountN)r#r$r%r&r'r(r)rXrXss%€€€€€€ØÐÐÑØ€J€J�J€J€Jr(rXcó‚—eZdZUded<ded<ded<ded<ded<ded<ded <ded
<ded <d ed
<gZded<dS)ÚImportResponserYrZrPr[Ú total_linesÚimportedÚskippedÚresolvedÚfailed_resolveÚ
duplicatesÚinvalidrMÚmessageÚfailed_examplesN)r#r$r%r&rfr'r(r)r]r]xs†€€€€€€ØÐÐÑØ€J€J�JØÐÐÑØ€M€M�MØ€L€L�LØ€M€M�MØÐÐÑØ€O€O�OØ€L€L�LØ€L€L�Là!#€OÐ#Ð#Ð#Ñ#Ð#Ð#r(r]cóD—eZdZUded<dZded<dZded<dZded<dS)ÚLoginStatusResponserÚ logged_inNrUÚ
login_timeÚlast_verified_timere)r#r$r%r&rjrkrer'r(r)rhrh‡sO€€€€€€Ø€O€O�OØ $€JÐ$Ð$Ð$Ñ$Ø(,ÐÐ,Ð,Ð,Ñ,Ø!€GÐ!Ð!Ð!Ñ!Ð!Ð!r(rhú/)Úresponse_classÚrequestrcƒó@K—t dd|i¦«S)Nz
index.htmlrn)r5ÚTemplateResponse)rns r)Úindexrq’s!èè€å × %Ò % l°YÀÐ4HÑ IÔ IÐIr(ÚreturnrMcóV—tj tjd¦«S)Nz users.txt)ÚosÚpathÚjoinrÚDATA_DIRr'r(r)Ú _users_filerx›s€Ý
Œ7�<Š<�œ¨Ñ 5Ô 5Ð5r(rYcó¨—t¦«}tj |¦«sgSg}t |dd¬¦«5}|D].}| ¦«}|sŒ| |¦«Œ/ ddd¦«n #1swxYwYt¦«}g}|D]1}||vrŒ| |¦«| |¦«Œ2|S)NÚrúutf-8©Úencoding) rxrtruÚexistsÚopenÚstriprCÚsetÚadd)rurZÚfÚlineÚseenÚoutÚus r)Úread_users_txtrˆŸs#€Ý ‰=Œ=€DÝ
Œ7�>Š>˜$Ñ Ô ðØˆ Ø€EÝ
ˆd�C 'Ð *Ñ *Ô *ð¨aØð ð ˆDØ—:’:‘<”<ˆDØð
ØØ �LŠL˜Ñ Ô Ð Ð ð  ðððñôððððððøøøððððõ ‰5Œ5€DØ
€CØ
ððˆØ �ˆ9ˆ9Ø Ø �Š�‰ Œ ˆ Ø �
Š
�1‰
Œ
ˆ
ˆ
Ø €JsÁ2BÂBÂ
BrZÚNonecóæ—t¦«}|dz}t|dd¬¦«5}|D]}| |dz¦«Œ ddd¦«n #1swxYwYtj||¦«dS)Nz.tmpÚwr{r|ú
)rxrÚwritertÚreplace)rZruÚtmprƒr‡s r)Úwrite_users_txtr�µsÂ€Ý ‰=Œ=€DØ
�‰-€CÝ
ˆc�3 Ð )Ñ )Ô )ð¨QØð ð ˆAØ
�GŠG�A˜‘HÑ Ô Ð Ð ð ðððñôððððððøøøððððõ„Jˆs�DÑÔÐÐÐs¦AÁAÁArcóT—tj€tdd¬¦«‚tjS)NéôzBrowser not ready©Ú status_codeÚdetail)r=r"r
r'r(r)Úrequire_browserr–¾s(€ÝÔРݨÐ4GÐHÑHÔHÐHÝ Ô Ðr(z /api/status)Úresponse_modelcƒó¾K—ttjtjrt tjdd¦«ndt t
¦«¦«¬¦«S)NrN)rTrNrV)rSr=rrÚgetattrÚlenrˆr'r(r)Ú
api_statusr›ÈsTèè€å ÝÔ$Ý9BÔ9JÐ
T�W•YÔ&¨°Ñ
5Ô
5Ð
5ÐPTÝ•~Ñ'Ô'Ñ(Ô(ð ñ ô ðr(z/api/logs/clearcƒó@K—t ¦«ddiS©NÚsuccessT)rBÚclearr'r(r)Ú
clear_logsr Ñs#èè€å×ÒÑÔÐØ �tÐ Ðr(z /api/logséÈÚlimitrPcƒó@K—dt |¬¦«iS)NÚlogs©r¢)rBÚ
get_latestr¥s r)Úget_logsr§×s"èè€à •K×*Ò*°Ð*Ñ7Ô7Ð 8Ð8r(z
/api/userscƒó^K—t¦«}t|t|¦«¬¦«S)N)rZr[)rˆrXrš)rZs r)Ú get_usersr©às*èè€å Ñ Ô €EÝ ˜u­C°©J¬JÐ 7Ñ 7Ô 7Ð7r(Úuser_idcƒóÖK—|pd ¦«}|stdd¬¦«‚t¦«}||vrdddœS| |¦«t |¦«ddiS) NÚé�uuser_id ä¸�能为空r“Tu 已存在©ržrerž)r€r
rˆrCr�©rªrZs r)Úadd_userr°æs‡èè€àˆ}˜"×#Ò#Ñ%Ô%€GØ ðLݨÐ4JÐKÑKÔKÐKå Ñ Ô €EØ�%ÐÐØ¨KÐ8Ð8Ð8à ‡L‚L�ÑÔÐÝ�EÑÔÐØ �tÐ Ðr(z/api/users/{user_id}cƒóf‡K—t¦«}ˆfd„|D¦«}t|¦«ddiS)Ncó •—g|]
}|‰k¯|‘Œ Sr'r')Ú.0r‡rªs €r)ú
<listcomp>zdelete_user.<locals>.<listcomp>øsø€Ð .Ð .Ð .�1  g¢ ˆQ   r(ržT)rˆr�r¯s` r)Ú delete_userrµõsDøèè€å Ñ Ô €EØ .Ð .Ð .Ð .˜Ð .Ñ .Ô .€EÝ�EÑÔÐØ �tÐ Ðr(cƒó,K—tg¦«ddiSr�)r�r'r(r)Údelete_all_usersr·ýsèè€å�BÑÔÐØ �tÐ Ðr(z/api/users/export/txtcƒóbK—td t¦«¦«¦«S)Nz\n)rrvrˆr'r(r)Úexport_users_txtr¹s&èè€å ˜UŸZšZ­Ñ(8Ô(8Ñ9Ô9Ñ :Ô :Ð:r(z/api/users/import/txtc
ƒóæK—t¦«}tj |¦«st dd¬¦«‚t |dd¬¦«5}d„|D¦«}ddd¦«n #1swxYwYt
|¦«}t¦«}g}d }d }d }d } d }
g} t¦«} g}
|D�]}tj
|¦«\}}}|rI|  ¦«}|| vr|d
z
}Œ;|   |¦«| 
|¦«Œf|r|
 
||f¦«Œ€| ¦«rN| ¦« d ¦«s'| ¦« d ¦«r|d
z
}n0|d
z
}t
| ¦«d
kr|  
d|›�¦«�Œ|
D]Æ\}}tj||d¬¦«ƒd{V—†\}}|s8|
d
z
}
t
| ¦«d
kr|  
d|›d|›d|›d�¦«Œ_|  ¦«}|| vr|d
z
}Œ}|   |¦«| 
|¦«| d