사용자:Utoleetest/libre detailed stat

사용 방법[편집 | 원본 편집]

  1. pywikibot이 설치된 디렉토리에서 /scripts/userscrips에 "libre_detailed_stat.py"라는 이름으로 아래 스크립트를 저장합니다.
  2. 실행할 때에는 pywikibot에 로그인한 이후
> python pwb.py libre_detailed_stat

라고 입력하시면 됩니다.

스크립트[편집 | 원본 편집]

from time import time
import asyncio
import pywikibot
import re
import datetime

# 문서 길이
lens = [0, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 1200, 1400, 1600, 1800, 2000, 2500, 3000, 3500, 4000, 4500, 5000, 6000, 7000, 8000, 9000,
        10000, 12000, 14000, 16000, 18000, 20000, 25000, 30000, 35000, 40000, 45000, 50000, 60000, 70000, 80000, 90000, 100000,
        120000, 140000, 160000, 180000, 200000, 250000, 300000, 350000, 400000, 500000, 1000000, 10000000]

len_redirect = [0, 20, 30, 40, 50, 60, 70, 80, 90, 100, 200, 500, 10000, 100000]

# 리브레 위키에서 사용하는 이름공간.
namespace_nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 416, 417, 418, 828, 829, 1600, 1601, 2600, 3604, 3605]

site = pywikibot.Site('ko', 'libre')
# 일반 문서 길이별
res0 = {}
res0_list = {}
# 총 일반문서 수
sum_count_0 = 0
# 총 넘겨주기 수
sum_count_r = 0
# 문서 넘겨주기 수
sum_count_r_a = 0
# 동음이의어 문서수
sum_disambig = 0
# 이름공간별 문서수
res_o = {}
# 이름공간별 리다리렉트 문서수
res_or = {}
# 총 문서수
sum_all = 0
sum_allr = 0


# 문자열 한 자리면 0 강제삽입
def zeroinput(_str):
    if len(_str) == 0:
        return '00'
    elif len(_str) == 1:
        return '0' + _str
    else:
        return _str

# 페이지 숫자 세기
def count_page(page_gen):
    cnt = 0
    for _ in page_gen:
        cnt +=1
    return cnt

# 넘겨주기 문서 세기
def count_redirect(redirect_gen):
    cnt = 0
    for page in redirect_gen:
        cnt +=1
        # # 문단 리다이렉트
        # if re.search(r'\[\[.*#.*\]\]', page.text):
        #     cnt2 +=1
        # # 문서 리다이렉트
        # else:
        #     cnt1 +=1

    return cnt

# 동음이의 문서 세기
def count_disambig():
    disambigs = pywikibot.Category(site, '동음이의어 문서')
    gen = disambigs.articles(namespaces=0)
    cnt = 0
    for _ in gen:
        cnt += 1
    return cnt

# 일반문서 숫자 세기
async def fetch(num):
    pages = site.allpages(minsize=lens[num], maxsize=lens[num+1]-1, filterredir=False)
    page_count = await loop.run_in_executor(None, count_page, pages)
    return page_count

# 넘겨주기 문서 숫자 세기
async def fetch_redirect(num):
    pages = site.allpages(minsize=len_redirect[num], maxsize=len_redirect[num+1]-1, filterredir=True)
    page_count = await loop.run_in_executor(None, count_redirect, pages)
    return page_count

# 이름공간별 문서 숫자 세기
async def fetch_others(num, is_redirect=False):
    pages = site.allpages(namespace=num, filterredir=is_redirect)
    page_count = await loop.run_in_executor(None, count_page, pages)
    return page_count

def fetch_others_sync(num, is_redirect=False):
    pages = site.allpages(namespace=num, filterredir=is_redirect)
    page_count = count_page(pages)
    return page_count

