Habrastatistika: saytning eng ko'p va eng kam tashrif buyurilgan bo'limlarini o'rganish

Salom, Xabr.

В oldingi qism Xabrning trafigi asosiy parametrlar - maqolalar soni, ularning ko'rishlari va reytinglari bo'yicha tahlil qilindi. Biroq, sayt bo'limlarining mashhurligi masalasi o'rganilmagan holda qoldi. Buni batafsilroq ko'rib chiqish va eng mashhur va eng mashhur bo'lmagan markazlarni topish qiziq bo'ldi. Va nihoyat, men geektimes effektini batafsil ko'rib chiqaman va yangi reytinglar asosidagi eng yaxshi maqolalarning yangi tanlovi bilan yakunlayman.

Habrastatistika: saytning eng ko'p va eng kam tashrif buyurilgan bo'limlarini o'rganish

Nima bo'lganiga qiziqqanlar uchun davomi kesma ostida.

Yana bir bor eslatib o‘taman, statistika va reytinglar rasmiy emas, menda hech qanday insayder ma’lumot yo‘q. Shuningdek, biror joyda xato qilmaganim yoki biror narsani o'tkazib yubormaganligim kafolatlanmaydi. Lekin shunga qaramay, menimcha, bu qiziqarli bo'ldi. Biz avval koddan boshlaymiz, bunga qiziqmaganlar birinchi bo'limlarni o'tkazib yuborishlari mumkin.

Ma'lumotlar yig'ish

Tahlil qiluvchining birinchi versiyasida faqat ko'rishlar soni, sharhlar va maqola reytinglari hisobga olindi. Bu allaqachon yaxshi, lekin u sizga murakkabroq so'rovlarni amalga oshirishga imkon bermaydi. Saytning tematik bo'limlarini tahlil qilish vaqti keldi, bu sizga juda qiziqarli tadqiqotlar o'tkazishga imkon beradi, masalan, "C++" bo'limining mashhurligi bir necha yil ichida qanday o'zgarganini ko'ring.

Maqolani tahlil qilish moslamasi takomillashtirildi, endi u maqola tegishli bo'lgan markazlarni, shuningdek muallifning taxallusini va uning reytingini qaytaradi (bu erda ham juda ko'p qiziqarli narsalarni qilish mumkin, ammo bu keyinroq keladi). Ma'lumotlar csv faylida saqlanadi, u quyidagicha ko'rinadi:

2018-12-18T12:43Z,https://habr.com/ru/post/433550/,"Мессенджер Slack — причины выбора, косяки при внедрении и особенности сервиса, облегчающие жизнь",votes:7,votesplus:8,votesmin:1,bookmarks:32,
views:8300,comments:10,user:ReDisque,karma:5,subscribers:2,hubs:productpm+soft
...

Biz saytning asosiy tematik markazlari ro'yxatini olamiz.

def get_as_str(link: str) -> Str:
    try:
        r = requests.get(link)
        return Str(r.text)
    except Exception as e:
        return Str("")

def get_hubs():
    hubs = []
    for p in range(1, 12):
        page_html = get_as_str("https://habr.com/ru/hubs/page%d/" % p)
        # page_html = get_as_str("https://habr.com/ru/hubs/geektimes/page%d/" % p)  # Geektimes
        # page_html = get_as_str("https://habr.com/ru/hubs/develop/page%d/" % p)  # Develop
        # page_html = get_as_str("https://habr.com/ru/hubs/admin/page%d" % p)  # Admin
        for hub in page_html.split("media-obj media-obj_hub"):
            info = Str(hub).find_between('"https://habr.com/ru/hub', 'list-snippet__tags') 
            if "*</span>" in info:
                hub_name = info.find_between('/', '/"')
                if len(hub_name) > 0 and len(hub_name) < 32:
                    hubs.append(hub_name)
    print(hubs)

find_between funksiyasi va Str klassi ikkita teg orasidagi satrni tanlaydi, men ulardan foydalanardim oldinroq. Tematik markazlar "*" belgisi bilan belgilanadi, shuning uchun ularni osongina ajratib ko'rsatish mumkin, shuningdek, boshqa toifalar bo'limlarini olish uchun tegishli qatorlarni izohdan chiqarishingiz mumkin.

Get_hubs funktsiyasining chiqishi juda ta'sirli ro'yxat bo'lib, biz uni lug'at sifatida saqlaymiz. Uning hajmini taxmin qilishingiz uchun men ro'yxatni to'liq taqdim etaman.

