スクレイピング対策

ヘッドレスChromeJavaScriptを有効にする teratail.com

スクレイピング https://gather-tech.info/news/2017/08/14/Gather59.html

ヘッドレスChromeからのアクセスを検出する方法について。User Agentによる判定、プラグインの有無による判定、画像読み込みがエラーになるときのサイズによる判定方法などが紹介されている。

一般的なUser Agentによる判定だと簡単に偽装できてしまうのでそれ以外の検出方法が書かれていて参考になります。画像が読み込めない場合のサイズの違いで検出できるとは驚きです。

Detecting Chrome Headless https://antoinevastel.com/bot%20detection/2017/08/05/detect-chrome-headless.html

qiita.com

こちらの再現性を低くするぐらいだったらまだ大丈夫かな

「日経」の文字のタグを検索してその子を抽出でいける。 数字以外は消せばいいので「\D」で置換

from bs4 import BeautifulSoup
import re


def nikkei_find(tag):
    return ('日経' in tag.contents[0])


doc = """<div>日経平均株価<b>114514</b></div>
<div>日経平均株価<span>114514</span></div>
<div>日経平均株価<div id="yaju">114514</div></div>"""

soup = BeautifulSoup(doc, 'html.parser')

for i in soup.find_all(nikkei_find):
    text = re.sub(r'\D', '', i.contents[1].get_text(strip=True))
    print(text)

doc = """<div>日経平均株価<b>114514</b></div>
<div>日経平均株価<b>114,514</b></div>
<div>日経平均株価<b>114 514</b></div>"""

soup = BeautifulSoup(doc, 'html.parser')

for i in soup.find_all(nikkei_find):
    text = re.sub(r'\D', '', i.contents[1].get_text(strip=True))
    print(text)

Chromebook C223Nのアプリ関連

海外版のレッドから日本版になってやっと帰ってきた

症状は電源不良みたい、最初起動したまま一度も電源落ちなかったし

imabari.hateblo.jp

imabari.hateblo.jp

Androidアプリ

Video & TV SideView

  • 初期設定画面の分割画面を解除はchromebookを最新版にして最大化にするとOK
  • 再生中のメニューが消せないのでかなりみずらい。消し方がわからない。
  • デュアルディスプレイにしてたら再生されない。

Amazonプライム・ビデオ

  • コマ送りやすぐ止まり動かない
  • アンインストール、chromeで再生

TVer

  • 動かない
  • アンインストール、chromeで再生

動画関連はChromeで動かすのが間違いないのかも

デュアルディスプレイにしながらTVerを見ながらブラウザ開いて作業していたら後半フリーズ コマ送りになりながらもアプリ全部終了同時作業はきびしいかも

Ubuntu Serverにfirefox headless

Headless

wget https://github.com/mozilla/geckodriver/releases/download/v0.23.0/geckodriver-v0.23.0-linux64.tar.gz
tar -zxvf geckodriver-v0.23.0-linux64.tar.gz 

sudo chmod +x geckodriver
sudo mv geckodriver /usr/local/bin

sudo apt install firefox
sudo apt install python3-pip
pip3 install selenium --user
sudo apt install xvfb
/usr/bin/Xvfb :99 -ac -screen 0 1024x768x8 & export DISPLAY=":99"
# sudo apt install libpangocairo-1.0-0 libx11-xcb1 libxcomposite1 libxcursor1 libxdamage1 libxi6 libxtst6 libnss3 libcups2 libxss1 libxrandr2 libgconf2-4 libasound2 libatk1.0-0 libgtk-3-0
from selenium import webdriver
#from selenium.webdriver.firefox.options import Options

#options = Options()
#options.headless = True
#driver = webdriver.Firefox(options=options)

driver = webdriver.Firefox()

driver.get('http://www.yahoo.co.jp')

# ブラウザ操作
driver.save_screenshot("ss.png")

driver.quit()

pandasで2018年の投手貢献度を計算

qiita.com

pandasで計算

import pandas as pd

url = 'https://baseball-data.com/stats/pitcher-all/era-1.html'
dfs = pd.read_html(url, index_col=0)

