Life is Like a Boat

忘備録や経済、投資、プログラミングに関するメモやtipsなど

Puppeteerを使って決算発表日をスクレイピングする

3Qの決算発表に向けて色々と準備を進めているところです。

今回は、どの企業がいつ決算を発表するか確実に把握しておきたいです。したがって、どこからかデータを事前に取り込んでおく必要があります。

どのサイトがいいかなとポチポチ経済サイトを見ていたところ、日経が決算発表スケジュールをこんな感じでまとめています。

決算発表スケジュール :企業業績・財務 :マーケット :日経電子版 f:id:nerimplo:20181013205930p:plain

決算種別も書いてあります。よさげなので、Puppeteerを使ってスクレイピングしてみました。

まぁPythonでもできるんですが、最近JavaScriptを書く機会が減ってしまい、リハビリも兼ねてます。

npm installl して node run.js yyyymmdd 例えば、2018年10月15日に決算発表する企業を知りたければ、20181015とします。

実行後、run.jsと同じディレクトリにnikkei_earnings_release_date_20181015.csvが作成されているはずです。

ちなみに、PuppeteerはヘッドレスChromeまたはChromiumを制御するためのハイレベルなAPIを提供するNodeライブラリです。

例えば、

  • スクリーンショットやPDFの生成
  • Webサイトスクレイプ
  • フォームテストの自動化などブラウザを使うテストの自動化

のようなことができます。開発はChrome DevTools のチームが行なっているので、開発の永続性、メンテの質など高く信頼できると思います。

package.json

{
  "name": "EarningsReleaseDateScrapper",
  "version": "0.0.1",
  "description": "",
  "main": "run.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "moment": "^2.20.1",
    "puppeteer": "git://github.com/GoogleChrome/puppeteer.git"
  },
  "devDependencies": {
    "csv": "^3.1.0",
    "csv-writer": "^1.0.0",
    "gulp-env": "^0.4.0",
    "node-env-file": "^0.1.8"
  }
}

run.js

const puppeteer = require('puppeteer');
const fs = require('fs')
const {promisify} = require('util');
const moment = require('moment')
const createCsvWriter = require('csv-writer').createObjectCsvWriter;


const NIKKEI_EARNINGS_URL = "https://www.nikkei.com/markets/kigyo/money-schedule/kessan/?ResultFlag=1&kwd=&KessanMonth=&SearchDate1=2018%E5%B9%B407&SearchDate2=31"
const FAKE_USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, likeGecko) Chrome/41.0.2228.0 Safari/537.36';


async function go_to_url(page, url) {
    await page.goto(url);
    await page.waitFor(1500);
    return page;
}


async function hasNextPage(page) {
    const pageIndexBoxTop = await page.evaluate(() => {
        return document.querySelector('div.pageIndexBoxTop');
    })

    const hasNextPageLink = await page.evaluate(()=>{
        return document.querySelector('div.pageIndexBoxTop li.nextPageLink a')
    })

    return pageIndexBoxTop && hasNextPageLink;
}

async function scrape_table(page, date) {
    const data = await page.evaluate((date) => {
        return Array.from(document.querySelectorAll('div.m-artcle table tr.tr2')).map((e)=>{
            return [date].concat(Array.from(e.querySelectorAll('td')).map((e)=>{return e.textContent}))
        })
    }, date)
    return data
}

async function click_next_page(page) {
    const nxtPageArrow = await page.$('div.pageIndexBoxTop li.nextPageLink a');
    await nxtPageArrow.click();
    await page.waitFor(3000);
    return page;
}

async function WriteDataToCSV(path, records) {
    const csvWriter = await createCsvWriter({
        path: path,
        header: [0,1,2,3,4,5,6,7,8]
    });

    await csvWriter.writeRecords(records)       // returns a promise
        .then(() => {
            console.log('...Done');
        });
}



(async () => {

    const d = process.argv[2]

    if (d.length != 8) {
        console.log('yyyymmdd形式で日付を入力してください')
        return;
    }

    const year = d.substring(0,4)
    const month = d.substring(4,6)
    const day = d.substring(6,8)

    const NIKKEI_EARNINGS_URL = `https://www.nikkei.com/markets/kigyo/money-schedule/kessan/?ResultFlag=1&kwd=&KessanMonth=&SearchDate1=${year}%E5%B9%B4${month}&SearchDate2=${day}`


    let dataList = []
    const browser = await puppeteer.launch({headless: false});
    let page = await browser.newPage();
    page = await go_to_url(page, NIKKEI_EARNINGS_URL);
    let data = await scrape_table(page, d)

    dataList = dataList.concat(data)

    let flag = await hasNextPage(page);
    while (flag) {
        page = await click_next_page(page)
        data = await scrape_table(page, d)
        dataList = dataList.concat(data)
        flag = await hasNextPage(page);
    }

    console.log(dataList)

    await WriteDataToCSV('./nikkei_earnings_release_date_'+ d +'.csv', dataList);


    await browser.close()


})()

Puppeteer入門 スクレイピング+Web操作自動処理プログラミング

Puppeteer入門 スクレイピング+Web操作自動処理プログラミング