Ë
    X«°j#  ã                  óš  — d Z ddlmZ ddlZddlZddlZddlZddlZddlZddl	Z	ddl
ZddlmZmZmZ  ej                   e«      j%                  «       j&                  j&                  ZdZdZdZ e	j0                  «       ZdgZdd	„Zdd
„Zdd„Z ej<                  dej>                  «       ej<                  dej>                  «       ej<                  dej>                  «       ej<                  dej>                  «       ej<                  dej>                  «      gZ dd„Z!	 	 d	 	 	 	 	 dd„Z"dd„Z#e$dk(  r ejJ                   e#«       «       yy)uÉ  5ch å�Žé›† (2026-09-21)ã€‚ å¤‰ã‚�ã‚‹ã‚‚ã�®ã�«æ‰‹ã‚’å�–ã‚‰ã‚Œã�ªã�„ä½œã‚Š:
  - æ�¿ã�¯å›ºå®šã�—ã�ªã�„: bbsmenu (æ�¿ä¸€è¦§) ã‚’æ¯Žå›žå�–ã‚Šã€� ã‚«ãƒ†ã‚´ãƒªèªž (channels.toml ã�® `match`) ã�§é�¸ã�¶ â†’ æ�¿ã�®ç§»è»¢ãƒ»ã‚µãƒ¼ãƒ�å¤‰æ›´ã�«è¿½å¾“
  - ã‚¹ãƒ¬ä¸€è¦§ã�¯ subject.txt (2ch æ™‚ä»£ã�‹ã‚‰å�Œã�˜å½¢å¼�: `<dat>.dat<>ã‚¿ã‚¤ãƒˆãƒ« (ãƒ¬ã‚¹æ•°)`)
  - æœ¬æ–‡ã�¯ read.cgi ã�® HTMLã€‚ ãƒ¬ã‚¹åŒºåˆ‡ã‚Šã�¯è¤‡æ•°ãƒ‘ã‚¿ãƒ¼ãƒ³ã�§è©¦ã�—ã€� å…¨éƒ¨å¤–ã‚Œã�Ÿã‚‰ ã€Œ0 ä»¶ã€� ã‚’å�¥å…¨æ€§ã�¨ã�—ã�¦è¨˜éŒ²ã�—ã�¦æ­¢ã�¾ã‚‹
  - æœ¬æ–‡ã�¯ YouTube ã�¨å�Œã�˜çµŒè·¯ (mask â†’ NFKC â†’ SqliteAppender)ã€‚ æ�¿å��ãƒ»ã‚¹ãƒ¬å��ãƒ»URLãƒ»å��å‰�æ¬„ã�¯ä¿�å­˜ã�—ã�ªã�„ (genre ã� ã�‘)

  python scripts/import_5ch.py --match å®Ÿæ³� --limit-boards 1 --threads 3 --dry     # å‹•ä½œç¢ºèª�
  python scripts/import_5ch.py --match VTuber --genre vtuber --threads 20         # å�Žé›†

å�¥å…¨æ€§: data/health_5ch.tsv ã�« (æ™‚åˆ», æ�¿, ã‚¹ãƒ¬æ•°, ãƒ¬ã‚¹æ•°) ã‚’è¿½è¨˜ã€‚ ãƒ¬ã‚¹ 0 ã�Œç¶šã�‘ã�° parser ã�Œå£Šã‚Œã�¦ã�„ã‚‹
é    )ÚannotationsN)ÚSqliteAppenderÚmaskÚ	normalizezFMozilla/5.0 (Windows NT 10.0; Win64; x64) Gecko/20100101 Firefox/120.0z!https://menu.5ch.net/bbsmenu.htmlg      @g        c                óÈ  — t         5  t        d   t        z   t        j                  «       z
  }|dkD  rt        j                  |«       t        j                  «       t        d<   ddd«       t
        j                  j                  | dt        i¬«      }t
        j                  j                  |d¬«      5 }|j                  «       cddd«       S # 1 sw Y   ŒkxY w# 1 sw Y   yxY w)u  å…¨ watcher å…±é€šã�® throttle (WAIT ç§’ã�« 1 ãƒªã‚¯ã‚¨ã‚¹ãƒˆ)ã€‚ 2026-09-21: æ�¿ watcher ã‚’ 5 æœ¬ã�«ã�—ã�Ÿã‚‰å�Œæ™‚èµ·å‹•ã�§
    read.cgi ã�Œç©ºãƒšãƒ¼ã‚¸ã‚’è¿”ã�— ã€Œparse 0 postsã€� ã�Œç¶šã�„ã�Ÿã�®ã�§ã€� æ�¿ã�”ã�¨ã�§ã�¯ã�ªã��ãƒ—ãƒ­ã‚»ã‚¹å…¨ä½“ã�§é–“éš”ã‚’å®ˆã‚‹ã€‚r   Nz