# 기본 함수
async def main():
    global res0, res0_list, sum_count_0, sum_count_r, sum_count_r_a, sum_disambig, res_o, res_or, sum_all, sum_allr
    futures = [asyncio.ensure_future(fetch(num)) for num in range(len(lens)-1)]
                                                           # 태스크(퓨처) 객체를 리스트로 만듦
    result = await asyncio.gather(*futures)                # 결과를 한꺼번에 가져옴
    res0 = {lens[num] : result[num] for num in range(len(lens)-1)}
    print(res0)
    res0_list = {
        0: res0[0]+res0[100]+res0[200]+res0[300]+res0[400],
        500: res0[500]+res0[600]+res0[700]+res0[800]+res0[900],
        1000: res0[1000]+res0[1200]+res0[1400]+res0[1600]+res0[1800],
        2000: res0[2000]+res0[2500]+res0[3000]+res0[3500]+res0[4000]+res0[4500],
        5000: res0[5000]+res0[6000]+res0[7000]+res0[8000]+res0[9000],
        10000: res0[10000] + res0[12000] + res0[14000] + res0[16000] + res0[18000],
        20000: res0[20000] + res0[25000] + res0[30000] + res0[35000] + res0[40000] + res0[45000],
        50000: res0[50000] + res0[60000] + res0[70000] + res0[80000] + res0[90000],
        100000: res0[100000] + res0[120000] + res0[140000] + res0[160000] + res0[180000]+res0[200000]+res0[250000]+res0[300000]+res0[350000]+res0[400000]+res0[500000]+res0[1000000]
                 }

    sum_count_0 = sum(result)
    print('총 문서 :', sum_count_0)

    future_redirects = [asyncio.ensure_future(fetch_redirect(num)) for num in range(len(len_redirect)-1)]
    result1 = await asyncio.gather(*future_redirects)

    print(result1)

    # 총 넘겨주기
    sum_count_r = sum(result1)
    print('총 넘겨주기 :', sum_count_r)

    # 동음이의어 문서수
    sum_disambig = count_disambig()

    future_namespaces = [asyncio.ensure_future(fetch_others(num, False)) for num in namespace_nums]
    result2 = await asyncio.gather(*future_namespaces)

    future_namespaces2 = [asyncio.ensure_future(fetch_others(num, True)) for num in namespace_nums]
    result3 = await asyncio.gather(*future_namespaces2)

    # result2 = [fetch_others_sync(num, False) for num in namespace_nums]
    # result3 = [fetch_others_sync(num, True) for num in namespace_nums]

    res_o = {namespace_nums[i]: result2[i] for i in range(len(namespace_nums)) }

    res_or = {namespace_nums[i]: result3[i] for i in range(len(namespace_nums)) }

    print(res_o)

    print(res_or)

    sum_all = sum_count_0 + sum(list(res_o.values()))
    sum_allr = sum_count_0+ sum_count_r + sum(list(res_o.values())) + sum(list(res_or.values()))


begin = time()
loop = asyncio.get_event_loop()          # 이벤트 루프를 얻음
loop.run_until_complete(main())          # main이 끝날 때까지 기다림
loop.close()                             # 이벤트 루프를 닫음
end = time()
print('실행 시간: {0:.3f}초'.format(end - begin))


x = datetime.datetime.now()

datetime_string = f"{str(x.year)}-{str(x.month)}-{str(x.day)} {zeroinput(str(x.hour))}:{zeroinput(str(x.minute))} (KST)"

# 이용자 정보 가져오기.
total_user = 0
u_2021 = 0
u_2022 = 0
USERS = site.allusers()
user_by_contribs = {'0': 0, '1':0, '20':0, '100':0, '200':0, '500':0, '1000':0, '2000':0, '5000':0, '10000':0, '20000':0, '50000':0}
for user in USERS:
    total_user +=1
    if user['registration'][0:4] == "2022":
        u_2022 +=1
    elif user['registration'][0:4] == "2021":
        u_2021 +=1
    if user['editcount'] == 0:
        user_by_contribs['0'] +=1
    elif user['editcount'] < 20:
        user_by_contribs['1'] += 1
    elif user['editcount'] < 100:
        user_by_contribs['20'] += 1
    elif user['editcount'] < 200:
        user_by_contribs['100'] += 1
    elif user['editcount'] < 500:
        user_by_contribs['200'] += 1
    elif user['editcount'] < 1000:
        user_by_contribs['500'] += 1
    elif user['editcount'] < 2000:
        user_by_contribs['1000'] += 1
    elif user['editcount'] < 5000:
        user_by_contribs['2000'] += 1
    elif user['editcount'] < 10000:
        user_by_contribs['5000'] += 1
    elif user['editcount'] < 20000:
        user_by_contribs['10000'] += 1
    elif user['editcount'] < 50000:
        user_by_contribs['20000'] += 1
    else:
        user_by_contribs['50000'] += 1

