Pythonで総選挙データのスクレイピング
AKB48総選挙データのスクレイピング
import csv from urllib.request import urlopen from bs4 import BeautifulSoup url = 'http://www.akb48.co.jp/sousenkyo_45th/result.php' html = urlopen(url).read() soup = BeautifulSoup(html, 'html.parser') with open('akb48.csv', 'w') as fw: writer = csv.writer(fw, dialect='excel', lineterminator='\n') # ヘッダー writer.writerow(['rank', 'akb_names', 'akb_count']) for i in soup.select('#main_area > div.frameFix > div > ul > li'): # 順位 前後の「第位」を削除=>数値化 rank = int( i.select_one('p.result_rank').get_text(strip=True).strip('第位')) # 得票数 後の「票」を削除=>カンマ削除=>数値化 count = int( i.select_one('p.result_count').get_text( strip=True).rstrip('票').replace(',', '')) # 名前 name = i.select_one('h4.result_name').get_text(strip=True) writer.writerow([rank, name, count])
2017年総選挙データ(東京)のスクレイピング
from urllib.request import urlopen from bs4 import BeautifulSoup import csv url = 'http://www.asahi.com/senkyo/senkyo2017/kaihyo/A13.html' html = urlopen(url).read() soup = BeautifulSoup(html, 'html.parser') with open('hr2017_tokyo.csv', 'w') as fw: writer = csv.writer(fw, dialect='excel', lineterminator='\n') # ヘッダー writer.writerow( ['num', 'name', 'age', 'count', 'party', 'status', 'previous']) for num, i in enumerate( soup.select('div.areabox > table > tbody > tr'), start=1): # 姓 sei = i.select_one('td.namae > div > span.sei').get_text(strip=True) # 名 mei = i.select_one('td.namae > div > span.mei').get_text(strip=True) # 年齢 age = int( i.select_one('td.namae > div > span.age').get_text( strip=True).strip('()')) # 得票数 count = int( i.select_one('td.num > div').contents[0].strip().replace(',', '')) # 政党 party = i.select_one('td.party > div').get_text(strip=True) # 新旧 status = i.select_one('td.status > div').get_text(strip=True) # 当選回数 previous = int( i.select_one('td.tosenkaisu > div').get_text( strip=True).rstrip('回')) writer.writerow( [num, sei + ' ' + mei, age, count, party, status, previous])
Pythonのマルチスレッドで同じものを含む順列
import concurrent.futures def permutations(head, rest): if len(rest) == 0: return [head] else: res = [] # set(集合)型で重複を削除、ソート data = sorted(set(rest)) for i in data: #配列の複製 restx = rest[:] #指定データ削除 restx.remove(i) headx = head + [i] res += permutations(headx, restx) return res if __name__ == '__main__': data = [1, 1, 1, 1, 2, 2, 2, 3, 3, 4] data_list = [] for i in set(data): temp = data[:] temp.remove(i) data_list.append([[i], temp]) with concurrent.futures.ThreadPoolExecutor(max_workers=4) as executor: futures = [ executor.submit(permutations, head, rest) for head, rest in data_list ] for future in concurrent.futures.as_completed(futures): res = future.result() print(res)
mineoのパケットギフトに変換
パケットギフト自動取得したい
driver.find_element_by_name("nablarch_form1_1").click()
ここでエラー、一回だけログイン通ったけど次から通らない エラー後コマンドで打つとログイン通るんだけどなんで?
from selenium import webdriver from selenium.webdriver.chrome.options import Options from selenium.webdriver.support.ui import WebDriverWait from bs4 import BeautifulSoup options = Options() # ヘッドレスモードを有効にする(次の行をコメントアウトすると画面が表示される)。 # options.add_argument('--headless') # ChromeのWebDriverオブジェクトを作成する。 driver = webdriver.Chrome(chrome_options=options) mineo_id = 'xxxxx' mineo_pass = 'xxxxx' # ブラウザ操作 driver.get("http://mineo.jp/") driver.find_element_by_xpath( "//nav[@id='small_top-navigation']/div/div[2]/a[2]").click() # 別ウインドウに切替 WebDriverWait(driver, 3).until(lambda d: len(d.window_handles) > 1) driver.switch_to.window(driver.window_handles[1]) driver.find_element_by_id("eoID").clear() driver.find_element_by_id("eoID").send_keys(mineo_id) driver.find_element_by_name("form.loginPassword").clear() driver.find_element_by_name("form.loginPassword").send_keys(mineo_pass) driver.find_element_by_name("nablarch_form1_1").click() while True: html = driver.page_source soup = BeautifulSoup(html, 'html.parser') temp = soup.select_one( '#boxData > div.detailArea > div.boxPacketGift01 > dl > dd > div.top > div > p.detail' ).get_text(strip=True).rstrip('MB') packet = int(temp.replace(',', '')) if packet > 9: gift_packet = 999 if packet > 9990 else packet // 10 packet -= gift_packet * 10 print(gift_packet, packet) driver.find_element_by_id( "GCC010301GCC010301_Init_packetGiftYoryo").clear() driver.find_element_by_id( "GCC010301GCC010301_Init_packetGiftYoryo").send_keys( str(gift_packet)) driver.find_element_by_id( "GCC010301GCC010301_Init_GCC010301GCC010301_SendGift").click() driver.find_element_by_id( "GUG010101GUG010101_Init_GUG010101BtnNext_Submit").click() driver.find_element_by_id( "GUG010201GUG010201_Init_GUG010201BtnTop_Submit").click() else: break driver.quit()
Python3 Webスクレイピングの実践入門
「1時間ごとに日本経済新聞にアクセスを行いその時の日経平均株価をcsvに記録する」を
定時実行を「apscheduler」に「select_one」でCSSセレクタで取得に変更しました
基本
Beautiful Soup Documentation — Beautiful Soup 4.4.0 documentation
kondou.com - Beautiful Soup 4.2.0 Doc. 日本語訳 (2013-11-19最終更新)
先頭のひとつ取得
- find(name, attrs, recursive, string, **kwargs)
- select_one(selector)
複数取得
- find_all(name, attrs, recursive, string, limit, **kwargs)
- select(selector, _candidate_generator=None, limit=None)
準備
パッケージをインストール
# Python 3.6.2
pip install requests
pip install apscheduler
pip install beautifulsoup4
日経平均株価のCSSセレクタを取得
Chromeで日本経済新聞のホームページにアクセス http://www.nikkei.com/markets/kabu/
日経平均株価を選択し右クリック-検証を選択する
HTMLのソースが反転しているところで右クリック-Copy-Copy selectorを選択する
#CONTENTS_MARROW > div.mk-top_stock_average.cmn-clearfix > div.cmn-clearfix > div.mkc-guidepost > div.mkc-prices > span.mkc-stock_prices
nikkei_heikin = soup.select_one('#CONTENTS_MARROW > div.mk-top_stock_average.cmn-clearfix > div.cmn-clearfix > div.mkc-guidepost > div.mkc-prices > span.mkc-stock_prices').get_text(strip=True)
スクレイピング
import csv import datetime import requests from apscheduler.schedulers.blocking import BlockingScheduler from bs4 import BeautifulSoup sched = BlockingScheduler() # 1時間ごとに実行する # @sched.scheduled_job('interval', hours=1) # 毎時0分に実行する @sched.scheduled_job('cron', minute=0, hour='*/1') def scheduled_job(): # 日本経済新聞の日経平均株価ページにアクセスし、HTMLを取得する r = requests.get('http://www.nikkei.com/markets/kabu/') # エラーがないか確認する if r.status_code == requests.codes.ok: # BeautifulSoupを使い日経平均株価を取得する soup = BeautifulSoup(r.content, 'html.parser') nikkei_heikin = soup.select_one( '#CONTENTS_MARROW > div.mk-top_stock_average.cmn-clearfix > div.cmn-clearfix > div.mkc-guidepost > div.mkc-prices > span.mkc-stock_prices' ).get_text(strip=True) # 今の時間を文字列に変換する now = datetime.datetime.now().strftime('%Y/%m/%d %H:%M:%S') print('{} {}'.format(now, nikkei_heikin)) # CSVに日時と日経平均株価の値を追記する with open('nikkei_heikin.csv', 'a') as fw: writer = csv.writer(fw, dialect='excel', lineterminator='\n') writer.writerow([now, nikkei_heikin]) sched.start()
標準ライブラリの場合
例 find('タグ名', class_='クラス名')
from urllib.request import urlopen from bs4 import BeautifulSoup url = "http://www.nikkei.com/markets/kabu/" html = urlopen(url).read() soup = BeautifulSoup(html, 'html.parser') nikkei_heikin = soup.find('span', class_='mkc-stock_prices').string print(nikkei_heikin)
蒼社川の水位をスクレイピング
import datetime import requests from bs4 import BeautifulSoup def scraping(): url = 'http://183.176.244.72/cgi/050_HQ_100_03.cgi?GID=050_HQ_100&UI=U777&SI=00000&DT=000000000000&DBDT=0000000000&MNU=1&DTO=-1&DN=0972900400025&KTM=3&GHK=3&YSK=0&SRO=1&LO=88&TD=0000&BTY=IE6X&cSessionID=0000000000000000000000&UIS=000000000000&SIMU=0&ZM=0' r = requests.get(url) soup = BeautifulSoup(r.content, 'html5lib') data = [] for trs in soup.select('body > table > tbody > tr'): temp = [i.get_text(strip=True) for i in trs.select('td.right-10')] # 日付 補完 if temp[0]: day = temp[0] else: temp[0] = day today = datetime.datetime.now() # 時間が24:00のときは00:00に変更し、+1日する if temp[1] == '24:00': hiduke = datetime.datetime.strptime( str(today.year) + '/' + temp[0] + ' ' + '00:00', '%Y/%m/%d %H:%M') hiduke += datetime.timedelta(days=1) else: hiduke = datetime.datetime.strptime( str(today.year) + '/' + temp[0] + ' ' + temp[1], '%Y/%m/%d %H:%M') if hiduke > today: hiduke -= datetime.timedelta(years=1) try: water_level = float(temp[2]) except: pass else: data.append([hiduke, water_level]) return (data[-1][0], data[-1][1], data[-7][1]) if __name__ == '__main__': hiduke, wl_now, wl_hour = scraping() print('{}現在の水位は{}mです。'.format(hiduke.strftime('%Y/%m/%d %H:%M'), wl_now)) # 1時間前の水位と比較 if wl_now > wl_hour: if wl_now >= 2.85: print('はん濫危険水位') elif wl_now >= 2.60: print('避難判断水位') elif wl_now >= 2.40: print('はん濫注意水位') elif wl_now >= 2.10: print('水防団待機水位')