hubs_profile = {'infosecurity', 'programming', 'webdev', 'python', 'sys_admin', 'it-infrastructure', 'devops', 'javascript', 'open_source', 'network_technologies', 'gamedev', 'cpp', 'machine_learning', 'pm', 'hr_management', 'linux', 'analysis_design', 'ui', 'net', 'hi', 'maths', 'mobile_dev', 'productpm', 'win_dev', 'it_testing', 'dev_management', 'algorithms', 'go', 'php', 'csharp', 'nix', 'data_visualization', 'web_testing', 's_admin', 'crazydev', 'data_mining', 'bigdata', 'c', 'java', 'usability', 'instant_messaging', 'gtd', 'system_programming', 'ios_dev', 'oop', 'nginx', 'kubernetes', 'sql', '3d_graphics', 'css', 'geo', 'image_processing', 'controllers', 'game_design', 'html5', 'community_management', 'electronics', 'android_dev', 'crypto', 'netdev', 'cisconetworks', 'db_admins', 'funcprog', 'wireless', 'dwh', 'linux_dev', 'assembler', 'reactjs', 'sales', 'microservices', 'search_technologies', 'compilers', 'virtualization', 'client_side_optimization', 'distributed_systems', 'api', 'media_management', 'complete_code', 'typescript', 'postgresql', 'rust', 'agile', 'refactoring', 'parallel_programming', 'mssql', 'game_promotion', 'robo_dev', 'reverse-engineering', 'web_analytics', 'unity', 'symfony', 'build_automation', 'swift', 'raspberrypi', 'web_design', 'kotlin', 'debug', 'pay_system', 'apps_design', 'git', 'shells', 'laravel', 'mobile_testing', 'openstreetmap', 'lua', 'vs', 'yii', 'sport_programming', 'service_desk', 'itstandarts', 'nodejs', 'data_warehouse', 'ctf', 'erp', 'video', 'mobileanalytics', 'ipv6', 'virus', 'crm', 'backup', 'mesh_networking', 'cad_cam', 'patents', 'cloud_computing', 'growthhacking', 'iot_dev', 'server_side_optimization', 'latex', 'natural_language_processing', 'scala', 'unreal_engine', 'mongodb', 'delphi',  'industrial_control_system', 'r', 'fpga', 'oracle', 'arduino', 'magento', 'ruby', 'nosql', 'flutter', 'xml', 'apache', 'sveltejs', 'devmail', 'ecommerce_development', 'opendata', 'Hadoop', 'yandex_api', 'game_monetization', 'ror', 'graph_design', 'scada', 'mobile_monetization', 'sqlite', 'accessibility', 'saas', 'helpdesk', 'matlab', 'julia', 'aws', 'data_recovery', 'erlang', 'angular', 'osx_dev', 'dns', 'dart', 'vector_graphics', 'asp', 'domains', 'cvs', 'asterisk', 'iis', 'it_monetization', 'localization', 'objectivec', 'IPFS', 'jquery', 'lisp', 'arvrdev', 'powershell', 'd', 'conversion', 'animation', 'webgl', 'wordpress', 'elm', 'qt_software', 'google_api', 'groovy_grails', 'Sailfish_dev', 'Atlassian', 'desktop_environment', 'game_testing', 'mysql', 'ecm', 'cms', 'Xamarin', 'haskell', 'prototyping', 'sw', 'django', 'gradle', 'billing', 'tdd', 'openshift', 'canvas', 'map_api', 'vuejs', 'data_compression', 'tizen_dev', 'iptv', 'mono', 'labview', 'perl', 'AJAX', 'ms_access', 'gpgpu', 'infolust', 'microformats', 'facebook_api', 'vba', 'twitter_api', 'twisted', 'phalcon', 'joomla', 'action_script', 'flex', 'gtk', 'meteorjs', 'iconoskaz', 'cobol', 'cocoa', 'fortran', 'uml', 'codeigniter', 'prolog', 'mercurial', 'drupal', 'wp_dev', 'smallbasic', 'webassembly', 'cubrid', 'fido', 'bada_dev', 'cgi', 'extjs', 'zend_framework', 'typography', 'UEFI', 'geo_systems', 'vim', 'creative_commons', 'modx', 'derbyjs', 'xcode', 'greasemonkey', 'i2p', 'flash_platform', 'coffeescript', 'fsharp', 'clojure', 'puppet', 'forth', 'processing_lang', 'firebird', 'javame_dev', 'cakephp', 'google_cloud_vision_api', 'kohanaphp', 'elixirphoenix', 'eclipse', 'xslt', 'smalltalk', 'googlecloud', 'gae', 'mootools', 'emacs', 'flask', 'gwt', 'web_monetization', 'circuit-design', 'office365dev', 'haxe', 'doctrine', 'typo3', 'regex', 'solidity', 'brainfuck', 'sphinx', 'san', 'vk_api', 'ecommerce'}

