pychanは、4chanと対話するためのPythonクライアントです。 4chanには公式のAPIがなく、第三者ごとに1つを実装しようとする試みは、苦しみを起こす傾向があるため、このライブラリは(スクレイピング)4chanと直接対話する抽象化を提供します。 pychanはオブジェクト指向であり、その実装は、パフォーマンスを最適化し、余分なブロッキングI/O操作を最小限に抑えるために、合理的な場合(Pythonジェネレーターを使用)怠zyです。
Python> = 3.10と<4.0がインストールされている場合、 pychan Pypiからのようなものを使用してインストールできます
pip install pychanすべての4chanの相互作用は、実行されたスレッドを睡眠することにより、内部的にスロットルされます。 pychanマルチスレッドの方法で実行した場合、このスロットリングのメリットは得られません。 pychan 、そのような場合の過剰なHTTP要求の結果に対して責任を負いません。
from pychan import FourChan , LogLevel , PychanLogger
# With all defaults (logging disabled, all exceptions raised)
fourchan = FourChan ()
# Tell pychan to gracefully ignore HTTP exceptions, if any, within its internal logic
fourchan = FourChan ( raise_http_exceptions = False )
# Tell pychan to gracefully ignore parsing exceptions, if any, within its internal logic
fourchan = FourChan ( raise_parsing_exceptions = False )
# Configure logging explicitly
logger = PychanLogger ( LogLevel . INFO )
fourchan = FourChan ( logger = logger )
# Use all of the above settings at once
logger = PychanLogger ( LogLevel . INFO )
fourchan = FourChan ( logger = logger , raise_http_exceptions = True , raise_parsing_exceptions = True )このREADMEの残りの例は、上記のようにFourChanクラスのインスタンスをすでに作成していると仮定しています。
この関数は、コール時に4chanからボードを動的にフェッチします。
注:
pychanと互換性のないボードは、このリストには返されません。
boards = fourchan . get_boards ()
# Sample return value:
# ['a', 'b', 'c', 'd', 'e', 'g', 'gif', 'h', 'hr', 'k', 'm', 'o', 'p', 'r', 's', 't', 'u', 'v', 'vg', 'vm', 'vmg', 'vr', 'vrpg', 'vst', 'w', 'wg', 'i', 'ic', 'r9k', 's4s', 'vip', 'qa', 'cm', 'hm', 'lgbt', 'y', '3', 'aco', 'adv', 'an', 'bant', 'biz', 'cgl', 'ck', 'co', 'diy', 'fa', 'fit', 'gd', 'hc', 'his', 'int', 'jp', 'lit', 'mlp', 'mu', 'n', 'news', 'out', 'po', 'pol', 'pw', 'qst', 'sci', 'soc', 'sp', 'tg', 'toy', 'trv', 'tv', 'vp', 'vt', 'wsg', 'wsr', 'x', 'xs'] # Iterate over all threads in /b/
for thread in fourchan . get_threads ( "b" ):
# Do stuff with the thread
print ( thread . title )
# You can also iterate over all the posts in the thread
for post in fourchan . get_posts ( thread ):
# Do stuff with the post - refer to the model documentation in pychan's README for details
print ( post . text )注:一部のボードにはアーカイブがありません(例
/b/)。このようなボードは、FourChanインスタンスの構成方法に応じて、空のリストを返したり、例外を提起したりします。
この関数によって返されるスレッドには、「抜粋」列ヘッダーの下に4chanのインターフェイスに表示されるテキストを含むtitleフィールドが常にあります。このテキストは、スレッドの実際のタイトルまたは元の投稿のテキストのプレビューのいずれかです。このメソッドによって返されたスレッドのいずれかをget_posts()メソッドに渡すと、返された投稿に添付されているスレッド上のtitleフィールド(必要に応じて)が自動的に修正されます。詳細については、特定のスレッドについては、Fetch Postsを参照してください。
技術的には、
pychan各スレッドに追加のHTTP要求を発行して実際のタイトルを取得することで上記のtitle動作に対処できますが、HTTPリクエストの最小数を可能にする精神で、pychan代わりに抜粋を直接使用します。
for thread in fourchan . get_archived_threads ( "pol" ):
# Do stuff with the thread
print ( thread . title )
# You can also iterate over all the posts in the thread
for post in fourchan . get_posts ( thread ):
# Do stuff with the post - refer to the model documentation in pychan's README for details
print ( post . text )4chanに対して検索を実行することは、4chanの残りのデータにアクセスするよりもはるかに面倒です。これは、4ChanがREST APIの前にCloudFlareファイアウォールを持っているため、検索からデータを取り戻す唯一の方法は、CloudFlareのアンチボットチェックをバイパスするために必要なHTTP要求情報を提供することです。最終的に、これはHTTP要求とともに特定のヘッダーを渡すことになりますが、課題は実際にそのようなヘッダーを取得することから生じます。
現在、これらのヘッダーを生成するのは現在、 pychanの範囲を超えているため、CloudFlareの保護の回避を自動化したい場合は、次のいずれかのプロジェクトを使用することを検討したい場合があります(このリストはアルファベット化され、網羅的ではありません)。
これらの値を取得する手動で、Webブラウザーを使用して4chan検索を実行し、ブラウザの開発者ツールを活用して、検索中に作成されたネットワークリクエストをトレースすることです。 CloudFlare値を含むリクエストは、いくつかのクエリパラメーターを使用してhttps://find.4chan.org/apiに対して行われます。このリクエストが見つかったら、リクエストで送信されたUser-AgentとCookie値をコピーしてから、 pychanのsearch()メソッドに渡します。 CloudFlare Cookieが有効期限を切っていることに注意してください。そのため、この手動の回避策は、CloudFlareがCookieを無効にするまで結果を返します。その後、新しい値を取得する必要があります。
注:検索結果では、閉じた/スティック/アーカイブされたスレッドが返されることはありません。
# This "threads" variable will contain a Python Generator (not a list) in order to facilitate laziness
threads = fourchan . search (
board = "b" ,
text = "ylyl" ,
user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36" ,
cloudflare_cookies = {
"cf_clearance" : "bm2RICpcDeR4cXoC2nfI_cnZcbAkN4UYpN6c1zzeb8g-1440859602-0-160"
}
)
for thread in threads :
# The thread object is the same class as the one returned by get_threads()
for post in fourchan . get_posts ( thread ):
# Do stuff with the post - refer to the model documentation in pychan's README for details
print ( post . text ) from pychan . models import Thread
# Instantiate a Thread instance with which to query for posts
thread = Thread ( "int" , 168484869 )
# Note: the thread contained within the returned posts will have all applicable metadata (such as
# title and sticky status), regardless of whether you provided such data above - pychan will
# "auto-discover" all metadata and include it in the post models' copy of the thread
posts = fourchan . get_posts ( thread )次の表は、このライブラリが使用するさまざまなモデルで使用できるすべての種類のデータを要約します。
また、 pychanのすべてのモデルクラスが次の方法を実装することに注意してください。
__repr____str____hash____eq____iter__ __-これは、モデルをPythonのtuple()関数に渡すことができるように実装されています__copy____deepcopy__以下の表は、 pychan.models.Threadクラスに対応しています。
| 分野 | タイプ | 例値の例 |
|---|---|---|
thread.board | str | "b" 、 "int" |
thread.number | int | 882774935 168484869 |
thread.title | Optional[str] | None 、 "YLYL thread" |
thread.is_stickied | bool | True 、 False |
thread.is_closed | bool | True 、 False |
thread.is_archived | bool | True 、 False |
thread.url | str | "https://boards.4chan.org/a/thread/251097344" |
以下の表は、 pychan.models.Postクラスに対応しています。
| 分野 | タイプ | 例値の例 |
|---|---|---|
post.thread | Thread | pychan.models.Thread |
post.number | int | 882774935 882774974 |
post.timestamp | DateTime.DateTime | DateTime.DateTime |
post.poster | Poster | pychan.models.Poster |
post.text | str | ">be men>be boredn>write pychann>somehow it works" |
post.is_original_post | bool | True 、 False |
post.file | Optional[File] | None 、 pychan.models.File |
post.replies | list[Post] | [] 、 [pychan.models.Post, pychan.models.Post] |
post.url | str | "https://boards.4chan.org/a/thread/251097344#p251097419" |
上記のrepliesフィールドは、 pychan >>オペレーターを使用して現在の投稿に「返信」するスレッド内のすべての投稿にアクセスするための純粋に便利な機能です。ただし、 repliesフィールドを使用して、スレッド内の利用可能なすべての投稿にアクセスする必要はありません。 get_posts()メソッドを呼び出すと、単一のフラットリストとして(順序で)すべての投稿を受け取ります。
以下の表は、 pychan.models.Posterクラスに対応しています。
| 分野 | タイプ | 例値の例 |
|---|---|---|
poster.name | str | "Anonymous" |
poster.is_moderator | bool | True 、 False |
poster.id | Optional[str] | None 、 "BYagKQXI" |
poster.flag | Optional[str] | None 、 "United States" 、 "Canada" |
以下の表は、 pychan.models.Fileクラスに対応しています。
| 分野 | タイプ | 例値の例 |
|---|---|---|
file.url | str | "https://i.4cdn.org/pol/1658892700380132.jpg" |
file.name | str | "wojak.jpg" 、 "i feel alone.jpg" |
file.size | str | "601 KB" |
file.dimensions | tuple[int, int] | (1920, 1080) 、 (800, 600) |
file.is_spoiler | bool | True 、 False |
開発者指向の情報については、converting.mdを参照してください。