مهارات مبرمج Python الرئيسية

في عصرنا الديناميكي ، يحتاج المبرمج إلى مواكبة وتعلم مهارات جديدة باستمرار من أجل أن يظل متخصصًا مطلوبًا.

لقد قمت بالبرمجة في بايثون لمدة عامين تقريبًا ، والآن حان الوقت للتعامل بوعي مع تطوير مهارات جديدة. للقيام بذلك ، قررت تحليل الوظائف الشاغرة وتقديم المهارات المطلوبة في شكل رسم بياني. توقعت أن أرى أن المهارات ستشكل مجموعات تتوافق مع التخصصات المختلفة: تطوير الواجهة الخلفية ، وعلوم البيانات ، وما إلى ذلك. ولكن ماذا عن الواقع؟ اهم الاشياء اولا.

جمع البيانات


كان عليك أولاً أن تقرر مصدر البيانات. فكرت في عدة خيارات: Habr Career و Yandex Work و HeadHunter وغيرها. يبدو أن HeadHunter هو الأكثر ملاءمة ، لأنه في الوظائف الشاغرة توجد قائمة بالمهارات الأساسية وهناك واجهة برمجة تطبيقات مفتوحة مريحة .

بعد دراسة HeadHunter API ، قررت أولاً تحليل قائمة معرف الوظيفة لكلمة رئيسية معينة (في هذه الحالة ، "python") ، ثم تحليل قائمة العلامات المقابلة لكل وظيفة.

عند البحث عن الوظائف الشاغرة ، يتم إرجاع الوظائف الشاغرة بصفحة ، الحد الأقصى لعدد الوظائف الشاغرة في الصفحة هو 100. في البداية قمت بحفظ النتائج الكاملة كقائمة لإجابات الصفحة.

لهذا ، تم استخدام وحدة الطلبات. في حقل "وكيل المستخدم" ، وفقًا لواجهة برمجة التطبيقات ، تم إدخال اسم المتصفح الافتراضي حتى يفهم HH أن البرنامج النصي كان يدخل إليه. قام بتأخير طفيف بين الطلبات حتى لا تفرط في تحميل الخادم.

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)

ونتيجة لذلك ، حصلت على قائمة بقواميس الإجابة ، حيث يتوافق كل قاموس مع صفحة واحدة من نتائج البحث.

كما اتضح ، فإن hh.ru API يحد من الحد الأقصى لعدد الوظائف الشاغرة إلى ألفين ، أي مع 100 وظيفة شاغرة في الصفحة ، يمكن أن يكون الحد الأقصى لعدد الصفحات 20. المزيد.

للحصول على قائمة بالعلامات ، قمت بما يلي:
  • تكررت فوق كل صفحة من نتائج البحث ،
  • تكررت فوق كل وظيفة في الصفحة وحصلت على معرف الوظيفة ،
  • تفاصيل الوظيفة المطلوبة عبر واجهة برمجة التطبيقات ،
  • إذا تم تحديد علامة واحدة على الأقل في الوظيفة الشاغرة ، فسيتم إضافة قائمة العلامات إلى القائمة.

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

تم حفظ قوائم العلامات في القاموس

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)

ومن المثير للاهتمام أنه من بين 2000 وظيفة شاغرة تم عرضها ، كان هناك 1579 وظيفة شاغرة فقط بها علامات.

تنسيق البيانات


تحتاج الآن إلى معالجة العلامات وترجمتها إلى تنسيق مناسب للعرض كرسم بياني ، أي:
  • إحضار جميع العلامات إلى سجل واحد ، لذلك يعني "التعلم الآلي" و "التعلم الآلي" و "التعلم الآلي" نفس الشيء
  • حساب قيمة العقدة مثل تكرار حدوث كل علامة ،
  • حساب قيمة الاتصال كتكرار الاجتماع المشترك للعلامات مع بعضها البعض.

بالحد إلى سجل واحد ، تم حساب تكرار تكرار كل علامة ، تم إجراء التصفية حسب حجم العقدة على النحو التالي.

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}

