Habrastatistics: сайттын эң көп жана эң аз кирген бөлүмдөрүн изилдөө

Эй Хабр.

В мурунку бөлүгү Хабрдын трафики негизги параметрлер боюнча талданган - макалалардын саны, алардын көз караштары жана рейтинги. Бирок, сайт бөлүмдөрүнүн популярдуулугу маселеси каралбай калган. Муну кененирээк карап чыгуу жана эң популярдуу жана эң популярдуу эмес хабтарды табуу кызыктуу болду. Акырында, мен жаңы рейтингдердин негизинде мыкты макалалардын жаңы тандоосу менен аяктап, 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 гана" макалаларын бөлдүм, анткени Макала бир эле учурда эки бөлүмгө тең тиешелүү болушу мүмкүн (мисалы, "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тин тегерегинде. Бирок көрүүлөрдүн жалпы саны байкаларлык өзгөрүп турганы менен, "көңүл ачуучу" макалаларды көрүү болжол менен бирдей деңгээлде калган.

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: сайттын эң көп жана эң аз кирген бөлүмдөрүн изилдөө

Таң калыштуусу, көз караштар боюнча эң популярдуу борбор болуп "Маалымат коопсуздугу" болгон;

Antitop Gtk жана Какаону ээлейт.

Habrastatistics: сайттын эң көп жана эң аз кирген бөлүмдөрүн изилдөө

Мен сизге сыр айтам, жогорку түйүндөрдү да көрүүгө болот бул жерде, ал жерде көрүүлөрдүн саны көрсөтүлбөсө да.

рейтинг

Акыр-аягы, убадаланган рейтинг. Хаб талдоо маалыматтарын колдонуу менен, биз 2019-жылдын эң популярдуу хабтары үчүн эң популярдуу макалаларды көрсөтө алабыз.

Маалымат коопсуздугу

программалоо

Популярдуу илим

мансап

IT чөйрөсүндөгү мыйзамдар

Вебди иштеп чыгуу

GTK

Акыр-аягы, эч ким таарынбашы үчүн, мен эң аз кирген хабдын рейтингин "gtk" берем. Бир жылдын ичинде ал басылып чыкты одна макала, ошондой эле "автоматтык түрдө" рейтингдин биринчи сабын ээлейт.

жыйынтыктоо

Эч кандай жыйынтык болбойт. Баарыңарга бактылуу окуу.

Source: www.habr.com

Комментарий кошуу