ウェブスクレイピングの手法をいくつかご紹介致します。
GAS、VBA、PHP、Python、それぞれを使って、Yahoo!Japanの主要ニュースを取得します。
結論からいうと、GAS + Spreadsheetのほうが気軽に使えてイチオシです。
##GAS + Spreadsheet
###良い点
Googleアカウントさえあれば、一切の環境を用意する必要がなく、GASのトリガーで定期的に実行できます。
###悪い点
大規模の実行にはパフォーマンスの懸念があります。
セキュリティ上、重要なデータの扱いはちょっと厳しいです。
###コード
function yahoo() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('yahoo');
//書き込むシート名を指定
var getUrl = 'https://www.yahoo.co.jp/';
//ターゲットページを指定
var content = UrlFetchApp.fetch(getUrl).getContentText('UTF-8');
var content = content.replace(/\r?\n/g, '');
var data = content.match(/<div class="_2jjSS8r_I9Zd6O9NFJtDN-" aria-label="主要 ニュース">(.*?)<\/div><div>/);
//コンテンツのブロックを設定
var data = data[0];
var URLs = data.match(/<a class="yMWCYupQNdgppL-NV6sMi _3sAlKGsIBCxTUbNi86oSjt" href="(.*?)"/g);
//URL群を一括で配列へ
var Titles = data.match(/<span class="fQMqQTGJTbIMxjQwZA2zk _3tGRl6x9iIWRiFTkKl3kcR">(.*?)<\/span>/g);
//記事名群を一括で配列へ
for (var i = 0; i < 8; i++) {
var URL = URLs[i];
URL = URL.replace('<a class="yMWCYupQNdgppL-NV6sMi _3sAlKGsIBCxTUbNi86oSjt" href="', '');
URL = URL.replace('"', '');
sheet.getRange(i + 2, 1).setValue(URL);
var Title = Titles[i];
Title = Title.replace('<span class="fQMqQTGJTbIMxjQwZA2zk _3tGRl6x9iIWRiFTkKl3kcR">', '');
Title = Title.replace('<\/span>', '');
sheet.getRange(i + 2, 2).setValue(Title);
}
Browser.msgBox('Done!');
}
##VBA + Excel
###良い点
リテラシーの低い利用者向けで、おなじみのエクセルで使って頂ける文はやはりありがたいです。
###悪い点
IEオブジェクトに依存しますので、Windows端末は必須となります。
IEの独特の仕様で現代的なウェブサイトでうまく動作しないケースがしばしばあります。
###ライブラリの追加
ExcelのVBA画面で
メニューバー > ツール > 参照設定
に下記2つのライブラリにチェックをつけます。
・Microsoft HTML Object Library
・Microsoft Internet Controls
###コード
Sub GetData_Click()
Application.ScreenUpdating = False
Dim objIE As InternetExplorer
Dim htmlDoc As HTMLDocument
Dim NewsItem IHTMLElement
Dim NewsList, NewsTitle, NewsURL As IHTMLElementCollection
Dim PageURL As String
Dim LastRow As Long
PageURL = "https://www.yahoo.co.jp/"
'新しいIEオブジェクトを作成してセット
Set objIE = CreateObject("Internetexplorer.Application")
objIE.Visible = False
'IEでURLを開く
objIE.navigate PageURL
'読み込み待ち
Do While objIE.Busy = True Or objIE.readyState < READYSTATE_COMPLETE
DoEvents
Loop
'objIEで読み込まれているHTMLドキュメントをセット
Set htmlDoc = objIE.document
'各項目のコンテンツ取得
Set NewsList = htmlDoc.getElementsByClassName("_2jjSS8r_I9Zd6O9NFJtDN-")
For Each NewsItem In NewsList
'各タグの検索用件を指定
Set NewsTitle = NewsItem.getElementsByTagName("a")
Set NewsURL = NewsItem.getElementsByClassName("fQMqQTGJTbIMxjQwZA2zk _3tGRl6x9iIWRiFTkKl3kcR")
'最終行を取得
LastRow = Worksheets("result").Cells(Rows.Count, 1).End(xlUp).Row
'各セルに該当する値を埋める
Worksheets("result").Cells(LastRow + 1, 1).Value = Right(NewsURL(0).href, 4)
Worksheets("result").Cells(LastRow + 1, 2).Value = NewsTitle(0).innerText
'見つからない場合にはスキップ
On Error Resume Next
Worksheets("result").Cells(LastRow + 1, 5).Value = Mid(Campagin(0).innerText, 2)
Worksheets("result").Cells(LastRow + 1, 6).Value = Mid(Campagin(1).innerText, 1)
Next NewsItem
MsgBox "Done!"
End Sub
##PHP + csv
###良い点
パフォーマンスがよいです。依存するライブラリも少ないです。
###悪い点
PHPを実行する環境が必要です。
###必要なライブラリ
phpQuery-onefile.php
上記ファイルをダウンロードし、本体のphpファイルと同じ階層に置く
###コード
<?php
require_once("phpQuery-onefile.php");
$path = "xxx/xxx.csv"; //出力するcsvを指定
$header = "URL".", ". "Title"."\n";
$file = fopen($path, "w");
$target = "https://www.yahoo.co.jp/";
$html = file_get_contents($target);
$list = phpQuery::newDocument($html)->find("div._2jjSS8r_I9Zd6O9NFJtDN-");
for($i = 0; $i < 8; $i++){
$url[$i] = phpQuery::newDocument($list)->find("li:eq($i)")->find("a")->attr("href");
$title[$i] = str_replace(",", "", phpQuery::newDocument($list)->find("span.fQMqQTGJTbIMxjQwZA2zk _3tGRl6x9iIWRiFTkKl3kcR:eq($i)")->text());
$data .= ".$url[$i].", ".$title[$i]."."\n";
}
$content = $header . $data;
fputs($file, $content);
fclose($file);
?>
##Python + csv
###良い点
パフォーマンスがよいです。すでにPythonを使っていれば、連携しやすいです。
###悪い点
Pythonの環境構築するにはちょっと手間です。すでにPythonを使っていれば、いろいろ連結して活用できるかもしれませんが、スクレイピングだけのためなら、PHPのほうが圧倒的に環境構築しやすいです。
###必要なライブラリをインストール
pip3 install requests
pip3 install beautifulsoup4
###コード
# coding: utf-8
import requests
from bs4 import BeautifulSoup
import csv
r = requests.get("https://yahoo.co.jp/")
data = BeautifulSoup(r.content, "html.parser")
list = data.find("div", "_2jjSS8r_I9Zd6O9NFJtDN-")
links = list.find_all("a", "")
titles = list.find_all("span", "fQMqQTGJTbIMxjQwZA2zk _3tGRl6x9iIWRiFTkKl3kcR")
with open('xxx/xxx.csv', 'w') as f:
# csvファイルの配置場所を決める
writer = csv.writer(f)
writer.writerow(['url', 'title'] )
for i in range(7):
writer.writerow([links[i].attrs['href'], titles[i].text])
##おまけ:ログインが必要なページの場合
ログインしないとコンテンツの閲覧ができない場合、Pythonのchromedriverを使うと便利です。
chromedriverの使い方についてはこちらの記事に詳しく紹介されています。
Python + Selenium で Chrome の自動操作を一通り
また、PATHの通し方やバージョンの注意点についてはこちらの記事をご参考してください。
[selenium向け] ChromeDriverをpipでインストールする方法(パス通し不要、バージョン指定可能)
###必要なライブラリ
pip3 install selenium
pip3 install chromedriver-binary
###コード
# coding: utf-8
import time, os, requests, sys, csv
from selenium import webdriver
import chromedriver_binary
# ユーザー名とパスワードの指定
user_id = "xxxxxxxxxx"
password = "xxxxxxxxxx"
download_dir = os.path.dirname(__file__)
# loginページURLの指定
login = 'https://www.example.com/login/'
# 保存先などオプションを指定してChromeを起動
opt = webdriver.ChromeOptions()
opt.add_experimental_option("prefs", {
"download.default_directory": download_dir,
"download.prompt_for_download": False,
"plugins.always_open_pdf_externally": True
})
driver = webdriver.Chrome(options=opt)
# ログインページを開く
driver.get(login)
time.sleep(3) # ページが開くまで待つ
# ログイン画面のユーザー名にキーを送信
u = driver.find_element_by_name('xxx')
u.send_keys(user_id)
# ログイン画面のパスワードにキーを送信
p = driver.find_element_by_name('yyy')
p.send_keys(password)
p.submit()
time.sleep(3) # ページが開くまで待つ
driver.get("https://www.example.com/listdata/")
list = driver.find_element_by_tag_name("_2jjSS8r_I9Zd6O9NFJtDN-")
links = list.find_all("a", "")
titles = list.find_all("span", "fQMqQTGJTbIMxjQwZA2zk _3tGRl6x9iIWRiFTkKl3kcR")
with open('xxx/xxx.csv', 'w') as f:
# csvファイルの配置場所を決める
writer = csv.writer(f)
writer.writerow(['url', 'title'] )
for i in range(7):
writer.writerow([links[i].attrs['href'], titles[i].text])
# ページが開くまで待つ
time.sleep(3)
driver.quit()
以上、5つの方法をご紹介しました。
使い道によっては、それぞれのメリット、デメリットがあります。
お役に立てれば幸いです。