データサイエンティストの市場要件の分析

インターネットには、データサイエンティストが知る必要がある多くの情報があります。 しかし、私はすぐにデータ科学者になる必要があると決めたので、空席のテキストを分析することで専門家の要件を見つけます。









まず、問題を定式化し、計画を作成します。



チャレンジ:



市場のすべての空席を表示し、それらに示されている一般的な要件を見つけます。



計画:



1. Dat Scientistのリクエストに応じて、処理に便利な形式ですべての空席を収集します。

2.説明によくある単語やフレーズを見つけます。



実装には、SQLとPythonの知識が少し必要です。



そうでない場合は、ここにいます
SQLの場合はsqlbolt.comを 、Pythonの場合はSoloLearnモバイルアプリケーション( GooglePlayおよびAppStore )をお勧めします。



データ収集



ソース:hh.ru

最初は、サイトを解析できると思いました。 幸い、hh.ruにはAPIがあることがわかりました。



まず、分析のためにIDの空席のリストを受け取る関数を作成します。 パラメーターでは、関数は検索テキスト(ここでは「データサイエンティスト」を送信します)と検索エリア(APIドキュメントに従って)を受け取り、IDリストを返します。 データを取得するには、求人検索API関数を使用します



ここにコードがあります
def get_list_id_vacancies(area, text): url_list = 'https://api.hh.ru/vacancies' list_id = [] params = {'text': text, 'area': area} r = requests.get(url_list, params=params) found = json.loads(r.text)['found']; #-    if found <= 500: # API    500    ( ).    500    . params['per_page'] = found r = requests.get(url_list, params=params) data = json.loads(r.text)['items'] for vac in data: list_id.append(vac['id']) else: i = 0; while i <= 3: #   500  ""   0  3     . API     2000 ,    3. params['per_page'] = 500 params['page'] = i r = requests.get(url_list, params=params) if 200 != r.status_code: break data = json.loads(r.text)['items'] for vac in data: list_id.append(vac['id']) i += 1 return list_id
      
      







デバッグのために、注文をAPIに直接送信しました。 これにはchrome Postmanアプリケーションを使用することをお勧めします。



その後、各空室に関する詳細情報を取得する必要があります。



ここにコードがあります
 def get_vacancy(id): url_vac = 'https://api.hh.ru/vacancies/%s' r = requests.get(url_vac % id) return json.loads(r.text)
      
      









これで、空席のリストと、各空席に関する詳細情報を受け取る関数ができました。 受信したデータを書き込む場所を決定する必要があります。 2つのオプションがありました。すべてをcsvファイルに保存するか、データベースを作成します。 Excelで分析するよりもSQLクエリを書く方が簡単なので、データベースを選択しました。 まず、記録するデータベースとテーブルを作成する必要があります。 これを行うには、APIの応答を分析し、必要なフィールドについて決定します。



api.hh.ru/vacancies/22285538などのapiリンクをPostmanに挿入し、GETリクエストを作成して回答を取得します。



フルJSON
 { "alternate_url": "https://hh.ru/vacancy/22285538", "code": null, "premium": false, "description": "<p> ....", "schedule": { "id": "fullDay", "name": " " }, "suitable_resumes_url": null, "site": { "id": "hh", "name": "hh.ru" }, "billing_type": { "id": "standard_plus", "name": "+" }, "published_at": "2017-09-05T11:43:08+0300", "test": null, "accept_handicapped": true, "experience": { "id": "noExperience", "name": " " }, "address": { "building": "367", "city": "", "description": null, "metro": { "line_name": "", "station_id": "8.470", "line_id": "8", "lat": 55.736478, "station_name": " ", "lng": 37.514401 }, "metro_stations": [ { "line_name": "", "station_id": "8.470", "line_id": "8", "lat": 55.736478, "station_name": " ", "lng": 37.514401 } ], "raw": null, "street": " ", "lat": 55.739068, "lng": 37.525432 }, "key_skills": [ { "name": " " }, { "name": " " } ], "allow_messages": true, "employment": { "id": "full", "name": " " }, "id": "22285538", "response_url": null, "salary": { "to": 90000, "gross": false, "from": 50000, "currency": "RUR" }, "archived": false, "name": "/ Data scientist", "contacts": null, "employer": { "logo_urls": { "90": "https://hhcdn.ru/employer-logo/1680554.png", "240": "https://hhcdn.ru/employer-logo/1680555.png", "original": "https://hhcdn.ru/employer-logo-original/309546.png" }, "vacancies_url": "https://api.hh.ru/vacancies?employer_id=1475513", "name": "  ", "url": "https://api.hh.ru/employers/1475513", "alternate_url": "https://hh.ru/employer/1475513", "id": "1475513", "trusted": true }, "created_at": "2017-09-05T11:43:08+0300", "area": { "url": "https://api.hh.ru/areas/1", "id": "1", "name": "" }, "relations": [], "accept_kids": false, "response_letter_required": false, "apply_alternate_url": "https://hh.ru/applicant/vacancy_response?vacancyId=22285538", "quick_responses_allowed": false, "negotiations_url": null, "department": null, "branded_description": null, "hidden": false, "type": { "id": "open", "name": "" }, "specializations": [ { "profarea_id": "14", "profarea_name": ", ", "id": "14.91", "name": ",  " }, { "profarea_id": "14", "profarea_name": ", ", "id": "14.141", "name": "" }] }
      
      







