Habrastatistics: ferkenne de meast en minst besochte seksjes fan 'e side

Hoi Habr.

В foarige diel Habr's ferkear waard analysearre neffens de wichtichste parameters - it oantal artikels, har werjeften en wurdearrings. It probleem fan 'e populariteit fan' e side-seksjes bleau lykwols net ûndersocht. It waard ynteressant om dit yn mear detail te besjen en de populêrste en ûnpopulêre hubs te finen. Uteinlik sil ik it geektimes-effekt yn mear detail besjen, en einigje mei in nije seleksje fan 'e bêste artikels basearre op nije ranglist.

Habrastatistics: ferkenne de meast en minst besochte seksjes fan 'e side

Foar dyjingen dy't ynteressearre binne yn wat der bard is, is it ferfolch ûnder de knipe.

Lit my jo nochris herinnerje dat de statistiken en wurdearrings net offisjeel binne, ik haw gjin ynsiderynformaasje. It is ek net garandearre dat ik net earne in flater makke of wat miste. Mar dochs, ik tink dat it is nijsgjirrich. Wy sille earst begjinne mei de koade; dyjingen dy't net ynteressearre binne yn dit kinne de earste seksjes oerslaan.

Data kolleksje

Yn 'e earste ferzje fan' e parser waard allinich rekken holden mei it oantal werjeften, opmerkings en artikelwurdearrings. Dit is al goed, mar it lit jo net mear komplekse fragen meitsje. It is tiid om de tematyske seksjes fan 'e side te analysearjen; dit sil jo frij ynteressant ûndersyk kinne dwaan, bygelyks te sjen hoe't de populariteit fan 'e seksje "C ++" is feroare oer ferskate jierren.

De artikelparser is ferbettere, no jout it de hubs werom dêr't it artikel by heart, lykas de bynamme fan de skriuwer en syn wurdearring (hjir kinne ek in protte nijsgjirrige dingen dien wurde, mar dat komt letter). De gegevens wurde bewarre yn in csv-bestân dat der sa útsjocht:

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

Wy sille in list krije mei de wichtichste tematyske hubs fan 'e side.

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)

De funksje find_between en de Str-klasse selektearje in tekenrige tusken twa tags, ik brûkte se earder. Tematyske hubs binne markearre mei in "*", sadat se maklik wurde markearre, en jo kinne ek de oerienkommende rigels uncommentearje om seksjes fan oare kategoryen te krijen.

De útfier fan 'e get_hubs-funksje is in frij yndrukwekkende list, dy't wy bewarje as in wurdboek. Ik presintearje spesifyk de list yn syn gehiel, sadat jo it folume kinne skatte.

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

Foar fergeliking sjogge de seksjes fan geektimes beskiedener:

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

De oerbleaune hubs waarden op deselde wize bewarre. No is it maklik om in funksje te skriuwen dy't it resultaat werombringt of it artikel heart ta geektimes of in profylhub.

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

Fergelykbere funksjes waarden makke foar oare seksjes ("ûntwikkeling", "administraasje", ensfh.).

Ferwurkjen

It is tiid om te begjinnen mei analysearjen. Wy laden de dataset en ferwurkje de hubgegevens.

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)

No kinne wy ​​​​de gegevens per dei groepearje en it oantal publikaasjes foar ferskate hubs werjaan.

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

Wy litte it oantal publisearre artikels sjen mei Matplotlib:

Habrastatistics: ferkenne de meast en minst besochte seksjes fan 'e side

Ik ferdield de artikels "geektimes" en "geektimes allinne" yn 'e grafyk, omdat In artikel kin tagelyk ta beide seksjes hearre (bygelyks "DIY" + "microcontrollers" + "C++"). Ik brûkte de oantsjutting "profyl" om profylartikels op 'e side te markearjen, hoewol miskien de Ingelske term profyl hjirfoar net hielendal korrekt is.

Yn it foarige diel hawwe wy frege oer it "geektimes-effekt" ferbûn mei de feroaring yn 'e betellingsregels foar artikels foar geektimes dy't dizze simmer begjinne. Litte wy de geektimes-artikels apart sjen litte:

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

It resultaat is nijsgjirrich. De ûngefear ferhâlding fan werjeften fan geektimes-artikels oan it totaal is earne om 1:5. Mar wylst it totale oantal views merkber fluktuearre, it besjen fan "entertainment" artikels bleau op likernôch itselde nivo.

Habrastatistics: ferkenne de meast en minst besochte seksjes fan 'e side

Jo kinne ek merke dat it totale oantal werjeften fan artikels yn 'e seksje "geektimes" noch foel nei it feroarjen fan de regels, mar "troch it each", mei net mear as 5% fan 'e totale wearden.

It is nijsgjirrich om te sjen nei it gemiddelde oantal werjeften per artikel:

Habrastatistics: ferkenne de meast en minst besochte seksjes fan 'e side

Foar "entertainment" artikels is it sa'n 40% boppe gemiddeld. Dit is wierskynlik net ferrassend. It mislearjen oan it begjin fan april is my ûndúdlik, miskien is dat wat bard, of it is in soarte fan parseerflater, of miskien gie ien fan 'e geektime-auteurs op fakânsje ;).

Trouwens, de grafyk toant twa mear opfallende peaks yn it oantal artikelwerjeften - de Nijjiers- en maaiefakânsje.

Hubs

Litte wy trochgean nei de taseine analyse fan hubs. Litte wy de top 20 hubs listje op oantal werjeften:

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

Resultaat:

Habrastatistics: ferkenne de meast en minst besochte seksjes fan 'e side

Ferrassend wie de populêrste hub yn termen fan werjeften "Ynformaasjefeiligens"; de top 5-lieders omfetten ek "Programmering" en "Populêre wittenskip".

Antitop beslacht Gtk en Cocoa.

Habrastatistics: ferkenne de meast en minst besochte seksjes fan 'e side

Ik sil jo in geheim fertelle, de boppeste hubs kinne ek sjoen wurde hjir, hoewol it oantal werjeften dêr net werjûn wurdt.

Rating

En as lêste, de taseine wurdearring. Mei hubanalysegegevens kinne wy ​​de populêrste artikels werjaan foar de populêrste hubs foar dit jier 2019.

Ynformaasje Security

Programming

Populêre wittenskip

Karriêre

Wetjouwing yn IT

Web ûntwikkeling

GTK

En as lêste, sadat gjinien misledige wurdt, sil ik de wurdearring fan 'e minst besochte hub "gtk" jaan. Binnen in jier waard it publisearre одна It artikel, dat ek "automatysk" beslacht de earste rigel fan 'e wurdearring.

konklúzje

Der sil gjin konklúzje wêze. Lokkich lêzen elkenien.

Boarne: www.habr.com

Add a comment