Хабрастатистика: омӯхтани бахшҳои аз ҳама бештар ва камтар диданшудаи сайт

Салом, Хабр.

В қисми қаблӣ Ҳаракати Ҳабр аз рӯи параметрҳои асосӣ - шумораи мақолаҳо, назарҳо ва рейтингҳои онҳо таҳлил карда шуд. Аммо, масъалаи маъруфияти бахшҳои сайт бетаъхир боқӣ монд. Ба ин муфассалтар назар кардан ва пайдо кардани марказҳои маъмултарин ва маъмултарин ҷолиб буд. Дар ниҳоят, ман эффекти geektimes-ро муфассалтар дида мебароям ва бо интихоби нави мақолаҳои беҳтарин дар асоси рейтингҳои нав ба охир мерасам.

Хабрастатистика: омӯхтани бахшҳои аз ҳама бештар ва камтар диданшудаи сайт

Барои онҳое, ки манфиатдор дар он чӣ рӯй дод, идомаи зери набуред.

Бори дигар хотиррасон мекунам, ки омор ва рейтингҳо расмӣ нестанд, ман ягон маълумоти инсайдерӣ надорам. Инчунин кафолат дода намешавад, ки ман дар ҷое хато накардаам ё чизеро аз даст надодаам. Аммо ба ҳар ҳол, ман фикр мекунам, ки он ҷолиб шуд. Мо аввал бо код оғоз мекунем, онҳое, ки ба ин таваҷҷӯҳ надоранд, метавонанд қисмҳои аввалро гузаред.

Ҷамъоварии маълумот

Дар версияи якуми таҳлилгар танҳо шумораи диданҳо, шарҳҳо ва рейтинги мақолаҳо ба назар гирифта шудааст. Ин аллакай хуб аст, аммо он ба шумо имкон намедиҳад, ки дархостҳои мураккабтар кунед. Вақти он расидааст, ки қисматҳои мавзӯии сайтро таҳлил кунед, ин ба шумо имкон медиҳад, ки тадқиқоти ҷолибро анҷом диҳед, масалан, бубинед, ки маъруфияти бахши "C++" дар тӯли чанд сол чӣ гуна тағйир ёфтааст.

Таҳлилгари мақола такмил дода шуд, ҳоло он марказҳоеро, ки мақола ба онҳо тааллуқ дорад, инчунин лақаби муаллиф ва рейтинги ӯро бармегардонад (дар ин ҷо низ бисёр чизҳои ҷолибро кардан мумкин аст, аммо ин баъдтар меояд). Маълумот дар файли csv захира карда мешавад, ки чунин менамояд:

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
...

Мо рӯйхати марказҳои асосии мавзӯии сайтро мегирем.

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 ва синфи Str сатри байни ду тегро интихоб мекунад, ман онҳоро истифода кардам пештар. Марказҳои мавзӯӣ бо аломати "*" ишора карда мешаванд, то онҳо ба осонӣ таъкид карда шаванд ва шумо инчунин метавонед сатрҳои мувофиқро барои гирифтани бахшҳои категорияҳои дигар шарҳ диҳед.

Натиҷаи функсияи get_hubs рӯйхати хеле таъсирбахш аст, ки мо онро ҳамчун луғат захира мекунем. Ман махсусан рӯйхатро пурра пешниҳод мекунам, то шумо ҳаҷми онро тахмин кунед.

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'}

Барои муқоиса, бахшҳои geektimes хоксортаранд:

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'}

Марказҳои боқимонда низ ҳамин тавр нигоҳ дошта шуданд. Ҳоло навиштани функсияе осон аст, ки натиҷаро баргардонад, оё мақола ба geektimes ё маркази профилӣ тааллуқ дорад.

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

Чунин вазифаҳо барои бахшҳои дигар («рушд», «идоракунӣ» ва ғ.) иҷро карда шуданд.

Коркард

Вақти он расидааст, ки таҳлилро оғоз кунед. Мо маҷмӯи маълумотро бор мекунем ва маълумоти марказро коркард мекунем.

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)

Акнун мо метавонем маълумотро аз рӯи рӯз гурӯҳбандӣ кунем ва шумораи нашрияҳоро барои марказҳои гуногун нишон диҳем.

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()

