Wichtige Python-Programmiererfähigkeiten

In unserer dynamischen Zeit muss der Programmierer auf dem Laufenden bleiben und ständig neue Fähigkeiten erlernen, um ein gefragter Spezialist zu bleiben.

Ich programmiere seit ungefähr zwei Jahren in Python und jetzt ist es an der Zeit, mich bewusst der Entwicklung neuer Fähigkeiten zu nähern. Zu diesem Zweck habe ich mich entschlossen, die offenen Stellen zu analysieren und die erforderlichen Fähigkeiten in Form eines Diagramms darzustellen. Ich hatte erwartet zu sehen, dass Fähigkeiten Cluster bilden, die verschiedenen Fachgebieten entsprechen: Backend-Entwicklung, Datenwissenschaft usw. Aber was ist mit der Realität? Das wichtigste zuerst.

Datensammlung


Zuerst musste man sich für die Datenquelle entscheiden. Ich habe verschiedene Optionen in Betracht gezogen: Habr Career , Yandex Work , HeadHunter und andere. HeadHunter schien am bequemsten zu sein, da hier in den offenen Stellen eine Liste der Schlüsselkompetenzen und eine bequeme offene API vorhanden sind .

Nachdem ich die HeadHunter-API studiert hatte, entschied ich mich, zuerst die Liste der Job-IDs für ein bestimmtes Schlüsselwort (in diesem Fall „Python“) zu analysieren und dann die Liste der entsprechenden Tags für jeden Job zu analysieren.

Bei der Suche nach Stellenangeboten werden Stellenangebote Seite für Seite zurückgegeben, die maximale Anzahl von Stellenangeboten pro Seite beträgt 100. Zuerst habe ich die vollständigen Ergebnisse in Form einer Liste mit Seitenantworten gespeichert.

Hierzu wurde das Anforderungsmodul verwendet. Im Feld "Benutzeragent" wurde gemäß der API der Name des virtuellen Browsers eingegeben, damit HH verstand, dass das Skript darauf zugreift. Er machte eine leichte Verzögerung zwischen den Anfragen, um den Server nicht zu überlasten.

ses = requests.Session()
ses.headers = {'HH-User-Agent': "Mozilla/5.0 (X11; Linux x86_64; rv:10.0) Gecko/20100101 Firefox/10.0"}

phrase_to_search = 'python'
url = f'https://api.hh.ru/vacancies?text={phrase_to_search}&per_page=100'
res = ses.get(url)

# getting a list of all pesponses
res_all = []
for p in range(res.json()['pages']):
    print(f'scraping page {p}')
    url_p = url + f'&page={p}'
    res = ses.get(url_p)
    res_all.append(res.json())
    time.sleep(0.2)

Als Ergebnis erhielt ich eine Liste von Antwortwörterbüchern, wobei jedes Wörterbuch einer Seite mit Suchergebnissen entsprach.

Wie sich herausstellte, begrenzt die hh.ru-API die maximale Anzahl von Stellenangeboten auf zweitausend, dh bei 100 Stellenangeboten pro Seite kann die maximale Anzahl von Seiten 20 betragen. Für das Schlüsselwort Python wurden 20 Stellenangebote zurückgegeben, was bedeutet, dass echte Stellenangebote in Python wahrscheinlicher sind umso mehr.

Um eine Liste der Tags zu erhalten, habe ich Folgendes getan:
  • Durch jede Seite der Suchergebnisse iteriert,
  • Ich habe jeden Job auf der Seite durchlaufen und die Job-ID erhalten.
  • über die API angeforderte Details der Vakanz,
  • Wenn in der Vakanz mindestens ein Tag angegeben wurde, wurde die Liste der Tags zur Liste hinzugefügt.

# parcing vacancies ids, getting vacancy page and scraping tags from each vacancy
tags_list = []
for page_res_json in res_all:
    for item in page_res_json['items']:
        vac_id = item['id']
        vac_res = ses.get(f'https://api.hh.ru/vacancies/{vac_id}')
        if len(vac_res.json()["key_skills"]) > 0:  # at least one skill present
            print(vac_id)
            tags = [v for v_dict in vac_res.json()["key_skills"] for _, v in v_dict.items()]
            print(' '.join(tags))
            tags_list.append(tags)
            print()
        time.sleep(0.1)

Tag-Listen wurden als Wörterbuch gespeichert

res = {'phrase': phrase_to_search, 'items_number': len(tags_list), 'items': tags_list}
with open(f'./data/raw-tags_{phrase_to_search}.json', 'w') as fp:  # Serializing
    json.dump(res, fp)

Interessanterweise hatten von den 2000 betrachteten Stellen nur 1579 Stellen Tags.

Datenformatierung


Jetzt müssen Sie die Tags verarbeiten und in ein Format übersetzen, das für die Anzeige als Grafik geeignet ist, nämlich:
  • Bringen Sie alle Tags in ein einziges Register, sodass „maschinelles Lernen“, „Maschinelles Lernen“ und „Maschinelles Lernen“ dasselbe bedeuten
  • Berechnen Sie den Wert des Knotens als Häufigkeit des Auftretens jedes Tags.
  • Berechnen Sie den Wert der Verbindung als die Häufigkeit des gemeinsamen Treffens von Tags miteinander.

Das Reduzieren auf ein einzelnes Register, das Berechnen der Häufigkeit des Auftretens jedes Tags und das Filtern nach der Größe des Knotens wurde wie folgt durchgeführt.

