pychan 4chan과 상호 작용하는 Python 클라이언트입니다. 4Chan에는 공식 API가 없으며 제 3자가 구현하려는 시도는 멍청한 경향이 있었 으므로이 라이브러리는 4chan과 직접 상호 작용하는 것보다 추상화를 제공합니다. pychan 은 객체 지향적이며 성능을 최적화하고 불필요한 차단 I/O 작업을 최소화하기 위해 합리적 (Python Generator 사용)에서 구현이 게으르다.
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 필드 (필요한 경우)가 자동으로 수정됩니다. 자세한 내용은 특정 스레드의 페치 게시물을 참조하십시오.
기술적으로,
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의 보호의 우회를 자동화하려면 다음 중 하나와 같은 프로젝트를 사용하여 검토 할 수 있습니다 (이 목록은 알파벳순으로 완전하지 않음).
이러한 값을 획득하는 수동 방법은 웹 브라우저를 사용하여 4chan 검색을 수행하고 검색 중에 작성된 네트워크 요청을 추적하기 위해 브라우저의 개발자 도구를 활용하는 것입니다. CloudFlare 값이 포함 된 요청은 일부 쿼리 매개 변수가 포함 된 https://find.4chan.org/api 로 이루어졌습니다. 이 요청을 찾은 후에는 요청에 전송 된 User-Agent 및 Cookie 값을 복사 한 다음 pychan 의 search() 메소드로 전달하십시오. CloudFlare 쿠키에 만료가 있으므로이 수동 해결 방법은 CloudFlare가 쿠키를 무효화 할 때까지 결과를 반환합니다. 그 후에는 새로운 가치를 얻어야합니다.
참고 : 검색 결과에서는 폐쇄/고정/보관 된 스레드가 반환되지 않습니다.
# 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 class에 해당합니다.
| 필드 | 유형 | 예제 값 (들) |
|---|---|---|
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 |
개발자 중심 정보는 Contributing.md를 참조하십시오.