# 최근 바뀜(7일, 30일)에서 정보 가져오기

d7b = datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta(days=7)
d30b = datetime.datetime.now(datetime.timezone.utc) - datetime.timedelta(days=30)

d7ts = d7b.strftime('%Y-%m-%dT%H:%M:%SZ')
d30ts = d30b.strftime('%Y-%m-%dT%H:%M:%SZ')

RC7 = site.recentchanges(end=d7ts)
RC30 = site.recentchanges(end=d30ts)

rctypes7 = {'new':0, 'edit':0, 'log': 0}
rcusers7 = {'user': [], 'anon': []}

for rc in RC7:
    if rc['type'] == 'edit':
        rctypes7['edit'] += 1
    elif rc['type'] == 'new':
        rctypes7['new'] += 1
    elif rc['type'] == 'log':
        rctypes7['log'] += 1
    if rc.get('anon') == "" and rc['user'] not in rcusers7['anon']:
        rcusers7['anon'].append(rc['user'])
    elif rc.get('anon') == None and rc['user'] not in rcusers7['user']:
        rcusers7['user'].append(rc['user'])

rctypes30 = {'new':0, 'edit':0, 'log': 0}
rcusers30 = {'user': [], 'anon': []}
rcusers30_obj = {}

for rc in RC30:
    if rc['type'] == 'edit':
        rctypes30['edit'] += 1
    elif rc['type'] == 'new':
        rctypes30['new'] += 1
    elif rc['type'] == 'log':
        rctypes30['log'] += 1
    if rc.get('anon') == "" and rc['user'] not in rcusers30['anon']:
        rcusers30['anon'].append(rc['user'])
    elif rc.get('anon') == None:
        if rc['user'] not in rcusers30['user']:
            rcusers30['user'].append(rc['user'])
            rcusers30_obj[rc['user']] =1
        else:
            rcusers30_obj[rc['user']] += 1

# 최근 30일간 이용자의 편집횟수 통계
user_uc0 = 0
user_uc5 = 0
user_uc20 = 0
user_uc50 = 0
user_uc100 = 0
user_uc500 = 0
for usr in rcusers30_obj:
    if rcusers30_obj[usr]<5:
        user_uc0 +=1
    elif rcusers30_obj[usr]<20:
        user_uc5 +=1
    elif rcusers30_obj[usr]<50:
        user_uc20 +=1
    elif rcusers30_obj[usr]<100:
        user_uc50 +=1
    elif rcusers30_obj[usr]<500:
        user_uc100 +=1
    else:
        user_uc500 +=1

