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()

qiita.com

Python3 Webスクレイピングの実践入門

imabari.hateblo.jp

qiita.com

Python Webスクレイピング 実践入門」の

「1時間ごとに日本経済新聞にアクセスを行いその時の日経平均株価csvに記録する」を

定時実行を「apscheduler」に「select_one」でCSSセレクタで取得に変更しました

基本

imabari.hateblo.jp

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セレクタを取得

  1. Chrome日本経済新聞のホームページにアクセス http://www.nikkei.com/markets/kabu/

  2. 日経平均株価を選択し右クリック-検証を選択する f:id:imabari_ehime:20171107085404p:plain

  3. HTMLのソースが反転しているところで右クリック-Copy-Copy selectorを選択する f:id:imabari_ehime:20171107085502p:plain

  4. クリップボードCSSセレクタがコピーされているので以下のソースに貼り付ける

#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('水防団待機水位')