Habrastatistik: Erkundung der am häufigsten und am wenigsten besuchten Bereiche der Website

Hallo Habr.

В vorherigen Abschnitt Der Verkehr von Habr wurde anhand der Hauptparameter analysiert – der Anzahl der Artikel, deren Aufrufe und Bewertungen. Die Frage nach der Beliebtheit der Seitenabschnitte blieb jedoch ungeklärt. Es wurde interessant, dies genauer zu betrachten und die beliebtesten und unbeliebtesten Hubs zu finden. Abschließend werde ich den Geektimes-Effekt genauer betrachten und mit einer neuen Auswahl der besten Artikel auf Basis neuer Rankings abschließen.

Habrastatistik: Erkundung der am häufigsten und am wenigsten besuchten Bereiche der Website

Für diejenigen, die sich für das Geschehene interessieren: Die Fortsetzung ist unter Verschluss.

Ich möchte Sie noch einmal daran erinnern, dass die Statistiken und Bewertungen nicht offiziell sind und mir keine Insiderinformationen vorliegen. Es ist auch nicht garantiert, dass ich nicht irgendwo einen Fehler gemacht oder etwas übersehen habe. Dennoch finde ich, dass es interessant geworden ist. Wir beginnen zunächst mit dem Code; wer sich nicht dafür interessiert, kann die ersten Abschnitte überspringen.

Datensammlung

In der ersten Version des Parsers wurden nur die Anzahl der Aufrufe, Kommentare und Artikelbewertungen berücksichtigt. Das ist schon gut, erlaubt aber keine komplexeren Abfragen. Es ist an der Zeit, die thematischen Abschnitte der Website zu analysieren. Auf diese Weise können Sie recht interessante Recherchen durchführen und beispielsweise sehen, wie sich die Beliebtheit des Abschnitts „C++“ über mehrere Jahre hinweg verändert hat.

Der Artikelparser wurde verbessert, er gibt jetzt die Hubs zurück, zu denen der Artikel gehört, sowie den Spitznamen des Autors und seine Bewertung (hier kann man auch viele interessante Dinge tun, aber das kommt später). Die Daten werden in einer CSV-Datei gespeichert, die etwa so aussieht:

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

Wir erhalten eine Liste der wichtigsten thematischen Schwerpunkte der Website.

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)

Die Funktion find_between und die Klasse Str wählen einen String zwischen zwei Tags aus, ich habe sie verwendet früher. Themenschwerpunkte sind mit einem „*“ gekennzeichnet, sodass sie leicht hervorgehoben werden können. Sie können die entsprechenden Zeilen auch auskommentieren, um Abschnitte anderer Kategorien zu erhalten.

Die Ausgabe der get_hubs-Funktion ist eine ziemlich beeindruckende Liste, die wir als Wörterbuch speichern. Ich präsentiere die Liste ausdrücklich in ihrer Gesamtheit, damit Sie den Umfang abschätzen können.

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

Zum Vergleich: Die Geektimes-Abschnitte sehen bescheidener aus:

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

Die übrigen Naben wurden auf die gleiche Weise konserviert. Jetzt ist es einfach, eine Funktion zu schreiben, die das Ergebnis zurückgibt, unabhängig davon, ob der Artikel zu Geektimes oder einem Profil-Hub gehört.

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

Ähnliche Funktionen wurden für andere Bereiche („Entwicklung“, „Verwaltung“ usw.) erstellt.

Verarbeitung

Es ist Zeit, mit der Analyse zu beginnen. Wir laden den Datensatz und verarbeiten die Hub-Daten.

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)

Jetzt können wir die Daten nach Tagen gruppieren und die Anzahl der Veröffentlichungen für verschiedene Hubs anzeigen.

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

Wir zeigen die Anzahl der veröffentlichten Artikel mit Matplotlib an:

Habrastatistik: Erkundung der am häufigsten und am wenigsten besuchten Bereiche der Website

