背景
自然言語処理をやりたくて、いろいろ調べていたところ、次のサイトを発見し、写経させていただきました。
ありがとうございました。
https://qiita.com/shizuma/items/44c016812552ba8a8b88
1年以上前の記事ということもあり、自分なりに少し修正は行いましたが、一番下に「今後の課題」として書きましたが、完ぺきとはいきませんでした。
上記参考サイトでは1000ユーザまで実行可能なようですが、この記事のコードだと、条件(25ユーザまで)付きで実効可能な感じです。
(20180127追記開始)
以前の投稿では、25ユーザまでしか実行できないという条件付きだったのですが、エラー処理を加え、特に制約条件はなくなりました(と思います(^_^;))。
とりあえず3ページ分スクレイピングし、60ユーザまではOKであることは確認しました。
最初は5ページ100ユーザで挑戦したのですが、Qiita APIの1時間あたりのアクセス上限?にかかってしまうようで、3ページ分60ユーザで実行しました。
出力結果などは、修正後の結果に差し替えました。
(20180127追記終了)
~~条件付きではありますが、~~僕と同じように、とにかく自然言語処理してみたいという人、のお役に立てれば幸いです。
環境
Ubuntu 16.04
Windows10(Bash on Ubuntu on Windows)
Python 3.6.3 :: Anaconda, Inc.
anaconda Command line client (version 1.6.5)
jupyter notebook
1.ユーザ名の取得
まず、BeautifulSoupを使って、Qiitaのユーザランキングのページから、~~上位20人(1ページ分)~~上位60人(3ページ分)を取得。
- コード
import requests
from bs4 import BeautifulSoup
import csv
import time
base_url = 'https://qiita-user-ranking.herokuapp.com/'
#max_page = 50
max_page = 3 # 1ページあたりユーザー20
qiita_users = []
for i in range(max_page):
target_url = base_url + "?page=" + str(i + 1)
target_html = requests.get(target_url).text
soup = BeautifulSoup(target_html, 'html.parser')
users = soup.select('main > p > a')
for k, user in enumerate(users):
qiita_users.append([(i*20 + k + 1), user.get_text()])
time.sleep(1)
print('scraping page: ' + str(i + 1))
f = open('qiita_users.csv', 'w')
writer = csv.writer(f, lineterminator='\n')
writer.writerow(['user_id', 'name'])
for user in qiita_users:
print(user)
writer.writerow(user)
f.close()
- 出力結果
「qiita_users.csv」として、次のようなcsvファイルが作成されます。
scraping page: 1
[1, 'hirokidaichi']
[2, 'jnchito']
[3, 'suin']
・・・
(以下、割愛)
- ユーザがフォローしているタグの取得
ランキング上位20名のユーザがフォローしているタグ(pythonとか、Gitとか)を、QiitaAPIをつかったスクレイピングにより取得。
ここで問題発生。
参考にしたソースコードは1年以上前のもので、現在のQiitaAPIはV1から「V2」に変更されていた。
なんとか「V2」で情報を取得はできたが、取得できる情報の内容が変更されている感じ。
- コード
import csv, requests, os.path, time
f = open('qiita_users.csv', 'r')
reader = csv.reader(f)
next(reader)
qiita_tags = []
qiita_user_tags = []
if os.path.isfile('qiita_user_tags.csv'):
user_tag_num = sum(1 for line in open('qiita_user_tags.csv'))
else:
user_tag_num = 0
if os.path.isfile('qiita_tags.csv'):
f_tag = open('qiita_tags.csv', 'r')
reader_tag = csv.reader(f_tag)
qiita_tags = [tag[0] for tag in reader_tag]
f_tag = open('qiita_tags.csv', 'w')
writer_tag = csv.writer(f_tag, lineterminator='\n')
f_user_tag = open('qiita_user_tags.csv', 'a')
writer_user_tag = csv.writer(f_user_tag, lineterminator='\n')
for user in reader:
if user_tag_num < int(user[0]):
# target_url = 'https://qiita.com/api/v1/users/' + user[1] + '/following_tags'
target_url = 'https://qiita.com/api/v2/users/' + user[1] + '/following_tags' #「v1」から「v2」へ変更
print('scraping: ' + user[0])
try:
result = requests.get(target_url)
except requests.exceptions.HTTPError as e:
print(e)
break
target = result.json()
# if 'error' in target:
# print(target['error'])
# if target['error'] == 'Rate limit exceeded.':
# break
# continue
#(20180127追記)エラー処理開始
if 'type' in target:
print(target['type'])
if target['type'] == 'not_found.':
break
continue
#(20180127追記)エラー処理終了
qiita_user_tag = [int(user[0])]
for tag in target:
#if tag['name'] in qiita_tags:
#qiita_user_tag.append(qiita_tags.index(tag['name']) + 1)
if tag['id'] in qiita_tags: #tag['name']から、tag['id']へ変更
qiita_user_tag.append(qiita_tags.index(tag['id']) + 1) #tag['name']から、tag['id']へ変更
else:
#qiita_tags.append(tag['name'])
qiita_tags.append(tag['id']) #tag['name']から、tag['id']へ変更
tag_num = len(qiita_tags)
qiita_user_tag.append(tag_num)
qiita_user_tags.append(qiita_user_tag)
time.sleep(1)
for tag in qiita_tags:
writer_tag.writerow([tag])
writer_user_tag.writerows(qiita_user_tags)
f_tag.close()
f_user_tag.close()
f.close()
- 出力結果(qiita_tags.csv)
GoogleAppsScript
ActionScript
JavaScript
CSS
・・・
(以下割愛)
- 出力結果(qiita_user_tags.csv)
1,1,2,3,4
2,5,6,7,8,9,10,3,11,12,13,14,15,16,17,18,19,20
3,21,22,17,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39
4,40,41,42,43,44,45,46,47,48,49,50,3,51
5,52,53,54,55,56,57,58,59,60,61,62,63,64,65,43,66,67,68,69,70
6,71,35,72,73,74,62,66,75,18,76,77,78,41,79,80,15,42,81,82,47
(以下、割愛)
3.出力結果の成型
- コード
import csv
import gensim
from pandas import DataFrame
tag_name_dict = {}
with open('qiita_tags.csv', 'r') as f_tags:
tag_reader = csv.reader(f_tags)
for i, row in enumerate(tag_reader):
tag_name_dict[(i+1)] = row[0]
user_tags_dict = {}
with open('qiita_user_tags.csv', 'r') as f_user_tags:
user_tags_reader = csv.reader(f_user_tags)
for i, row in enumerate(user_tags_reader):
user_tags_dict[int(row[0])] = row[1:-1]
tags_list = []
for k, v in user_tags_dict.items():
tags_list.extend(v)
once_tags = [tag for tag in tags_list if tags_list.count(tag) == 1]
user_tags_dict_multi = { k: [tag for tag in user_tags if not tag in once_tags] for k, user_tags in user_tags_dict.items()}
user_tags_dict_multi = {k: v for k, v in user_tags_dict_multi.items() if not len(v) == 0}
corpus = [[(int(tag), 1) for tag in user_tags]for k, user_tags in user_tags_dict_multi.items()]
lda = gensim.models.ldamodel.LdaModel(corpus=corpus, num_topics=15)
topic_top10_tags = []
for topic in lda.show_topics(-1, formatted=False):
topic_top10_tags.append([tag_name_dict[int(tag[0])] for tag in topic[1]])
topic_data = DataFrame(topic_top10_tags)
print(topic_data)
print("------------------")
c = [(1, 1), (2, 1)]
for (tpc, prob) in lda.get_document_topics(c):
print(str(tpc) + ': '+str(prob))
- 実行結果
0 1 2 3 4 \
0 Swift iOS docker Git Objective-C
1 GLSL 機械学習 Node.js JavaScript ShellScript
2 Qiita Swift chef iPhone JavaScript
3 docker Elixir Hubot vagrant itamae
4 gcp lambda es6 MySQL GraphQL
5 Node.js CoffeeScript iOS 機械学習 HTML
6 RSpec Zsh Qiita Redis MySQL
7 機械学習 DeepLearning Keras Emacs R
8 Swift TypeScript angular Angular2 gulp
9 Elixir Blockchain TensorFlow Swift solidity
10 docker Polymer Phoenix Erlang lisp
11 Heroku Kotlin vue.js dotfiles Arukas
12 RaspberryPi CSS3 docker R Emacs
13 JavaScript Android TypeScript Haskell Node.js
14 Python Go Linux Node.js googlecomputeengine
5 6 7 8 9
0 MacOSX iPhone Ruby Rails GitHub
1 Swift HoloLens Android DeepLearning MachineLearning
2 Rails MongoDB api CoffeeScript Python
3 GitLab Ruboty TOML crystal JavaScript
4 JavaScript Emacs Swift Android Haskell
5 TensorFlow Ethereum CSS Chainer Cryptocurrency
6 Rails Ruby CoffeeScript Git Go
7 Python CoffeeScript Qiita docker TensorFlow
8 Vim Go Android 機械学習 Xcode
9 Ethereum atom-shell chef Terraform GitLab
10 Elixir nginx Swift GLSL TypeScript
11 pandas React mecab JavaScript Emacs
12 Java Chrome jasmine TypeScript HTML
13 HTML golang Go SQL Ruby
14 C# MySQL Ruby JavaScript ShellScript
------------------
0: 0.022222246643926906
1: 0.022222263995008054
2: 0.022222255047640332
3: 0.02222229444346636
4: 0.6888882649724504
5: 0.022222267884482987
6: 0.02222226608552513
7: 0.02222225896685582
8: 0.022222259566950935
9: 0.02222228246944507
10: 0.02222226546848409
11: 0.02222229498350666
12: 0.02222226471356833
13: 0.022222261560756094
14: 0.022222253197932956
この投稿が、何かのお役にたてればうれしいです。