Taqqoslash uchun, geektimes bo'limlari oddiyroq ko'rinadi:

hubs_gt = {'popular_science', 'history', 'soft', 'lifehacks', 'health', 'finance', 'artificial_intelligence', 'itcompanies', 'DIY', 'energy', 'transport', 'gadgets', 'social_networks', 'space', 'futurenow', 'it_bigraphy', 'antikvariat', 'games', 'hardware', 'learning_languages', 'urban', 'brain', 'internet_of_things', 'easyelectronics', 'cellular', 'physics', 'cryptocurrency', 'interviews', 'biotech', 'network_hardware', 'autogadgets', 'lasers', 'sound', 'home_automation', 'smartphones', 'statistics', 'robot', 'cpu', 'video_tech', 'Ecology', 'presentation', 'desktops', 'wearable_electronics', 'quantum', 'notebooks', 'cyberpunk', 'Peripheral', 'demoscene', 'copyright', 'astronomy', 'arvr', 'medgadgets', '3d-printers', 'Chemistry', 'storages', 'sci-fi', 'logic_games', 'office', 'tablets', 'displays', 'video_conferencing', 'videocards', 'photo', 'multicopters', 'supercomputers', 'telemedicine', 'cybersport', 'nano', 'crowdsourcing', 'infographics'}

Qolgan markazlar xuddi shu tarzda saqlanib qolgan. Endi maqola geektimes yoki profil markaziga tegishlimi, natijani qaytaradigan funksiyani yozish oson.

def is_geektimes(hubs: List) -> bool:
    return len(set(hubs) & hubs_gt) > 0

def is_geektimes_only(hubs: List) -> bool:
    return is_geektimes(hubs) is True and is_profile(hubs) is False

def is_profile(hubs: List) -> bool:
    return len(set(hubs) & hubs_profile) > 0

Xuddi shunday funktsiyalar boshqa bo'limlar uchun ham amalga oshirildi ("ishlab chiqish", "ma'muriyat" va boshqalar).

ishlov berish

Tahlil qilishni boshlash vaqti keldi. Biz ma'lumotlar to'plamini yuklaymiz va hub ma'lumotlarini qayta ishlaymiz.

def to_list(s: str) -> List[str]:
    # "user:popular_science+astronomy" => [popular_science, astronomy]
    return s.split(':')[1].split('+')

def to_date(dt: datetime) -> datetime.date:
    return dt.date()

df = pd.read_csv("habr_2019.csv", sep=',', encoding='utf-8', error_bad_lines=True, quotechar='"', comment='#')
dates = pd.to_datetime(df['datetime'], format='%Y-%m-%dT%H:%MZ')
dates += datetime.timedelta(hours=3)
df['date'] = dates.map(to_date, na_action=None)
hubs = df["hubs"].map(to_list, na_action=None)
df['hubs'] = hubs
df['is_profile'] = hubs.map(is_profile, na_action=None)
df['is_geektimes'] = hubs.map(is_geektimes, na_action=None)
df['is_geektimes_only'] = hubs.map(is_geektimes_only, na_action=None)
df['is_admin'] = hubs.map(is_admin, na_action=None)
df['is_develop'] = hubs.map(is_develop, na_action=None)

Endi biz ma'lumotlarni kun bo'yicha guruhlashimiz va turli markazlar uchun nashrlar sonini ko'rsatishimiz mumkin.

g = df.groupby(['date'])
days_count = g.size().reset_index(name='counts')
year_days = days_count['date'].values
grouped = g.sum().reset_index()
profile_per_day_avg = grouped['is_profile'].rolling(window=20, min_periods=1).mean()
geektimes_per_day_avg = grouped['is_geektimes'].rolling(window=20, min_periods=1).mean()
geektimesonly_per_day_avg = grouped['is_geektimes_only'].rolling(window=20, min_periods=1).mean()
admin_per_day_avg = grouped['is_admin'].rolling(window=20, min_periods=1).mean()
develop_per_day_avg = grouped['is_develop'].rolling(window=20, min_periods=1).mean()

Biz Matplotlib yordamida chop etilgan maqolalar sonini ko'rsatamiz:

Habrastatistika: saytning eng ko'p va eng kam tashrif buyurilgan bo'limlarini o'rganish

Men "geektimes" va "faqat geektimes" maqolalarini jadvalda ajratdim, chunki Maqola bir vaqtning o'zida ikkala bo'limga tegishli bo'lishi mumkin (masalan, "DIY" + "mikrokontrollerlar" + "C++"). Saytdagi profil maqolalarini ta'kidlash uchun men "profil" belgisidan foydalandim, garchi buning inglizcha profil atamasi mutlaqo to'g'ri emas.