User-Agent)Úheadersé<   )Útimeout)Ú_GATEÚ_LASTÚWAITÚtimeÚsleepÚurllibÚrequestÚRequestÚUAÚurlopenÚread)ÚurlÚwaitÚreqÚrs       õP   /var/www/html/é…�ä¿¡ã‚¢ãƒ¼ã‚«ã‚¤ãƒ–/videos/stream-comments/scripts/import_5ch.pyÚgetr   #   s²   € ô 
ñ Ü�Q‰xœ$‰¤§¡£Ñ,ˆØ�!Š8Ü�J‰J�tÔÜ—9‘9“;Œˆa‰÷	ô
 �.‰.×
 Ñ
  ¨|¼RÐ.@Ð
 Ó
A€CÜ	�‰×	Ñ	 ¨RÐ	Ó	0ð °AØ�v‰v‹x÷ñ ÷ð ú÷ð ús   ‡ACÂ2CÃCÃC!c           	     óv  — t        t        «      j                  dd¬«      }g }d}|j                  «       D �]   }t	        j
                  d|t        j                  «      }|r|j                  d«      }t	        j                  d|t        j                  «      D ]�  }|j                  d«      |j                  d«      }}t	        j
                  d	|«      s&d
|j                  d«      j                  dd«      d   v rŒbd|v sd|v sd|v rŒo| |v s| |v sŒx|j                  |||j                  d«      dz   f«       ŒŸ �Œ |S )u_   bbsmenu â†’ (ã‚«ãƒ†ã‚´ãƒª, æ�¿å��, URL)ã€‚ ã‚«ãƒ†ã‚´ãƒªå��ã�‹æ�¿å��ã�« match ã‚’å�«ã‚€ã‚‚ã�®ã€‚Ú	shift_jisÚreplace©ÚerrorsÚ z<BR><BR><B>(.+?)</B>é   z6<A HREF=(https?://[^/ >"]+/[^/ >"]+/)[^>]*>([^<]+)</A>é   z/(bbsmenu|test|_)ú.ú/éÿÿÿÿz	headline.zfind.zdig.)r   ÚBBSMENUÚdecodeÚ
splitlinesÚreÚsearchÚIÚgroupÚfinditerÚrstripÚrsplitÚappend)ÚmatchÚtÚoutÚcatÚlineÚmr   Únames           r   Úboardsr9   0   s   € äŒG‹×Ñ˜K°	ÐÓ:€AØ
€CØ
€CØ—‘“ó ?ˆÜ�I‰IÐ-¨t´R·T±TÓ:ˆÙØ—'‘'˜!“*ˆCä—‘ÐVÐX\Ô^`×^bÑ^bÓcò 	?ˆAØŸ™ ›
 A§G¡G¨A£J�ˆCÜ�y‰yÐ-¨sÔ3°s¸c¿j¹jÈ»o×>TÑ>TÐUXÐZ[Ó>\Ð]_Ñ>`Ñ7`ØØ˜cÑ! W°¡^°vÀ±}ØØ˜‰|˜u¨š}Ø—
‘
˜C  s§z¡z°#£¸Ñ'<Ð=Õ>ò	?ð?ð €Jó    c           
     óŠ  — t        | dz   «      j                  dd¬«      }g }|j                  «       D ]x  }t        j                  d|«      }|sŒ|j                  |j                  d«      t        j                  |j                  d«      «      t        |j                  d«      «      f«       Œz |j                  d	„ ¬
«       |d| S )uM   subject.txt â†’ (dat, ã‚¿ã‚¤ãƒˆãƒ«, ãƒ¬ã‚¹æ•°) ã‚’ãƒ¬ã‚¹æ•°é™�é †ã�§ n ä»¶ã€‚zsubject.txtr   r   r   z(\d+)\.dat<>(.*)\s\((\d+)\)\s*$r"   r#   é   c                ó   — | d    S )Nr#   © )Úxs    r   ú<lambda>zthreads.<locals>.<lambda>M   s   € ˜A˜a™D˜5€ r:   )ÚkeyN)r   r(   r)   r*   r2   r1   r-   ÚhtmlÚunescapeÚintÚsort)Ú	board_urlÚnr3   r4   r6   r7   s         r   ÚthreadsrH   E   s¤   € äˆI˜Ñ%Ó&×-Ñ-¨kÀ)Ð-ÓL€AØ
€CØ—‘“ò QˆÜ�H‰HÐ7¸Ó>ˆÚØ�J‰J˜Ÿ™ ›
¤D§M¡M°!·'±'¸!³*Ó$=¼sÀ1Ç7Á7È1Ã:»ÐOÕPðQð ‡H�H‘€HÔ!Øˆr�ˆ7€Nr:   z*<div class="post-content"[^>]*>(.*?)</div>z%<div class="message"[^>]*>(.*?)</div>z:<div class="post"[^>]*>.*?<div class="message">(.*?)</div>z<dd>(.*?)</dd>z"<span class="escaped">(.*?)</span>c                óò  — t        j                  d| «      }|sg S |j                  d«      |j                  d«      }}t        |› d|› d|› d�«      }t        j                  d|d d t         j
                  «      }|r|j                  d«      j                  «       nd}|j                  «       j                  d	d
«      dv rd}	 |j                  |d¬«      }t        D ]÷  }	|	j                  |«      }
t        |
«      dk\  sŒ#g }|
D ]Ë  }t        j                  dd|t         j
                  ¬«      }t        j                  dd|t         j                  ¬«      }t        j                  dd|«      }t        j                   |«      }t        j                  dd|j#                  «       «      }t        j                  d|«      s|sŒ»|j%                  |«       ŒÍ |c S  g S # t        $ r |j                  dd¬«      }Y �Œ!w xY w)Nz(https?://[^/]+)/([^/]+)/r"   r#   z/test/read.cgi/r%   s   charset=([\w-]+)i   úutf-8Ú_ú-)ú	shift-jisrM   Úsjiszx-sjiszwindows-31jÚms932Úcp932r   r   r<   z	<br\s*/?>ú
)Úflagsz<a [^>]*>(.*?)</a>z\1z<[^>]+>r!   z^>>\d+(-\d+)?\s*z-^(!extend:|VIPQ2_EXTDAT|https?://|youtu\.be/))r*   r2   r-   r   r+   r,   r(   Úlowerr   ÚLookupErrorÚPOST_PATTERNSÚfindallÚlenÚsubÚSrB   rC   Ústripr1   )rF   Údatr7   ÚhostÚbbsÚbÚm_csÚencr3   ÚpatÚfoundr4   Úps                r   Úpostsrd   [   s¸  € Ü
�‰Ð-¨yÓ9€AÙØˆ	Ø—‘˜“
˜AŸG™G A›Jˆ#€DÜˆtˆf�O C 5¨¨#¨¨aÐ0Ó1€Aä�9‰9Ð)¨1¨U¨d¨8´R·T±TÓ:€DÙ$(ˆ$�*‰*�Q‹-×
Ñ
Ô
 ¨g€CØ
‡y�yƒ{×Ñ˜3 Ó$Ð(lÑlØˆð0Ø�H‰H�S ˆHÓ+ˆô ò ˆØ—‘˜A“ˆÜˆu‹:˜‹?ØˆCØò �Ü—F‘F˜<¨¨q¼¿¹Ô=�Ü—F‘FÐ0°%¸Ä"Ç$Á$ÔG�Ü—F‘F˜: r¨1Ó-�Ü—M‘M !Ó$�Ü—F‘FÐ.°°A·G±G³IÓ>�Ü—8‘8ÐLÈaÔPÑXYØØ—
‘
˜1•ðð ŠJðð €Iøô! ò 0Ø�H‰H�W YˆHÓ/‹ð0ús   ÃG ÇG6Ç5G6c                óÂ  — |rd|› d�nd}t        | «      d| }	t        |› d| ›d|	D �
��cg c]
  \  }
}}|
|f‘Œ c}}}
› �d¬«       |rdnt        j                  |d	z  «      }t        d
z  dz  }d}	 |	D �]»  \  }}}|�|j                  «       r �n¢t        j                  t        «       	 t        ||«      }d}|D ]ð  \  }}}|�|j                  «       r nØt        j                  t        «       	 t        ||«      }|D ]Œ  }|j                  d«      D ]v  }t        t        |«      «      }|rt        |«      dk  rŒ(|r|dk  rCt        d|dd d¬«       n1|j!                  t#        t        j                  «       dz  «      ||«       |dz  }Œx ŒŽ |rŒÕt        |› d|› d|› d|dd › d�d¬«       Œò ||z  }|j%                  dd¬«      5 }|j!                  t#        t        j                  «       «      › d|› dt        |«      › d|› d�«       ddd«       t        |› |› d t        |«      › d!|› �d¬«       �Œ¾ |�|j'                  «        	 t        |› d"|› �d¬«       |S c c}}}
w # t        $ r }t        |› d|› d|›�d¬«       Y d}~�Œd}~ww xY w# t        $ r%}t        |› d|› d|› d|›�d¬«       g }Y d}~�Œºd}~ww xY w# 1 sw Y   Œ·xY w# |�|j'                  «        w w xY w)#u„   æ�¿ã‚’ç™ºè¦‹ã�—ã�¦å‹¢ã�„ä¸Šä½�ã‚¹ãƒ¬ã�®ãƒ¬ã‚¹ã‚’é›†ã‚�ã‚‹ã€‚ æˆ»ã‚Šå€¤ = å�–ã‚Šè¾¼ã‚“ã� è¡Œæ•°ã€‚ daemon ã�‹ã‚‰å®šæœŸå‘¼ã�³å‡ºã�—ã€‚ú[z] z[5ch] Nzmatch=z boards=T)Úflushzcomments.sqliteÚdatazhealth_5ch.tsvr   z[err] subject z: z[err] z dat=rQ   r#   é   z  éP   iè  r"   z[warn] parse 0 posts: z (é   ú)ÚarJ   )Úencodingú	z
: threads=z posts=zdone posts=)r9   Úprintr   ÚsharedÚROOTÚis_setr   r   r   rH   Ú	Exceptionrd   Úsplitr   r   rW   ÚwriterD   ÚopenÚclose)r2   ÚgenreÚout_dirÚlimit_boardsÚthreads_per_boardÚdryÚlog_tagÚ
stop_eventÚprefixÚbsÚcrG   rK   ÚwriterÚhealthÚtotalr5   r8   r   ÚthsÚeÚn_postsr[   ÚtitleÚcntÚpsrc   r6   ÚbodyÚfs                                 r   ÚcollectrŽ   {   s#  € ñ !(ˆq��	˜‰_¨X€FÜ	�‹�}˜Ð	%€BÜ	ˆVˆH�F˜5˜) 8À2×,FÐ,F¹¸¸1¸a¨a°ªVÔ,FÐ+GÐ
HÐPTÕUÙ‰Tœn×3Ñ3°GÐ>OÑ4OÓP€FÜ�F‰]Ð-Ñ-€FØ€Eð'Ø ó #	U‰NˆC��sØÐ%¨*×*;Ñ*;Ô*=ÚÜ�J‰J”tÔðÜ˜cÐ#4Ó5�ð ˆGØ#&ò h‘��U˜CØÐ)¨j×.?Ñ.?Ô.AÙÜ—
‘
œ4Ô ðÜ˜s C›�Bð ò 
%�AØ !§¡¨£ò 	%˜Ü(¬¨d«Ó4˜Ù#¤s¨4£y°1¢}Ø$ÙØ&¨š|Ü % d¨D°°"¨I¸TÖ Bà"ŸL™L¬¬T¯Y©Y«[¸4Ñ-?Ó)@À$ÈÔNØ 1™™ñ	%ð
%ò Ü˜V˜HÐ$:¸4¸&ÀÀcÀUÈ"ÈUÐSVÐTVÈZÈLÐXYÐZÐbfÖgð+hð, �WÑˆEØ—‘˜S¨7�Ó3ð P°qØ—‘œ3œtŸy™y›{Ó+Ð,¨B¨t¨f°B´s¸3³x°jÀÀ7À)È2ÐNÔO÷Pä�V�H˜T˜F *¬S°«X¨J°g¸g¸YÐGÈt×TðG#	UðJ ÐØ�L‰L�NÜ	ˆVˆH�K ˜wÐ
'¨tÕ4Ø€Lùô[ -Gøô ò Ü˜˜ ¨t¨f°B°q°eÐ<ÀDÕIÝûðûô !ò Ü˜V˜H F¨4¨&°°c°U¸"¸Q¸EÐBÈ$ÕOØ–Bûðú÷"Pð Pûð ÐØ�L‰L�Nð ús…   ªIÁ18K	 Â*I Â68K	 Ã/JÃ;BK	 Æ6K	 ÇAJ=È+K	 É 	J	É)JÉ>K	 ÊJ	Ê	K	 Ê	J:ÊJ5Ê/K	 Ê5J:Ê:K	 Ê=K	ËK	 Ë	Kc                 ó&  — t        j                  «       } | j                  ddd¬«       | j                  dd ¬«       | j                  dt        d¬	«       | j                  d
t        dd¬«       | j                  dd¬«       | j                  dt	        t
        dz  «      ¬«       | j                  «       }t        |j                  |j                  t        j                  |j                  «      |j                  |j                  |j                  «       y)Nz--matchTu[   bbsmenu ã�®ã‚«ãƒ†ã‚´ãƒªå�� / æ�¿å��ã�«å�«ã�¾ã‚Œã‚‹èªž (ä¾‹: ã�ªã‚“ã�§ã‚‚å®Ÿæ³�J, ã‚²ãƒ¼ãƒ ))ÚrequiredÚhelpz--genre)Údefaultz--limit-boardsr<   )Útyper’   z	--threadsé
   u.   æ�¿ã�”ã�¨ã�«å‹¢ã�„ (ãƒ¬ã‚¹æ•°) ä¸Šä½� N ã‚¹ãƒ¬)r“   r’   r‘   z--dryÚ
store_true)Úactionz	--out-dirrh   r   )ÚargparseÚArgumentParserÚadd_argumentrD   Ústrrr   Ú
parse_argsrŽ   r2   ry   ÚpathlibÚPathrz   r{   rH   r}   )Úaprm   s     r   ÚmainrŸ   °   sÎ   € Ü	×	 Ñ	 Ó	"€BØ‡O�O�I¨ð  4Q€Oô  RØ‡O�O�I t€OÔ,Ø‡O�OÐ$¬3¸€OÔ:Ø‡O�O�K¤c°2Ð<l€OÔmØ‡O�O�G L€OÔ1Ø‡O�O�K¬¬T°F©]Ó);€OÔ<Ø
�‰‹€AÜˆA�G‰G�Q—W‘WœgŸl™l¨1¯9©9Ó5°q·~±~ÀqÇyÁyÐRS×RWÑRWÔXØr:   Ú__main__)r   rš   ÚreturnÚbytes)r2   rš   r¡   zlist[tuple[str, str, str]])rF   rš   rG   rD   r¡   zlist[tuple[str, str, int]])rF   rš   r[   rš   r¡   z	list[str])r<   r”   Fr!   N)r2   rš   ry   z
str | Nonerz   zpathlib.Pathr{   rD   r|   rD   r}   Úboolr~   rš   r¡   rD   )r¡   rD   )&Ú__doc__Ú
__future__r   r—   rB   rœ   r*   Úsysr   Ú	threadingÚurllib.requestr   Úimport_youtube_liver   r   r   r�   Ú__file__ÚresolveÚparentrr   r   r'   r   ÚLockr   r   r   r9   rH   ÚcompilerY   rU   rd   rŽ   rŸ   Ú__name__Úexitr>   r:   r   ú<module>r±      sK  ðñ
õ #ã Û Û Û 	Û 
Û Û Û ç ?Ñ ?à€w‡|�|�HÓ×%Ñ%Ó'×.Ñ.×5Ñ5€ØM€Ø
-€Ø
€ð 	ˆ	�‰Ó€Ø	ˆ€ó
óó*	ð €B‡J�JÐ<¸b¿d¹dÓCØ€B‡J�JÐ7¸¿¹Ó>Ø€B‡J�JÐLÈbÏdÉdÓSØ€B‡J�JÐ  "§$¡$Ó'Ø€B‡J�JÐ4°b·d±dÓ;ð€óð@ suØ=Að2Øð2Ø(+ð2ØFIó2ój
ð ˆzÒØ€C‡H�H‰T‹VÕð r:   