分析する予定のないものはすべてJSONから削除されます。



適切なJSON
 { "description": "<p> ....", "schedule": { "id": "fullDay", "name": " " }, "accept_handicapped": true, "experience": { "id": "noExperience", "name": " " }, "key_skills": [ { "name": " " }, { "name": " " } ], "employment": { "id": "full", "name": " " }, "id": "22285538", "salary": { "to": 90000, "gross": false, "from": 50000, "currency": "RUR" }, "name": "/ Data scientist", "employer": { "name": "  ", }, "area": { "name": "" }, "specializations": [ { "profarea_id": "14", "profarea_name": ", ", "id": "14.91", "name": ",  " }, { "profarea_id": "14", "profarea_name": ", ", "id": "14.141", "name": "" }] }
      
      







このJSONに基づいて、データベースを作成します。 簡単なので、省略します:)



データベースとの相互作用のモジュールを実現します。 MySQLを使用しました。



ここにコードがあります
 def get_salary(vac): #   .      ,     ,     None,   . if vac['salary'] is None: return {'currency':None , 'from':None,'to':None,'gross':None} else: return {'currency':vac['salary']['currency'], 'from':vac['salary']['from'], 'to':vac['salary']['to'], 'gross':vac['salary']['gross']} def get_connection(): conn = pymysql.connect(host='localhost', port=3306, user='root', password='-', db='hh', charset="utf8") return conn def close_connection(conn): conn.commit() conn.close() def insert_vac(conn, vac, text): a = conn.cursor() salary = get_salary(vac) print(vac['id']) a.execute("INSERT INTO vacancies (id, name_v, description, code_hh, accept_handicapped, \ area_v, employer, employment, experience, salary_currency, salary_from, salary_gross, \ salary_to, schedule_d, text_search) \ VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)", (vac['id'], vac['name'], vac['description'], vac['code'], vac['accept_handicapped'], vac['area']['name'], vac['employer']['name'], vac['employment']['name'], vac['experience']['name'], salary['currency'], salary['from'], salary['gross'], salary['to'], vac['schedule']['name'], text)) for key_skill in vac['key_skills']: a.execute("INSERT INTO key_skills(vacancy_id, name) VALUES(%s, %s)",(vac['id'], key_skill['name'])) for spec in vac['specializations']: a.execute("INSERT INTO specializations(vacancy_id, name, profarea_name) VALUES(%s, %s, %s)", (vac['id'], spec['name'], spec['profarea_name'])) a.close()
      
      







main()メソッドをファイルに追加して、すべてをまとめます



データ収集
 text_search = 'data scientist' list_id_vacs = get_list_id_vacancies(text_search) vacs = [] for vac_id in list_id_vacs: vacs.append(get_vacancy(vac_id)) conn = get_connection() for vac in vacs: insert_vac(conn, vac, text_search) close_connection(conn)
      
      







text_search変数とarea変数を変更すると、さまざまな地域からさまざまな空席が得られます。

これでデータマイニングが完了し、興味深いことに進みます。



テキスト分析



主なインスピレーションは、「 お母さんとの出会い」シリーズの人気フレーズ検索に関する記事でした



