In [1]:
import requests
import yaml
import os.path

In [2]:
response = requests.get("https://iosdc.jp/2016/c/api/talks.json")

In [3]:
j = response.json()

In [4]:
len(j)


Out[4]:
40

In [5]:
j[0]


Out[5]:
{'changed': [{'value': '1471577660'}],
 'created': [{'value': '1467108923'}],
 'default_langcode': [{'value': '1'}],
 'field_abstract': [{'format': None,
   'value': 'フリマアプリ フリルはここ1年で2度の大規模リニューアルを行いました。\nこのトークではフリルでの経験を元に、ユーザーに受け入れられ、問題を起こしづらいリニューアルの進め方をエンジニア目線でお話しします。\nリニューアルでありがちな大きなバグの発生や、星1レビューの嵐をいかにして防ぐか、開発チームの総力戦となる大規模プロジェクトをいかにスムーズに進めるかについてお話しします。'}],
 'field_adoption_no': [],
 'field_no': [{'value': '55'}],
 'field_slide_will_be_shared': [{'value': '1'}],
 'field_speaker': [{'value': 'shoby'}],
 'field_speaker_twitter': [{'value': 'shobyshoby'}],
 'field_submitted_at': [],
 'field_talk_adopted': [{'value': '1'}],
 'field_talk_date': [{'value': '2016/08/19'}],
 'field_talk_room': [{'value': 'A'}],
 'field_talk_start_at': [{'value': '2016/08/19 17:40'}],
 'field_talk_time': [{'value': '30分'}],
 'langcode': [{'value': 'ja'}],
 'nid': [{'value': '84'}],
 'path': [],
 'promote': [{'value': '1'}],
 'revision_log': [],
 'revision_timestamp': [{'value': '1467108923'}],
 'revision_translation_affected': [{'value': '1'}],
 'revision_uid': [{'target_id': '0',
   'target_type': 'user',
   'target_uuid': '5972e388-7b01-40dd-bc00-d1b758c9850d',
   'url': '/2016/c/en/user/0'}],
 'status': [{'value': '1'}],
 'sticky': [{'value': '0'}],
 'title': [{'value': 'ユーザーに受け入れられ、問題を起こしづらい大規模リニューアルの進め方'}],
 'type': [{'target_id': 'paper',
   'target_type': 'node_type',
   'target_uuid': '524edc0e-1589-4a93-8d00-dba5aeea6c69'}],
 'uid': [{'target_id': '0',
   'target_type': 'user',
   'target_uuid': '5972e388-7b01-40dd-bc00-d1b758c9850d',
   'url': '/2016/c/en/user/0'}],
 'uuid': [{'value': '3364a7eb-d598-4a98-bb03-3b08f0bc4a3f'}],
 'vid': [{'value': '88'}]}

In [6]:
def normalize(session):
    def get_value(d, k):
        try:
            return d[k][0]["value"]
        except:
            return None
    links = []
    twitter_account = get_value(session, "field_speaker_twitter")
    if twitter_account is not None:
        links.append({
            "title": "@" + twitter_account,
            "url": "https://twitter.com/" + twitter_account
        })
    time = get_value(session, "field_talk_time")
    nid = get_value(session, "nid")
    room = get_value(session, "field_talk_room")
    if room == "A":
        links.append({
                "title": "#iosdc #a",
                "url": "https://twitter.com/search?q=%23iosdc%20%23a"
            })
    elif room == "B":
        links.append({
                "title": "#iosdc #b",
                "url": "https://twitter.com/search?q=%23iosdc%20%23b"
            })
    enable_to_vote = not time.startswith("5分")
    if enable_to_vote:
        links.append({
                "title": "投票",
                "url": "https://iosdc.herokuapp.com/vote/" + nid
            })
    
    return {
        
        "session": {
            "description": get_value(session, "field_abstract"),
            "title": get_value(session, "title"),
            "start_at": get_value(session, "field_talk_start_at"),
            "room": room,
            "time": time,
            "nid": nid,
            "links": links,
            "speaker": {
                "name": get_value(session, "field_speaker"),
                "twitter_account": twitter_account,
            },
        }
    }