league = pd.DataFrame({
    'チーム': [
        '広島', '阪神', 'DeNA', '巨人', '中日', 'ヤクルト', 'ソフトバンク', '西武', '楽天', 'オリックス',
        '日本ハム', 'ロッテ'
    ],
    'リーグ': [
        'セントラル', 'セントラル', 'セントラル', 'セントラル', 'セントラル', 'セントラル', 'パシフィック',
        'パシフィック', 'パシフィック', 'パシフィック', 'パシフィック', 'パシフィック'
    ]
})
league

df = pd.merge(dfs[0], league, on='チーム')
df

# 列名を置換
df.rename(
    columns={
        'セlブ': 'セーブ',
        'ホlルド': 'ホールド'
    }, inplace=True)
df

# 小松式ドネーション計算
df['KD'] = ((df['投球回'] * 3) + (df['勝利'] + df['セーブ'] + df['ホールド']) * 10) * 1000

# セ・リーグ抽出
se_league = df[df['リーグ'] == 'セントラル'].copy()

# パ・リーグ抽出
pa_league = df[df['リーグ'] == 'パシフィック'].copy()

# チーム別集計
pv = df.pivot_table(values='KD', index='チーム', aggfunc=sum, fill_value=0)
pv['順位'] = pv['KD'].rank(ascending=False, method='min')
pv.sort_values('順位', inplace=True)

team_rank = pv.reset_index().set_index('順位')
team_rank

# ランキング
df['順位'] = df['KD'].rank(ascending=False, method='min')
df.sort_values('順位', inplace=True)
df.set_index('順位', inplace=True)
df[df.index < 21]

# セ・リーグ
se_league['順位'] = se_league['KD'].rank(ascending=False, method='min')
se_league.sort_values('順位', inplace=True)
se_league.set_index('順位', inplace=True)
se_league[se_league.index < 11]

# パ・リーグ
pa_league['順位'] = pa_league['KD'].rank(ascending=False, method='min')
pa_league.sort_values('順位', inplace=True)
pa_league.set_index('順位', inplace=True)
pa_league[pa_league.index < 11]

Pythonスクレイピングのフローチャート

  • requests-htmlを使えば複雑な操作以外はスクレイピング可能
  • タグが閉じていない場合はrequests-htmlだとスクレイピングできない。
  • 上記の場合はbeautifulsoupでパーサーをhtml5libにしておくとタグ補完してくれるので可能
  • pyppetterの代わりにseleniumでもよい。
  • seleniumはブラウザ操作のみのためスクレイピングはbeautifulsoupでする。

f:id:imabari_ehime:20181217163545p:plain

@startuml
start

:requests-html;
:ページ表示;

if (タグが見つからない) then (yes)
  :JavaScript;

  if (操作が必要) then (yes)
    :pyppetter;
    :操作;
  else(no)
    :requests-html;
    :レンダリング;
  endif
else(no)
:requests-html;
endif
:HTML表示;
:スクレイピング;
if (タグ抽出がシンプル) then (yes)
  if (操作が必要) then (yes)
    :pyppetter;
  else(no)
    :requests-html;
  endif
else(no)
  :beautifulsoup;
endif
:抽出;
end
@enduml

slenium・pypetterで全体のスクリーンショットを保存

blog.amedama.jp

Selenium

from selenium import webdriver

options = webdriver.ChromeOptions()
options.headless = True
driver = webdriver.Chrome(chrome_options=options)

url = 'https://www.amazon.co.jp/'

driver.get(url)

w = driver.execute_script('return document.body.scrollWidth')
h = driver.execute_script('return document.body.scrollHeight')
driver.set_window_size(w, h)

driver.save_screenshot("ss{}.png".format(i))

driver.quit()

Pyppetter

import asyncio
from pyppeteer import launch


async def main():
    browser = await launch()
    page = await browser.newPage()
    await page.goto('https://www.amazon.co.jp/')
    await page.screenshot({'path': 'example.png', 'fullPage': True})
    await browser.close()


asyncio.get_event_loop().run_until_complete(main())