new_text = """[[리브레 위키]]의 상세한 통계 정보를 제공하는 문서입니다. [[특수:통계]]에서 대략적인 통계값을 제공하고는 있지만 가끔 정확하지 않은 값을 출력하기도 하고, 정보가 다소 아쉬울 때가 있습니다. 이 문서는 좀 더 정교한 통계를 제공할 생각입니다.

참고로 통계값이 마지막으로 업데이트된 시각은 {now}입니다.

== 문서 상세 통계 ==
{{|class="wikitable"
! 전체 문서(넘겨주기 포함) !! 넘겨주기 제외 !! 넘겨주기 문서수 !! 동음이의어 문서수
|-
| {total} || {noredirect} || {redirect} || {disambig}
|}} 
=== 문서 길이별 문서 통계 ===
넘겨주기 문서는 제외한다.
{{|class="wikitable"
! 전체 문서 !! <500 !! 500~999 !! 1,000~1,999 !! 2,000~4,999 !! 5,000~9,999 !! 10,000~19,999 !! 20,000~49,999 !! 50,000~99,999 !! &ge;100,000
|-
| {noredirect} || {a0} || {a500} || {a1000} || {a2000} || {a5000} || {a10000} || {a20000} || {a50000} || {a100000}
|}} 

;그래프로 보기
<div class="box" style="overflow:auto;">
{{{{그래프|width=800|height=400|xAxisTitle=문서 길이|yAxisTitle=숫자|type=rect
|x=0,500,1000,2000,5000,10000,20000,50000,100000
|y={a0}, {a500}, {a1000}, {a2000}, {a5000}, {a10000}, {a20000}, {a50000}, {a100000}
}}}}
</div>

=== 이름공간별 문서 통계 ===
{{|class="wikitable"
! 이름공간 이름 !! 이름공간 번호 !! 문서수 (리다이렉트 포함)
|-
| (총문서수) || - || {sums}({sums_total})
|-
| (일반) || 0 || {noredirect}({total})
|-
| 토론 || 1 || {nr1}({tot1})
|-
| 사용자 || 2 || {nr2}({tot2})
|-
| 사용자토론 || 3 || {nr3}({tot3})
|-
| 리브레 위키 || 4 || {nr4}({tot4})
|-
| 리브레 위키토론 || 5 || {nr5}({tot5})
|-
| 파일 || 6 || {nr6}({tot6})
|-
| 파일토론 || 7 || {nr7}({tot7})
|-
| 미디어위키 || 8 || {nr8}({tot8})
|-
| 미디어위키토론 || 9 || {nr9}({tot9})
|-
| 틀 || 10 || {nr10}({tot10})
|-
| 틀토론 || 11 || {nr11}({tot11})
|-
| 도움말 || 12 || {nr12}({tot12})
|-
| 도움말토론 || 13 || {nr13}({tot13})
|-
| 분류 || 14 || {nr14}({tot14})
|-
| 분류토론 || 15 || {nr15}({tot15})
|-
| 포크1 || 416 || {nr416}({tot416})
|-
| 포크2 || 417 || {nr417}({tot417})
|-
| 포크3 || 418 || {nr418}({tot418})
|-
| 모듈 || 828 || {nr828}({tot828})
|-
| 모듈토론 || 829 || {nr829}({tot829})
|-
| 시리즈 || 1600 || {nr1600}({tot1600})
|-
| 시리즈토론 || 1601 || {nr1601}({tot1601})
|-
| 주제 || 2600 || {nr2600}({tot2600})
|-
| 마당 || 3604 || {nr3604}({tot3604})
|-
| 마당토론 || 3605 || {nr3605}({tot3605})
|}}

== 사용자 통계 ==
=== 로그인 사용자 총 기여횟수별 통계 ===
{{|class="wikitable"
! 유저수 총계 !! 미편집 !! 20회 미만 !!  20~99 !! 100~199 !! 200~499 !! 500~999 !! 1000~1999 !! 2000~4999 !! 5000~9999 !! 10000~19999 !! 20000~49999 !! 50000 이상  
|-
| {login_user} || {user_c0} || {user_c1} || {user_c20} || {user_c100} || {user_c200} || {user_c500} || {user_c1000} || {user_c2000} || {user_c5000} || {user_c10000} || {user_c20000} || {user_c50000}
|}} 

=== 활동중인 사용자 최근 30일간 기여빈도 ===
{{|class="wikitable"
! 5회 미만 !! 5~19 !! 20~49 !! 50~99 !! 100~499 !! 500회 이상
|-
| {user_uc0} || {user_uc5} || {user_uc20} || {user_uc50} || {user_uc100} || {user_uc500} 
|}} 

=== 로그인 사용자 가입년도 통계 ===
{{|class="wikitable"
! 2015년 !! 2016년 !! 2017년 !! 2018년 !! 2019년 !! 2020년 !! 2021년 !! 2022년
|-
| 2837 || 755 || 529 || 482 || 1239 || 1098 || {u_2021} || {u_2022}
|}} 

== 최근 편집 관련 ==
=== 최근 편집 횟수 세기 ===
{{|class="wikitable"
! 항목 !! 최근 7일 !! 최근 30일 
|-
| 로그인 사용자(전체 사용자) || {d7_login_user} ({d7_user}) ||  {d30_login_user} ({d30_user})
|-
| 편집 횟수 (문서 생성 제외) || {d7_count_edit} || {d30_count_edit}
|-
| 문서 생성 || {d7_count_new} || {d30_count_new}
|-
| 문서 기록 횟수 (업로드/이동/삭제 등) || {d7_count_log} || {d30_count_log}
|}} 

[[분류:위키야 놀자]]
"""

page = pywikibot.Page(site, "위키야 놀자/리브레 위키 상세통계", 1600)