まず、データベースからすべての空席の説明を受け取ります。



ここにコードがあります
 def get_vac_descriptions(conn, text_search): a = conn.cursor() a.execute("SELECT description FROM vacancies WHERE text_search = %s", text_search) descriptions = a.fetchall() a.close return descriptions
      
      







テキストを操作するには、 nltkパッケージを使用します。 上記の記事と同様に、テキストから人気のフレーズを取得する機能を記述します。



ここにコードがあります
 def get_popular_phrase(text, len, count_phrases): phrase_counter = Counter() words = nltk.word_tokenize(text.lower()) for phrase in nltk.ngrams(words, len): if all(word not in string.punctuation for word in phrase): phrase_counter[phrase] += 1 return phrase_counter.most_common(count_phrases) descriptions = get_vac_descriptions(get_connection(), 'data scientist') text = '' for description in descriptions: text = text + description[0] result = get_popular_phrase(text, 1, 20) for r in result: print(" ".join(r[0]) + " - " + str(r[1]))
      
      







mainメソッドで上記のすべてのメソッドを組み合わせて実行します。



ここにコードがあります
 def main(): descriprions = get_vac_descriptions(get_connection(), 'data scientist') text = '' for descriprion in descriprions: text = text + descriprion[0] result = get_popular_phrase(text, 4, 20, stopwords) for r in result: print(" ".join(r[0]) + " - " + str(r[1])) main()
      
      







実行して確認します:



li-2459

/ li-2459

および-1297

p-1225

/ p-1224

で-874

強い-639

/強い-620

および-486

ul-457

/ ul-457

s-415

オン-341

データ-329

データ-313

ザ-308

経験-275

の-269

-254

仕事-233



結果には、説明で使用されているすべての空席とタグに特徴的な多くの単語が含まれていることがわかります。 これらの単語を分析から削除します。 このためには、ストップワードのリストが必要です。 別の分野の空席を分析することにより、自動的に形成します。 「料理人」、「掃除婦」、「錠前屋」を選びました。



最初に戻って、これらのリクエストの空きを取得しましょう。 その後、ストップワードを取得する機能を追加します。



ここにコードがあります
 def get_stopwords(): descriptions = get_vac_descriptions(get_connection(), '') \ + get_vac_descriptions(get_connection(), '') + \ get_vac_descriptions(get_connection(), '') text = '' for description in descriptions: text = text + descriprion[0] stopwords = [] list = get_popular_phrase(text, 1, None, 200) #    for i in list: stopwords.append(i[0][0]) return stopwords
      
      









また、英語のthe and ofも参照してください。 英語で空室を削除して簡単にしましょう。

main()を変更します:



ここにコードがあります
 for description in descriptions: if detect(description[0]) != 'en': text = text + description[0]
      
      







結果は次のようになります。



データ-329

データ-180

分析-157

トレーニング-134

マシン-129

モデル-128

エリア-101

アルゴリズム-87

python-86

タスク-82

タスク-82

開発-77

分析-73

建物-68

メソッド-66

-65

統計-56

より高い-55

知識-53

学習-52



まあ、これは一言ですが、常に真実を反映しているわけではありません。 2つの単語の単語の組み合わせが示すものを見てみましょう:



機械学習-119

データ分析-56

機械学習-44

データサイエンス-38

データサイエンティスト-38

ビッグデータ-34

数学モデル-34

データマイニング-28

機械アルゴリズム-27

数学統計-23

プラスになります-21

統計分析-20

データ処理-18

英語-17

データ分析-17

含む-17

また-17

マシンメソッド-16

分析分野-15

確率論-14



分析の結果。



より明示的なクエリは、結果を2つの単語で返します。知っておく必要があります。





新しいものはありませんが、楽しかったです:)



結論



これは理想的なソリューションとはほど遠いものです。



エラー:



1.英語の欠員を除外する必要はありません。翻訳する必要があります。

2.すべてのストップワードが除外されるわけではありません。

3.すべての単語を基本形式(機械->機械、分析->分析など)にする必要があります。

4.ストップワードのより最適なリストを計算する方法を考え出す。 「なぜ200人ですか?」「なぜ清掃員ですか?」という質問に答えてください。

5.結果を自動的に分析して、1つまたは2つの単語に意味があることを理解する方法を理解する必要があります。



All Articles