Oldingi qismda biz bu yozdan boshlab geektimes uchun maqolalar uchun to'lov qoidalarining o'zgarishi bilan bog'liq "geektimes effekti" haqida so'radik. Keling, geektimes maqolalarini alohida ko'rsatamiz:

df_gt = df[(df['is_geektimes_only'] == True)]
group_gt = df_gt.groupby(['date'])
days_count_gt = group_gt.size().reset_index(name='counts')
grouped = group_gt.sum().reset_index()
year_days_gt = days_count_gt['date'].values
view_gt_per_day_avg = grouped['views'].rolling(window=20, min_periods=1).mean()

Natija qiziq. Geektimes maqolalarini ko'rishlar sonining umumiy soniga taxminiy nisbati 1:5 atrofida. Ko'rishlarning umumiy soni sezilarli darajada o'zgargan bo'lsa-da, "ko'ngilochar" maqolalarni ko'rish taxminan bir xil darajada qoldi.

Habrastatistika: saytning eng ko'p va eng kam tashrif buyurilgan bo'limlarini o'rganish

Shuningdek, "geektimes" bo'limidagi maqolalarni ko'rishlar soni qoidalar o'zgartirilgandan keyin ham pasayganini, ammo "ko'z bilan" umumiy qiymatlarning 5% dan ko'p bo'lmaganiga e'tibor berishingiz mumkin.

Har bir maqolaning o'rtacha ko'rishlar sonini ko'rish qiziq:

Habrastatistika: saytning eng ko'p va eng kam tashrif buyurilgan bo'limlarini o'rganish

"O'yin-kulgi" maqolalari uchun bu o'rtacha 40% dan yuqori. Bu, ehtimol, ajablanarli emas. Aprel oyining boshidagi muvaffaqiyatsizlik men uchun tushunarsiz, ehtimol shunday bo'lgandir yoki bu qandaydir tahlil qilish xatosi yoki geektimes mualliflaridan biri ta'tilga ketgandir;).

Aytgancha, grafik maqolalarni ko'rish sonining yana ikkita sezilarli cho'qqisini ko'rsatadi - Yangi yil va may bayramlari.

Hublar

Keling, markazlarning va'da qilingan tahliliga o'tamiz. Keling, ko'rishlar soni bo'yicha eng yaxshi 20 ta markazni sanab o'tamiz:

hubs_info = []
for hub_name in hubs_all:
    mask = df['hubs'].apply(lambda x: hub_name in x)
    df_hub = df[mask]

    count, views = df_hub.shape[0], df_hub['views'].sum()
    hubs_info.append((hub_name, count, views))

# Draw hubs
hubs_top = sorted(hubs_info, key=lambda v: v[2], reverse=True)[:20]
top_views = list(map(lambda x: x[2], hubs_top))
top_names = list(map(lambda x: x[0], hubs_top))

plt.rcParams["figure.figsize"] = (8, 6)
plt.bar(range(0, len(top_views)), top_views)
plt.xticks(range(0, len(top_names)), top_names, rotation=90)
plt.ticklabel_format(style='plain', axis='y')
plt.tight_layout()
plt.show()

natija:

Habrastatistika: saytning eng ko'p va eng kam tashrif buyurilgan bo'limlarini o'rganish

Ajablanarlisi shundaki, ko'rishlar bo'yicha eng mashhur markaz "Axborot xavfsizligi" bo'ldi;

Antitop Gtk va Kakaoni egallaydi.

Habrastatistika: saytning eng ko'p va eng kam tashrif buyurilgan bo'limlarini o'rganish

Men sizga bir sirni aytaman, yuqori markazlarni ham ko'rish mumkin shu yerda, garchi u yerda ko'rishlar soni ko'rsatilmagan bo'lsa-da.

Reyting

Va nihoyat, va'da qilingan reyting. Hub tahlili ma'lumotlaridan foydalanib, biz 2019 yil uchun eng mashhur markazlar uchun eng mashhur maqolalarni ko'rsatishimiz mumkin.

Axborot xavfsizligi

Dasturlash

Ommaviy fan

Ishga qabul qilish

IT sohasidagi qonunchilik

Veb ishlab chiqish

GTK

Va nihoyat, hech kim xafa bo'lmasligi uchun men eng kam tashrif buyurilgan "gtk" markazining reytingini beraman. Bir yil ichida u nashr etildi одна Maqola, shuningdek, "avtomatik" reytingning birinchi qatorini egallaydi.

xulosa

Xulosa bo'lmaydi. Hammaga baxtli o'qish.

Manba: www.habr.com

a Izoh qo'shish