9
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

スクレイピングいろいろ

Last updated at Posted at 2020-05-22

ウェブスクレイピングの手法をいくつかご紹介致します。
GAS、VBA、PHP、Python、それぞれを使って、Yahoo!Japanの主要ニュースを取得します。
結論からいうと、GAS + Spreadsheetのほうが気軽に使えてイチオシです。

##GAS + Spreadsheet
###良い点
Googleアカウントさえあれば、一切の環境を用意する必要がなく、GASのトリガーで定期的に実行できます。
###悪い点
大規模の実行にはパフォーマンスの懸念があります。
セキュリティ上、重要なデータの扱いはちょっと厳しいです。

###コード

gas.js
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ファイルと同じ階層に置く
###コード

scraping.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

###コード

scraping.py
# 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

###コード

login_scraping.py
# 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つの方法をご紹介しました。
使い道によっては、それぞれのメリット、デメリットがあります。
お役に立てれば幸いです。

9
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?