يتم حساب التواجد الزوجي على النحو التالي. أولاً قمت بإنشاء قاموس حيث كانت جميع المفاتيح عبارة عن أزواج من العلامات الممكنة في شكل مجموعة ، وكانت القيم صفرًا. ثم استعرضت قائمة العلامات وزادت العدادات لكل زوج واجهته. ثم حذفت كل العناصر التي كانت قيمها صفر.

# 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]

عند الإخراج ، قمت بتشكيل قاموس

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

تصور بايثون


لتصور الرسم البياني ، استخدمت وحدة networkx. هذا ما حدث في المرة الأولى دون تصفية العقد.



هذا التصور يشبه كرة خيوط متشابكة أكثر من رسم بياني للمهارات. يتم الخلط بين الاتصالات واختراق الرسم البياني بكثافة لدرجة أنه من المستحيل عمل عقد. بالإضافة إلى ذلك ، هناك الكثير من العقد على الرسم البياني ، بعضها صغير جدًا بحيث لا يكون له دلالة إحصائية.

لذلك ، قمت بتصفية أصغر العقد التي يقل حجمها عن 5 ، وقمت أيضًا بعمل روابط رمادية. في هذه الصورة ، لم أحضر الكلمات بعد إلى سجل واحد ، بينما حاولت حذف أكبر عقدة Python من أجل قطع الاتصال.



لقد أصبح أفضل بكثير. الآن يتم فصل العقد ، ولا تسد الروابط التصور. أصبح من الممكن رؤية المهارات الأساسية ، فهي تقع في كرات كبيرة في وسط الرسم البياني ، والعقد الصغيرة. لكن هذا الرسم البياني لا يزال لديه الكثير لتحسينه.

تصور جافا سكريبت


ربما سأستمر في اختيار هذا الرمز إذا لم يكن لدي في تلك اللحظة مساعدة في شكل أخ. شارك بنشاط في العمل وقدم عرضًا ديناميكيًا جميلًا يعتمد على وحدة JavaScript D3 .

اتضح مثل هذا.


التصور الديناميكي متاح هنا. لاحظ أنه يمكن سحب العقد.

تحليل النتائج


كما نرى ، تبين أن الرسم البياني متشابك جدًا ، ولا يمكن الكشف عن العناقيد المحددة بوضوح للوهلة الأولى. يمكنك على الفور ملاحظة العديد من العقد الكبيرة الأكثر طلبًا: linux و sql و git و postgresql و django. هناك أيضًا مهارات ذات شعبية متوسطة ومهارات نادرًا ما تتم مواجهتها.

بالإضافة إلى ذلك ، يمكنك الانتباه إلى حقيقة أن المهارات لا تزال تشكل مجموعات حسب المهنة ، وتقع على جانبي المركز:

  • أسفل اليسار - تحليل البيانات ،
  • في الأسفل توجد قواعد البيانات ،
  • أسفل اليمين - تطوير الواجهة الأمامية ،
  • على اليمين يختبر ،
  • أعلى اليمين - تطوير الويب ،
  • أعلى اليسار - التعلم الآلي.

يعتمد هذا الوصف للمجموعات على معرفتي وقد يحتوي على أخطاء ، لكن الفكرة نفسها ، على ما آمل ، واضحة.

بناءً على النتائج التي تم الحصول عليها ، يمكن استخلاص النتائج التالية:
  • أنت بحاجة إلى إتقان المهارات التي تتوافق مع العقد الكبيرة ، ستكون مفيدة دائمًا ،
  • أنت بحاجة إلى إتقان مهارات المجموعة التي تناسب اهتماماتك.

آمل أن تكون قد استمتعت به وسيكون هذا التحليل مفيدًا لك.

يمكنك إلقاء نظرة على الكود أو المشاركة في تطويره باستخدام الروابط: مشروع GitHub ، كمبيوتر محمول يمكن ملاحظته مع التصور

النجاح في إتقان آفاق جديدة!

All Articles