-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathScrapePyCampList.py
More file actions
149 lines (127 loc) · 5.49 KB
/
ScrapePyCampList.py
File metadata and controls
149 lines (127 loc) · 5.49 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
import requests
from bs4 import BeautifulSoup
import japanmap as jm
import json
import csv
import ast
from sendmailgun import sendMessage
prefnames = ('_', '北海道', '青森', '岩手', '宮城', '秋田', '山形', '福島', '茨城', '栃木',
'群馬', '埼玉', '千葉', '東京', '神奈川', '新潟', '富山', '石川', '福井', '山梨',
'長野', '岐阜', '静岡', '愛知', '三重', '滋賀', '京都', '大阪', '兵庫', '奈良',
'和歌山', '鳥取', '島根', '岡山', '広島', '山口', '徳島', '香川', '愛媛', '高知',
'福岡', '佐賀', '長崎', '熊本', '大分', '宮崎', '鹿児島', '沖縄')
def parse_connpass(url):
'''
input:
url: connpassのPyCamp開催情報URL
output:
address: 郵便番号を含むPyCamp開催会場の所在地
status: 開催済みかどうか 1=開催済み 0=開催予定
'''
res = requests.get(url)
content = res.content
soup = BeautifulSoup(content, 'html.parser')
infos = soup.find_all('div', class_='group_inner clearfix')
statusinfo = soup.find_all('span', class_='label_status_event close')
if len(statusinfo)>0 and '終了' in statusinfo[1]:
status = 1 # 終了
else:
status = 0 # 開催予定
address = ''
for info in infos[0].select('li'):
if '〒' in info.text:
address = info.get_text()
if address == '':
# connpassのAPIをevent_idで叩いて開催地住所を取得
res2 = requests.get("https://connpass.com/api/v1/event/?event_id=" + url.split('/')[-2])
content2 = ast.literal_eval(res2.content.decode())
address2 = content2["events"][0]["address"]
# 開催地住所をGoogleで検索
google = requests.get("https://www.google.co.jp/search?q=" + address2)
content3 = google.content
soup3 = BeautifulSoup(content3, 'html.parser')
infos3 = soup3.find_all("span", class_="st") # 検索結果はだいたい同じ場所のはず
for info in infos3:
if "〒" in info.text:
address = info.get_text()
return address, status
# 開催地住所をyahooで検索
yahoo = requests.get("https://search.yahoo.co.jp//search?p=" + address2)
content4 = yahoo.content
soup4 = BeautifulSoup(content4, 'html.parser')
infos4 = soup4.find_all("div")
for info in infos4:
if "〒" in info.text:
address = info.get_text()
return address, status
sendMessage('parse_connpassでエラー', '開催地の住所が取得できませんでした。\n\n' + url)
return address, status
def pref_code(address):
'''
input:
address: 郵便番号を含む開催会場の所在地
output:
県コード(1〜43)
該当する県を見つけられなかった場合は0
'''
# 郵便番号部に半角スペースが入っていると以下の処理が失敗するので削除。住所部にも影響があるがこの関数としては無関係
address = address.replace(' ', '')
# zip = address[1:9] # これでは甘かった
start = address.find('〒')
zip = address[start+1:start+9]
res = requests.get('http://geoapi.heartrails.com/api/json?method=searchByPostal&postal=' + zip)
try:
prefecture = res.json()['response']['location'][0]['prefecture']
return jm.pref[prefecture]
except:
# 郵便番号リストをしらみつぶし
with open('JIGYOSYO.CSV', 'r', encoding='cp932') as f:
postreader = csv.reader(f)
for row in postreader:
if row[7] == zip.replace('-', ''):
prefecture = row[3]
return jm.pref[prefecture]
# それでもだめなら
sendMessage('pref_codeで失敗', '郵便番号で都道府県が指定できませんでした。確認してください\n\n' + address)
return 0
def parse_pycamp():
'''
PyCamp開催情報をパースして,connpassの開催情報URLをすべて返す
'''
url = 'https://www.pycon.jp/support/bootcamp.html#id8'
res = requests.get(url)
content = res.content
soup = BeautifulSoup(content, 'html.parser')
return soup.find_all('a', class_='reference external')
def api():
'''
PyCampの開催地リストを取得して,県コードをキー,開催済みかどうかを値とする辞書を返す
'''
with open('info.dic') as f:
response = json.loads(f.read())
return response
def update():
'''
PyCampの開催地リストを取得して,県コードをキー,開催済みかどうかを値とする辞書をjsonで保存
'''
pycamps = parse_pycamp()
response = {}
for pycamp in pycamps:
url = pycamp['href']
name = pycamp.text
if ' in ' in name:
address, status = parse_connpass(url)
if address != '':
code = pref_code(address)
if code not in response: # まだなければ追加
response[code] = status
elif response[code] == 0: # すでにあっても未開催なら上書き
response[code] = status
else:
pass # どちらでもなければなにもしない(開催済み情報がすでにある)
with open('info.dic', 'w') as f:
f.write(json.dumps(response))
return 0
if __name__ == '__main__':
update()
print(api())