page.text = new_text.format(
    now = datetime_string,
    total=sum_count_0 + sum_count_r,
    noredirect = sum_count_0,
    redirect = sum_count_r,
    disambig= sum_disambig,
    a0= res0_list[0],
    a500= res0_list[500],
    a1000= res0_list[1000],
    a2000= res0_list[2000],
    a5000= res0_list[5000],
    a10000= res0_list[10000],
    a20000= res0_list[20000],
    a50000= res0_list[50000],
    a100000= res0_list[100000],
    sums = sum_all,
    sums_total=sum_allr,
    nr1 = res_o[1],
    tot1 = res_o[1] + res_or[1],
    nr2=res_o[2],
    tot2=res_o[2] + res_or[2],
    nr3=res_o[3],
    tot3=res_o[3] + res_or[3],
    nr4=res_o[4],
    tot4=res_o[4] + res_or[4],
    nr5=res_o[5],
    tot5=res_o[5] + res_or[5],
    nr6=res_o[6],
    tot6=res_o[6] + res_or[6],
    nr7=res_o[7],
    tot7=res_o[7] + res_or[7],
    nr8=res_o[8],
    tot8=res_o[8] + res_or[8],
    nr9=res_o[9],
    tot9=res_o[9] + res_or[9],
    nr10=res_o[10],
    tot10=res_o[10] + res_or[10],
    nr11=res_o[11],
    tot11=res_o[11] + res_or[11],
    nr12=res_o[12],
    tot12=res_o[12] + res_or[12],
    nr13 = res_o[13],
    tot13 = res_o[13] + res_or[13],
    nr14=res_o[14],
    tot14=res_o[14] + res_or[14],
    nr15=res_o[15],
    tot15=res_o[15] + res_or[15],
    nr416 = res_o[416],
    tot416 = res_o[416] + res_or[416],
    nr417 = res_o[417],
    tot417 = res_o[417] + res_or[417],
    nr418 = res_o[418],
    tot418 = res_o[418] + res_or[418],
    nr828 = res_o[828],
    tot828 = res_o[828] + res_or[828],
    nr829 = res_o[829],
    tot829 = res_o[829] + res_or[829],
    nr1600 = res_o[1600],
    tot1600 = res_o[1600] + res_or[1600],
    nr1601 = res_o[1601],
    tot1601 = res_o[1601] + res_or[1601],
    nr2600 = res_o[2600],
    tot2600 = res_o[2600] + res_or[2600],
    nr3604 = res_o[3604],
    tot3604 = res_o[3604] + res_or[3604],
    nr3605 = res_o[3605],
    tot3605 = res_o[3605] + res_or[3605],
    total_user = '?',
    login_user = total_user,
    u_2021 = u_2021,
    u_2022 = u_2022,
    d7_user = len(rcusers7['user'])+len(rcusers7['anon']),
    d7_login_user = len(rcusers7['user']),
    d30_user= len(rcusers30['user'])+len(rcusers30['anon']),
    d30_login_user= len(rcusers30['user']),
    d7_count_edit = rctypes7['edit'],
    d7_count_new = rctypes7['new'],
    d7_count_log = rctypes7['log'],
    d30_count_edit = rctypes30['edit'],
    d30_count_new = rctypes30['new'],
    d30_count_log = rctypes30['log'],
    user_c0 = user_by_contribs['0'],
    user_c1 = user_by_contribs['1'],
    user_c20 = user_by_contribs['20'],
    user_c100 = user_by_contribs['100'],
    user_c200 = user_by_contribs['200'],
    user_c500 = user_by_contribs['500'],
    user_c1000 = user_by_contribs['1000'],
    user_c2000 = user_by_contribs['2000'],
    user_c5000 = user_by_contribs['5000'],
    user_c10000 = user_by_contribs['10000'],
    user_c20000 = user_by_contribs['20000'],
    user_c50000 = user_by_contribs['50000'],
    user_uc0 = user_uc0,
    user_uc5 = user_uc5,
    user_uc20 = user_uc20,
    user_uc50 = user_uc50,
    user_uc100 = user_uc100,
    user_uc500 = user_uc500,
)

page.save('봇: 리브레 위키 상세통계 작업 추가')