Мо шумораи мақолаҳои нашршударо бо истифода аз Matplotlib нишон медиҳем:

Хабрастатистика: омӯхтани бахшҳои аз ҳама бештар ва камтар диданшудаи сайт

Ман мақолаҳои "geektimes" ва "geektimes танҳо" -ро дар диаграмма тақсим кардам, зеро Мақола метавонад дар як вақт ба ҳарду бахш тааллуқ дошта бошад (масалан, "DIY" + "микроконтроллерҳо" + "C++"). Ман таъиноти "профил" -ро барои таъкид кардани мақолаҳои профилӣ дар сайт истифода кардам, гарчанде ки истилоҳи профили англисӣ барои ин комилан дуруст нест.

Дар қисми қаблӣ мо дар бораи "эффектҳои geektimes" пурсидем, ки бо тағир додани қоидаҳои пардохт барои мақолаҳо барои Geektimes аз тобистони имсол оғоз мешавад. Биёед мақолаҳои geektimes-ро алоҳида намоиш диҳем:

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()

Натиҷа ҷолиб аст. Таносуби тахминии назари мақолаҳои Geektimes ба шумораи умумӣ тақрибан 1:5 аст. Аммо дар ҳоле ки шумораи умумии тамошобинон ба таври қобили мулоҳиза тағйир меёфт, тамошои матолиби “тафреҳӣ” тақрибан дар ҳамон сатҳ боқӣ мондааст.

Хабрастатистика: омӯхтани бахшҳои аз ҳама бештар ва камтар диданшудаи сайт

Шумо инчунин метавонед аҳамият диҳед, ки шумораи умумии дидани мақолаҳо дар бахши "geektimes" пас аз тағир додани қоидаҳо то ҳол коҳиш ёфтааст, аммо "бо чашм" на бештар аз 5% арзишҳои умумӣ.

Ҷолиб аст, ки ба шумораи миёнаи тамошои як мақола нигаред:

Хабрастатистика: омӯхтани бахшҳои аз ҳама бештар ва камтар диданшудаи сайт

Барои мақолаҳои "фароғатӣ" он тақрибан 40% аз ҳисоби миёна аст. Ин шояд тааҷҷубовар нест. Нокомӣ дар аввали моҳи апрел барои ман норавшан аст, шояд ҳамин тавр бошад, ё ин як навъ хатогии таҳлил аст ё шояд яке аз муаллифони Geektimes ба таътил рафта бошад;).

Дар омади гап, график боз ду қуллаи назарраси шумораи тамошои мақолаҳоро нишон медиҳад - ҷашнҳои Соли нав ва Май.

Хабҳо

Биёед ба таҳлили ваъдашудаи марказҳо гузарем. Биёед 20 маркази беҳтаринро аз рӯи шумораи диданҳо номбар кунем:

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()

Натиҷа:

Хабрастатистика: омӯхтани бахшҳои аз ҳама бештар ва камтар диданшудаи сайт

Тааҷҷубовар аст, ки маркази маъмултарин аз нигоҳи назарҳо "Амнияти иттилоотӣ" буд;

Antitop Gtk ва Cocoa-ро ишғол мекунад.

Хабрастатистика: омӯхтани бахшҳои аз ҳама бештар ва камтар диданшудаи сайт

Ман ба шумо сирро мегӯям, марказҳои болоро низ дидан мумкин аст дар ин ҷо, гарчанде ки шумораи тамошобинон дар он чо нишон дода нашудааст.

Рейтинг

Ва ниҳоят, рейтинги ваъдашуда. Бо истифода аз маълумоти таҳлили марказ, мо метавонем мақолаҳои маъмултаринро барои марказҳои маъмултарин дар соли 2019 намоиш диҳем.

Амнияти иттилоот

Барномасозӣ

Илми оммавӣ

Карера

Қонунгузорӣ дар соҳаи IT

Таҳияи веб

GTK

Ва дар охир, то касе хафа нашавад, ман рейтинги маркази камтар боздидшуда "gtk" -ро медиҳам. Дар давоми як сол он нашр шуд як Мақола, ки он низ "ба таври худкор" сатри аввали рейтингро ишғол мекунад.

хулоса

Хулоса нахоҳад буд. Хониши ҳама муборак.

Манбаъ: will.com

Илова Эзоҳ