def normalize_sessions(sessions):
    for s in sessions:
        yield normalize(s)

In [7]:
session = list(normalize_sessions(j))[0]
def user_name(s):
    t = s["session"]["speaker"]["twitter_account"]
    if t is not None:
        return t
    else:
        return s["session"]["speaker"]["name"]

In [38]:
session


Out[38]:
{'session': {'description': 'フリマアプリ フリルはここ1年で2度の大規模リニューアルを行いました。\nこのトークではフリルでの経験を元に、ユーザーに受け入れられ、問題を起こしづらいリニューアルの進め方をエンジニア目線でお話しします。\nリニューアルでありがちな大きなバグの発生や、星1レビューの嵐をいかにして防ぐか、開発チームの総力戦となる大規模プロジェクトをいかにスムーズに進めるかについてお話しします。',
  'links': [{'title': '@shobyshoby', 'url': 'https://twitter.com/shobyshoby'},
   {'title': '投票', 'url': 'https://iosdc.herokuapp.com/vote/84'}],
  'nid': '84',
  'room': 'A',
  'speaker': {'name': 'shoby', 'twitter_account': 'shobyshoby'},
  'start_at': '2016/08/19 17:40',
  'time': '30分',
  'title': 'ユーザーに受け入れられ、問題を起こしづらい大規模リニューアルの進め方'}}

In [8]:
def twitter_account(s):
    t = s["session"]["speaker"]["twitter_account"]
    if t is not None:
        return t
    else:
        return None

twac = twitter_account(session)

In [9]:
import tweepy
key = ""
api_secret = ""
auth = tweepy.OAuthHandler(key, api_secret)
twapi = tweepy.API(auth)

In [10]:
user = twapi.get_user(twac)


---------------------------------------------------------------------------
TweepError                                Traceback (most recent call last)
<ipython-input-10-0c90fd2e461d> in <module>()
----> 1 user = twapi.get_user(twac)

/Users/hayashi311/.pyenv/versions/iosdc2016/lib/python3.5/site-packages/tweepy/binder.py in _call(*args, **kwargs)
    243             return method
    244         else:
--> 245             return method.execute()
    246 
    247     # Set pagination mode

/Users/hayashi311/.pyenv/versions/iosdc2016/lib/python3.5/site-packages/tweepy/binder.py in execute(self)
    227                     raise RateLimitError(error_msg, resp)
    228                 else:
--> 229                     raise TweepError(error_msg, resp, api_code=api_error_code)
    230 
    231             # Parse the response payload

TweepError: [{'message': 'Bad Authentication data.', 'code': 215}]

In [11]:
image_url = user.profile_image_url.replace("_normal", "")
# image_url = user.profile_image_url


---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-11-1b8da0188fe1> in <module>()
----> 1 image_url = user.profile_image_url.replace("_normal", "")
      2 # image_url = user.profile_image_url

NameError: name 'user' is not defined

In [12]:
img_response = requests.get(image_url, stream=True)
img_response


---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-12-6500b5a77e1c> in <module>()
----> 1 img_response = requests.get(image_url, stream=True)
      2 img_response

NameError: name 'image_url' is not defined

In [13]:
img_response.raw.data


---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-13-bd30cb065432> in <module>()
----> 1 img_response.raw.data

NameError: name 'img_response' is not defined

In [14]:
img_response.raw

path = "/Users/hayashi311/Desktop/dev/iosdcjp2016app/WebAPI/static/speakers/{}.jpg".format(twac)

if img_response.status_code == 200:
    with open(path, 'wb') as f:
        f.write(img_response.raw.data)


---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-14-de20bb056e3c> in <module>()
----> 1 img_response.raw
      2 
      3 path = "/Users/hayashi311/Desktop/dev/iosdcjp2016app/WebAPI/static/speakers/{}.jpg".format(twac)
      4 
      5 if img_response.status_code == 200:

NameError: name 'img_response' is not defined

In [15]:
i = img_response.raw


---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-15-5f01848a4835> in <module>()
----> 1 i = img_response.raw

NameError: name 'img_response' is not defined

In [16]:
def fetch_user_image(user_name):
    jpg_path = "/Users/hayashi311/Desktop/dev/iosdcjp2016app/WebAPI/static/speakers/{}.jpg".format(user_name)
    if os.path.isfile(jpg_path):
        print(user_name,': image file exists')
        return "/static/speakers/{}.jpg".format(user_name)
    png_path = "/Users/hayashi311/Desktop/dev/iosdcjp2016app/WebAPI/static/speakers/{}.png".format(user_name)
    if os.path.isfile(png_path):
        print(user_name,': image file exists')
        return "/static/speakers/{}.png".format(user_name)
    print(user_name,': fetch image')
    user = twapi.get_user(twac)
    image_url = user.profile_image_url.replace("_normal", "")
    img_response = requests.get(image_url, stream=True)
    if img_response.status_code == 200:
        with open(path, 'wb') as f:
            f.write(img_response.raw.data)
    return "/static/speakers/{}.jpg".format(user_name)
    

fetch_user_image(twitter_account(session))


shobyshoby : image file exists
Out[16]:
'/static/speakers/shobyshoby.jpg'

In [ ]:


In [17]:
for s in normalize_sessions(j):
    print(s["session"]["nid"], s["session"]["speaker"]["name"])
    twac = twitter_account(s)
    if twac is not None:
        s["session"]["speaker"]["image"] = fetch_user_image(twac)
    
    path = "/Users/hayashi311/Desktop/dev/iosdcjp2016app/WebAPI/data/speakers/{}.yaml".format(user_name(s))
    f = open(path, 'w')
    f.write(yaml.dump(s, default_flow_style=False, allow_unicode=True))
    f.close()


84 shoby
shobyshoby : image file exists
72 Yuki Takei
noppoMan722 : image file exists
34 田中賢治
ktanaka117 : image file exists
123 kazunori kikuchi
kichikuchi : image file exists
36 huin
huin : image file exists
40 宇佐見 公輔
usamik26 : image file exists
110 へんてこ
bilyakudan : image file exists
208 Kishikawa Katsumi
k_katsumi : image file exists
146 堤 修一
shu223 : image file exists
168 藤崎 智宏/岡田 雅之
smadako : image file exists
139 ishkawa
_ishkawa : image file exists
124 meyco
meyco : image file exists
184 TachibanaKaoru
TachibanaKaoru : image file exists
41 Yukinaga Azuma
yuky_az : image file exists
32 稲見 泰宏
inamiy : image file exists
122 Yusuke Wada
yusukebe : image file exists
133 Mao Nishi
mao_nishi : image file exists
54 Kosuke Ogawa
koogawa : image file exists
129 Ray Fix
rayfix : image file exists
78 Noritaka Kamiya
nolili : image file exists
176 Hiroki Kato
cockscomb : image file exists
65 nakajijapan
nakajijapan : image file exists
100 Yuichiro Masui
masuidrive : image file exists
155 小野 将之
_mono : image file exists
86 熊谷 友宏
es_kumagai : image file exists
161 satoshi0212
shmdevelop : image file exists
116 Toshihiro Morimoto
dealforest : image file exists
71 Yuji Hato
dekatotoro : image file exists
189 池田 翔
ikesyo : image file exists
46 よぴた
yopita_ : image file exists
182 にわタコ
niwatako : image file exists
165 yimajo
yimajo : image file exists
188 Yusuke Ohashi
iMickx : image file exists
154 Motoki Narita
motokiee : image file exists
55 ezura
eduraaa : image file exists
162 原 一史
haranicle : image file exists
187 Yoichiro Sakurai
saku2saku : image file exists
117 wasabeef
wasabeef_jp : image file exists
173 m-naruse
37 kaneshin
kaneshin0120 : image file exists

In [ ]: