Habrastatistics. ուսումնասիրել կայքի ամենաշատ և ամենաքիչ այցելվող հատվածները

Հե՜յ Հաբր։

В նախորդ մասը Habr-ի տրաֆիկը վերլուծվել է ըստ հիմնական պարամետրերի՝ հոդվածների քանակի, դրանց դիտումների և վարկանիշների։ Այնուամենայնիվ, կայքի բաժինների հանրաճանաչության հարցը մնաց չքննված։ Հետաքրքիր դարձավ ավելի մանրամասն նայել այս ամենին և գտնել ամենահայտնի և ոչ հանրաճանաչ կենտրոնները: Ի վերջո, ես ավելի մանրամասն կանդրադառնամ geektimes-ի էֆեկտին, որը կավարտվի նոր վարկանիշների հիման վրա լավագույն հոդվածների նոր ընտրությամբ:

Habrastatistics. ուսումնասիրել կայքի ամենաշատ և ամենաքիչ այցելվող հատվածները

Տեղի ունեցածով հետաքրքրվողների համար շարունակությունը կտրվածքի տակ է.

Եվս մեկ անգամ հիշեցնեմ, որ վիճակագրությունը և վարկանիշները պաշտոնական չեն, ես որևէ ինսայդերային տեղեկություն չունեմ։ Նաև երաշխավորված չէ, որ ես ինչ-որ տեղ չեմ սխալվել կամ ինչ-որ բան բաց չեմ թողել։ Բայց այնուամենայնիվ, կարծում եմ, որ հետաքրքիր է ստացվել։ Մենք նախ կսկսենք ծածկագրից, նրանք, ում դա չի հետաքրքրում, կարող են բաց թողնել առաջին բաժինները:

Տվյալների հավաքագրումը

Վերլուծիչի առաջին տարբերակում հաշվի է առնվել միայն դիտումների քանակը, մեկնաբանությունները և հոդվածների վարկանիշները։ Սա արդեն լավ է, բայց թույլ չի տալիս ավելի բարդ հարցումներ կատարել։ Ժամանակն է վերլուծել կայքի թեմատիկ բաժինները, սա թույլ կտա բավականին հետաքրքիր հետազոտություններ կատարել, օրինակ՝ տեսնել, թե ինչպես է փոխվել «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.

Habrastatistics. ուսումնասիրել կայքի ամենաշատ և ամենաքիչ այցելվող հատվածները

Ես բաժանեցի «geektimes» և «geektimes only» հոդվածները աղյուսակում, քանի որ Հոդվածը կարող է պատկանել միաժամանակ երկու բաժիններին (օրինակ՝ «DIY» + «microcontrollers» + «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 է: Բայց մինչ դիտումների ընդհանուր թիվը նկատելիորեն տատանվում էր, «ժամանցային» հոդվածների դիտումը մնացել է մոտավորապես նույն մակարդակի վրա։

Habrastatistics. ուսումնասիրել կայքի ամենաշատ և ամենաքիչ այցելվող հատվածները

Կարող եք նաև նկատել, որ «geektimes» բաժնում հոդվածների ընդհանուր դիտումների թիվը կանոնները փոխելուց հետո դեռ նվազել է, բայց «աչքով»՝ ընդհանուր արժեքների 5%-ից ոչ ավելի։

Հետաքրքիր է դիտել մեկ հոդվածի դիտումների միջին թիվը.

Habrastatistics. ուսումնասիրել կայքի ամենաշատ և ամենաքիչ այցելվող հատվածները

«Ժամանցային» հոդվածների համար այն միջինից մոտ 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()

Արդյունքը:

Habrastatistics. ուսումնասիրել կայքի ամենաշատ և ամենաքիչ այցելվող հատվածները

Զարմանալիորեն, դիտումների առումով ամենահայտնի կենտրոնը եղել է «Տեղեկատվական անվտանգությունը», լավագույն 5 առաջատարների թվում են նաև «Ծրագրավորումը» և «Հանրաճանաչ գիտությունը»:

Անտիտոպը զբաղեցնում է Գտկը և Կակաոն։

Habrastatistics. ուսումնասիրել կայքի ամենաշատ և ամենաքիչ այցելվող հատվածները

Գաղտնիք կասեմ, վերին հանգույցներն էլ են երեւում այստեղ, չնայած դիտումների քանակը այնտեղ ցուցադրված չէ։

Գնահատական

Եվ վերջապես՝ խոստացված վարկանիշը. Օգտագործելով հանգույցների վերլուծության տվյալները՝ մենք կարող ենք ցուցադրել այս 2019 թվականի ամենահայտնի հանգույցների ամենահայտնի հոդվածները:

Տեղեկատվական անվտանգություն

Ծրագրավորում

Հանրաճանաչ գիտություն

կարիերա

Օրենսդրությունը ՏՏ ոլորտում

Վեբ մշակում

GTK

Եվ վերջապես, որպեսզի ոչ ոք չնեղանա, կտամ ամենաքիչ այցելվող «gtk» կենտրոնի վարկանիշը։ Մեկ տարվա ընթացքում այն ​​լույս է տեսել одна Հոդվածը, որը նույնպես «ավտոմատ կերպով» զբաղեցնում է վարկանիշի առաջին տողը։

Ամփոփում

Եզրակացություն չի լինելու. Ուրախ ընթերցում բոլորին:

Source: www.habr.com

Добавить комментарий