tags_list['items'] = [[i.lower() for i in line] for line in tags_list['items']]

# counting words occurrences
flattened_list = [i for line in tags_list for i in line]
nodes_dict_all = {i: flattened_list.count(i) for i in set(flattened_list)}
nodes_dict = {k:v for k, v in nodes_dict_all.items() if v > del_nodes_count}

Das paarweise Auftreten wird wie folgt berechnet. Zuerst habe ich ein Wörterbuch erstellt, in dem die Schlüssel alle möglichen Paare von Tags in Form von Tupeln waren und die Werte Null waren. Dann ging es die Liste der Tags durch und erhöhte die Zähler für jedes angetroffene Paar. Dann habe ich alle Elemente gelöscht, deren Werte Null waren.

# tags connection dict initialization
formatted_tags = {(tag1, tag2): 0 for tag1, tag2 in itertools.permutations(set(nodes_dict.keys()), 2)}

# count tags connection
for line in tags_list:
    for tag1, tag2 in itertools.permutations(line, 2):
        if (tag1, tag2) in formatted_tags.keys():
            formatted_tags[(tag1, tag2)] += 1

# filtering pairs with zero count
for k, v in formatted_tags.copy().items():
    if v == 0:
        del formatted_tags[k]

Am Ausgang habe ich ein Wörterbuch der Form gebildet

{
'phrase': phrase searched,
'items_number': number of vacancies parced, 
'items': {
 	"nodes": [
			{
			"id": tag name, 
		 	"group": group id, 
		 	"popularity": tag count
			},
		] 
	"links": [
			{
			"source": pair[0], 
			"target": pair[1], 
			"value": pair count
			},
		]
	}
}

nodes = []
links = []
for pair, count in formatted_tags.items():
    links.append({"source": pair[0], "target": pair[1], "value": count})

max_count = max(list(nodes_dict.values()))
count_step = max_count // 7
for node, count in nodes_dict.items():
    nodes.append({"id": node, "group": count // count_step, "popularity": count})

data_to_dump = in_json.copy()
data_to_dump['items'] = {"nodes": nodes, "links": links}

Python-Visualisierung


Zur Visualisierung des Diagramms habe ich das networkx-Modul verwendet. Dies ist das erste Mal passiert, ohne die Knoten zu filtern.



Diese Visualisierung ähnelt eher einer Kugel aus verwickelten Fäden als einem Fertigkeitsdiagramm. Die Verbindungen sind verwirrt und dringen so dicht in den Graphen ein, dass es unmöglich ist, Knoten zu erkennen. Darüber hinaus enthält das Diagramm zu viele Knoten, von denen einige so klein sind, dass sie keine statistische Signifikanz haben.

Daher habe ich die kleinsten Knoten mit einer Größe von weniger als 5 herausgefiltert und auch graue Links erstellt. In diesem Bild habe ich die Wörter noch nicht in ein einzelnes Register gebracht, während ich versucht habe, den größten Python-Knoten zu löschen, um die Verbindung zu entladen.



Es ist viel besser geworden. Jetzt sind die Knoten getrennt und die Links verstopfen die Visualisierung nicht. Es wurde möglich, die Grundfertigkeiten zu sehen, sie befinden sich in großen Kugeln in der Mitte des Diagramms und kleinen Knoten. Aber diese Grafik hat noch viel zu verbessern.

JavaScript-Visualisierung


Ich würde diesen Code wahrscheinlich weiterhin auswählen, wenn ich in diesem Moment keine Hilfe in Form eines Bruders hätte. Er war aktiv an der Arbeit beteiligt und machte eine schöne dynamische Anzeige basierend auf dem JavaScript- Modul D3 .

Es stellte sich so heraus.


Eine dynamische Visualisierung finden Sie hier. Beachten Sie, dass Knoten gezogen werden können.

Ergebnisanalyse


Wie wir sehen können, erwies sich der Graph als sehr eng miteinander verbunden, und klar definierte Cluster können auf den ersten Blick nicht erkannt werden. Sie können sofort mehrere große Knoten bemerken, die am meisten gefragt sind: Linux, SQL, Git, Postgresql und Django. Es gibt auch Fähigkeiten mittlerer Beliebtheit und selten anzutreffende Fähigkeiten.

Darüber hinaus können Sie darauf achten, dass Fähigkeiten nach Beruf immer noch Cluster bilden, die sich auf gegenüberliegenden Seiten des Zentrums befinden:

  • unten links - Datenanalyse,
  • unten sind die Datenbanken,
  • unten rechts - Frontend-Entwicklung,
  • auf der rechten Seite wird getestet,
  • oben rechts - Webentwicklung,
  • oben links - maschinelles Lernen.

Diese Beschreibung der Cluster basiert auf meinem Wissen und kann Fehler enthalten, aber die Idee selbst ist hoffentlich klar.

Basierend auf den erhaltenen Ergebnissen können die folgenden Schlussfolgerungen gezogen werden:
  • Sie müssen Fähigkeiten beherrschen, die großen Knoten entsprechen. Sie sind immer nützlich.
  • Sie müssen die Fähigkeiten des Clusters beherrschen, die Ihren Interessen entsprechen.

Ich hoffe es hat Ihnen gefallen und diese Analyse wird Ihnen nützlich sein.

Sie können sich den Code ansehen oder über die folgenden Links an seiner Entwicklung teilnehmen: GitHub-Projekt , Beobachtbarer Laptop mit Visualisierung

Erfolgreich bei der Beherrschung neuer Horizonte!

All Articles