Habrastatistics: vekolîna beşên herî zêde û herî hindik ên malperê

Hey Habr.

В beşa berê Trafîka Habrê li gorî pîvanên sereke - hejmara gotaran, dîtin û nirxandinên wan - hate analîz kirin. Lêbelê, mijara populerbûna beşên malperê nehat lêkolîn kirin. Balkêş bû ku meriv li vê yekê bi hûrgulî binêre û navendên herî populer û ne populer bibînin. Di dawiyê de, ez ê bi hûrgulî li bandora geektimes binihêrim, ku bi hilbijarkek nû ya çêtirîn gotarên li ser bingeha rêzikên nû bi dawî bibe.

Habrastatistics: vekolîna beşên herî zêde û herî hindik ên malperê

Ji bo kesên ku bi çi qewimî re eleqedar dibin, berdewam di bin qutbûnê de ye.

Careke din bi bîr tînim ku îstatîstîk û nirx ne fermî ne, ti agahiyeke min a hundirîn nîne. Di heman demê de ne garantî ye ku min li deverek xeletiyek nekiriye an tiştek ji bîr nekiriye. Lê dîsa jî, ez difikirim ku ew balkêş derket. Em ê pêşî bi kodê dest pê bikin, yên ku bi vê yekê re eleqedar nabin, dikarin beşên yekem derbas bikin.

Komkirina daneyan

Di guhertoya yekem a parserê de, tenê jimara dîtin, şîrove û nirxandinên gotaran hatine hesibandin. Ev jixwe baş e, lê ew nahêle ku hûn pirsên tevlihevtir bikin. Wext e ku hûn beşên tematîk ên malperê analîz bikin ev ê bihêle ku hûn lêkolînek pir balkêş bikin, mînakî, bibînin ka çiqas populerbûna beşa "C ++" di çend salan de guheriye.

Parsera gotarê baştir bûye, naha ew navendên ku gotar tê de ye vedigerîne, her weha paşnavê nivîskar û nirxa wî vedigerîne (li vir jî gelek tiştên balkêş dikarin bêne kirin, lê ew ê paşê were). Daneyên di pelek csv de têne tomar kirin ku tiştek weha xuya dike:

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

Em ê navnîşek navendên mijarên sereke yên malperê bistînin.

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)

Fonksiyona find_between û çîna Str di navbera du nîşanan de rêzek hilbijêrin, min ew bikar anîn berê. Navendên tematîk bi "*"-ê têne nîşankirin da ku ew bi hêsanî bêne ronî kirin, û hûn dikarin rêzikên têkildar jî şîrove bikin da ku beşên kategoriyên din bistînin.

Hilberîna fonksiyona get_hubs navnîşek berbiçav e, ku em wekî ferheng tomar dikin. Ez bi taybetî navnîşê bi tevahî pêşkêşî dikim da ku hûn qebareya wê texmîn bikin.

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

Ji bo berhevdanê, beşên geektimes nermtir xuya dikin:

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

Hubên mayî jî bi heman awayî hatin parastin. Naha hêsan e ku meriv fonksiyonek binivîsîne ku encamê vedigerîne ka gotar ji geektimes re be an ji navendek profîlek be.

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

Ji bo beşên din ("pêşveçûn", "rêveberî", hwd.) fonksiyonên bi vî rengî hatin çêkirin.

Danasîn

Wext e ku meriv dest bi analîzê bike. Em danûstendinê bar dikin û daneyên hubê pêvajo dikin.

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)

Naha em dikarin daneyan bi roj kom bikin û hejmara weşanan ji bo navendên cihêreng nîşan bidin.

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

Em hejmara gotarên hatine weşandin bi karanîna Matplotlib nîşan didin:

Habrastatistics: vekolîna beşên herî zêde û herî hindik ên malperê

Min gotarên "geektimes" û "tenê geektimes" di nexşeyê de dabeş kirin, ji ber ku Gotarek dikare di heman demê de bibe xwediyê her du beşan (mînak, "DIY" + "microkontroller" + "C++"). Min binavkirina "profîl" bikar anî da ku gotarên profîlê yên li ser malperê ronî bike, her çend dibe ku profîla terma îngilîzî ji bo vê yekê bi tevahî ne rast be.

Di beşa paşîn de me li ser "bandora geektimes" ya ku bi guherîna qaîdeyên dravdanê ji bo gotarên ji bo geektimes vê havînê dest pê dike ve pirsî. Ka em gotarên geektimes cuda nîşan bidin:

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

Encam balkêş e. Rêjeya texmînî ya dîtinên gotarên geektimes bi tevahî li derûdora 1:5 e. Lê dema ku jimara giştî ya dîtinan bi rengek berbiçav diguhezî, temaşekirina gotarên "şavhewa" hema hema di heman astê de ma.

Habrastatistics: vekolîna beşên herî zêde û herî hindik ên malperê

Her weha hûn dikarin bala xwe bidin ku jimara giştî ya dîtinên gotaran di beşa "geektimes" de piştî guheztina qaîdeyan dîsa jî kêm bû, lê "bi çav", ne ji% 5 ê nirxên giştî.

Balkêş e ku meriv li hejmara navînî ya dîtina her gotarê binêre:

Habrastatistics: vekolîna beşên herî zêde û herî hindik ên malperê

Ji bo gotarên "şahî" ew bi qasî 40% li ser navînî ye. Ev dibe ku ne ecêb e. Têkçûn di destpêka Nîsanê de ji min re ne diyar e, dibe ku ew çi bûye, an ew celebek xeletiyek parsek e, an jî dibe ku yek ji nivîskarên geektimes çûye betlaneyê;).

Bi awayê, grafîk di hejmara dîtinên gotaran de du lûtkeyên din ên berbiçav nîşan dide - betlaneyên Sersal û Gulanê.

Hubs

Werin em biçin ser analîza soza hub. Werin em 20 navendên sereke li gorî hejmara dîtinan navnîş bikin:

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

Encam:

Habrastatistics: vekolîna beşên herî zêde û herî hindik ên malperê

Ecêb e, di warê dîtinan de navenda herî populer "Ewlehiya Agahdariyê" bû ku di nav 5 serokên herî mezin de "Bernamekirin" û "Zanistiya populer" jî hebûn.

Antitop Gtk û Kakao dagir dike.

Habrastatistics: vekolîna beşên herî zêde û herî hindik ên malperê

Ez ê ji we re sirekekê bibêjim, hubên jorîn jî têne dîtin vir, her çend hejmara dîtinan li wir nayê nîşandan.

Rêjeya

Û di dawiyê de, rêjeya soz. Bi karanîna daneyên analîzkirina hubê, em dikarin gotarên herî populer ên ji bo navendên herî populer ên îsal 2019 nîşan bidin.

Ewlekariya Agahdariyê

Programming

Popular Science

Karsaziyê

Qanûna di IT

Pêşveçûna Webê

GTK

Û di dawiyê de, ji bo ku kes aciz nebe, ez ê nirxa navendê ya herî hindik "gtk" bidim. Di nava salekê de hat çapkirin yek gotara, ku di heman demê de "otomatîk" rêza yekem a nirxandinê digire.

encamê

Wê ti encam dernekeve. Xwendina herkesî xweş.

Source: www.habr.com

Add a comment