Ich habe die Artikel „Geektimes“ und „Nur Geektimes“ in der Tabelle unterteilt, weil Ein Artikel kann gleichzeitig zu beiden Rubriken gehören (zum Beispiel „DIY“ + „Mikrocontroller“ + „C++“). Ich habe die Bezeichnung „Profil“ verwendet, um Profilartikel auf der Website hervorzuheben, obwohl der englische Begriff „Profil“ dafür möglicherweise nicht ganz korrekt ist.

Im vorherigen Teil haben wir nach dem „Geektimes-Effekt“ gefragt, der mit der Änderung der Zahlungsregeln für Artikel für Geektimes ab diesem Sommer verbunden ist. Lassen Sie uns die Geektimes-Artikel separat anzeigen:

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

Das Ergebnis ist interessant. Das ungefähre Verhältnis der Aufrufe von Geektimes-Artikeln zur Gesamtzahl liegt bei etwa 1:5. Doch während die Gesamtzahl der Aufrufe deutlich schwankte, blieb die Betrachtung von „Unterhaltungs“-Artikeln in etwa auf dem gleichen Niveau.

Habrastatistik: Erkundung der am häufigsten und am wenigsten besuchten Bereiche der Website

Sie können auch feststellen, dass die Gesamtzahl der Aufrufe von Artikeln im Bereich „Geektimes“ nach der Änderung der Regeln immer noch gesunken ist, jedoch „nach Augenmaß“ um nicht mehr als 5 % der Gesamtwerte.

Es ist interessant, sich die durchschnittliche Anzahl der Aufrufe pro Artikel anzusehen:

Habrastatistik: Erkundung der am häufigsten und am wenigsten besuchten Bereiche der Website

Bei „Unterhaltungs“-Artikeln liegt er etwa 40 % über dem Durchschnitt. Dies ist wahrscheinlich nicht überraschend. Der Fehler Anfang April ist mir unklar, vielleicht ist das passiert, oder es handelt sich um eine Art Parsing-Fehler, oder vielleicht ist einer der Geektimes-Autoren in den Urlaub gefahren ;).

Die Grafik zeigt übrigens zwei weitere auffällige Spitzenwerte bei der Anzahl der Artikelaufrufe – die Neujahrs- und Maifeiertage.

Hubs

Kommen wir zur versprochenen Hub-Analyse. Lassen Sie uns die Top-20-Hubs nach Anzahl der Aufrufe auflisten:

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

Ergebnis:

Habrastatistik: Erkundung der am häufigsten und am wenigsten besuchten Bereiche der Website

Überraschenderweise war „Informationssicherheit“ der beliebteste Hub in Bezug auf die Ansichten; zu den Top-5-Spitzenreitern gehörten auch „Programmierung“ und „Populärwissenschaft“.

Antitop besetzt Gtk und Cocoa.

Habrastatistik: Erkundung der am häufigsten und am wenigsten besuchten Bereiche der Website

Ich verrate euch ein Geheimnis, auch die Top-Naben können sich sehen lassen hier, obwohl die Anzahl der Aufrufe dort nicht angezeigt wird.

Bewertung

Und zum Schluss noch die versprochene Bewertung. Mithilfe von Hub-Analysedaten können wir die beliebtesten Artikel für die beliebtesten Hubs für dieses Jahr 2019 anzeigen.

Informationssicherheit

Programmierung

Populärwissenschaft

Karriere

Gesetzgebung in der IT

Web Entwicklung

GTK

Und damit es niemanden beleidigt, gebe ich abschließend noch die Bewertung des am wenigsten besuchten Hubs „gtk“ ab. Innerhalb eines Jahres wurde es veröffentlicht ein Der Artikel, der auch „automatisch“ die erste Zeile der Bewertung belegt.

Abschluss

Es wird keine Schlussfolgerung geben. Viel Spaß beim Lesen an alle.

Source: habr.com

Kommentar hinzufügen