0
3

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 1 year has passed since last update.

【アマゾンで安価更新されたらLINEに送信】をできなかった話

Last updated at Posted at 2023-07-04

アマゾンンの価格SearchをしてどうせならLINEでおくる

アマゾンで安価更新されたらをLINEに送信しようとしたらAmazonでスクレイピングは禁止されていた。

結論 スクレイピングでしようとしては駄目。禁止されていたのでAPIを使おう。


スクレイピングが禁止されているかどうかはrobot.txtが用意されているで確認します。

Amazon
https://www.amazon.co.jp/robots.txt


今回はスクレイピングをしたいと思っていたので日経平均株価に代替えする。

日経平均は下記で確認してスクレイピングをしても大丈夫とのこと確認
https://www.nikkei.com/robots.txt


補足
「User-agent」の部分は許可するユーザーを表しています。
表示されている「*」は全てのユーザーを許可するという意味です。
「Allow」と「Disallow」で判別。
「Allow」はスクレイピングを許可するという意味。
「Disallow」はスクレイピングを許可しないという意味。

修正、日経平均で安価更新されたらLINEに送信

必要ライブラリ
import requests
from bs4 import BeautifulSoup

持ってない人は

terminal
pip install beautifulsoup4

持っているかどうかの確認

terminal
pip freeze

日経新聞のほしい情報を検索

日経平均が****円になった時にLineで通知を送るようにしたい。(既存のアプリがありそう)

"https://www.nikkei.com/markets/kabu/"

※日本語は勝手に置き換わる

Nikkei.py
import requests
from bs4 import BeautifulSoup

url = "https://www.nikkei.com/markets/kabu/"

def NikkeiPrice():
    
# URLにアクセスする 戻り値にはアクセスした結果やHTMLなどが入ったNikkeiPageが帰ってきます
    NikkeiPage = requests.get(url)

    # NikkeiPageからHTMLを取り出して、BeautifulSoupで扱えるようにパースします
    soup = BeautifulSoup(NikkeiPage, "html.parser")
    
    # <h2 class="m-headline_text">日経平均株価<span class="cmn-notes">(4日、大引、円)</span></h2>
    title = soup.find("h2",class_= "m-headline_text").get_text()    
    print(title)
    # <span class="mkc-stock_prices">33,422.52</span>
    price = soup.find("span",class_="mkc-stock_prices").get_text()
    print(price)
    

NikkeiPrice()

def NikkeiPrice():
//こいつに収納

soup = BeautifulSoup(NikkeiPage,"html.parser")
//URLの全ページをとってくる。HTMLを取り出して、BeautifulSoupで使えるようにしている。

開発ツールをひらいて欲しい情報を探すと下記が書かれている。
※Google chromeで開発ツールを開いて左上の矢印がかかれた絵をタッチして必要な情報を探す。
"h2 class="m-headline_text">日経平均株価(4日、大引、円)/h2"


情報の取得方法1
title = soup.find("h2",class_= "m-headline_text").get_text() ※classの後の_に注意する

情報の取得方法2
title = soup.select_one("#CONTENTS_MARROW > div.mk-top_stock_average.cmn-clearfix > div.m-headline > h2").get_text())

CSSセレクターを使って指定した場所のテキストを右クリックしてCopy→CopySelectorを選択しselect_one以下に張り付ける。※なおfirefoxなどではCSSセレクターはない。

情報の取得方法3
今回のページにはなかったがidの表記があればこちらを使用するのが一番手っ取り早い
title = soup.find(id="*****").get_text())


.textがないとテキスト化されないので注意

実行:戻り値にNikkeiPrice()がないとただObjectを作っただけになる。

soup = BeautifulSoup(NikkeiPage.content, "html.parser")にcontentがないと
TypeError: object of type 'Response' has no len()


補足

urlopen関数とは:
Pythonのurllibモジュールで使われるURLを取得するためのメソッド。urllibはURLを使用するためのモジュールでその中にurlopen関数が含まれている。

単純にrequests.get(URL)でもかまわない(import request)

select()はfind()などでも応用可能だが前者のほうが応用が利くような気がする

タイプ すべての要素をリストで返す ひとつだけ要素を返す 引数(検索条件の指定)
find系 find_all() find() 要素名, 属性指定(キーワード引数)
select系 select() select_one() CSSセレクタ

パーサーにも種類がいくつかあるので他で代用可能
html.parser
利点:バッテリーが含まれている、まともな速度、寛大(Python 2.7.3および3.2以降)。
短所:それほど寛大ではない(Python 2.7.3または3.2.2より前)

lxml(import必要)pip3 install lxml
利点:非常に高速、寛大
短所:外部C依存

html5lib(import必要)pip install html5lib
利点:非常に寛大で、Webブラウザーと同じようにページを解析し、有効なHTML5を作成します
短所:非常に遅い、外部Python依存関係


requests.get(url)の代わりにurllib.request.urlopen(url)を使用してもいいがrequestsはより使いやすく、高レベル


補足2
同一のclassがあり二つ以上の値を取得してしまった時の対処法
例えば¥3640¥3640
converterdPrice = price[1:5]で指定してやると6つ目以降がなくなる。


カンマを取り除く

数値を比較するうえでカンマ(,)は不要なので取り除く。またString型の可能性があるのでfloat型(小数点なのでInt型は駄目)に訂正
ConvertedPrice = price.replace(",","")
floatPrice = float(ConvertedPrice)

なお"."と","の両方とも消したい場合

import re
ConvertedPrice = re.sub("[,.]","",price)

Lineに送信する処理をつくる

Lineと連携するので下記サイトにアクセス右上のマイページにアクセスしアクセストークンを発行し下記のように記載

 if(floatPrice > 3000):
        sendLineNotify()


def sendLineNotify():
    print("lineに通知がいきました")
    lineNotifyToken = "あなたのLineNotifyトークン"
    lineNotifyApi = "https://notify-api.line.me/api/notify"
    headers = {"Authorization": f"Bearer {lineNotifyToken}"}
    data = {"message": "今がお買い時です!https://www.nikkei.com/markets/kabu/"}
    requests.post(lineNotifyApi, headers=headers, data=data)

最後にsleep関数で自動処理を組み込む。下記は一時間ごとにトラッキング(検索サーチ、Pythonの実行)している。NikkeiPrice()の実行をwhile(True):の下層におく

import time

while(True):
    print("トラッキングしました")
    time.sleep(60 * 60)
    NikkeiPrice()

最終的な記述は下記になる。floatPrice > 3000は実用化するならfloatPrice < 3000に変更
Lineのトークンは作るシステム毎に発行する。

Nikkei.py
# coding: UTF-8
from bs4 import BeautifulSoup
import requests
import time

# アクセスするURL

url = "https://www.nikkei.com/markets/kabu/"

def NikkeiPrice():
    
# URLにアクセスする 戻り値にはアクセスした結果やHTMLなどが入ったNikkeiPageが帰ってきます
    NikkeiPage = requests.get(url)

    # NikkeiPageからHTMLを取り出して、BeautifulSoupで扱えるようにパースします
    soup = BeautifulSoup(NikkeiPage.content, "html.parser")
    
    # <h2 class="m-headline_text">日経平均株価<span class="cmn-notes">(4日、大引、円)</span></h2>
    title = soup.find("h2",class_= "m-headline_text").get_text()    
    print(title)
    # <span class="mkc-stock_prices">33,422.52</span>
    price = soup.find("span",class_="mkc-stock_prices").get_text()
    print(price)
    ConvertedPrice = price.replace(",","")
    # print(ConvertedPrice)
    
    floatPrice = float(ConvertedPrice)
    print(floatPrice)
    
    
    if(floatPrice > 3000):
        sendLineNotify()


def sendLineNotify():
    print("lineに通知がいきました")
    lineNotifyToken = "Zcccv5BLFd61X8p6ScmczmJgwc6YhZt9T4dMj"//Tokenは適当です
    lineNotifyApi = "https://notify-api.line.me/api/notify"
    headers = {"Authorization": f"Bearer {lineNotifyToken}"}
    data = {"message": "今がお買い時ですhttps://www.nikkei.com/markets/kabu/"}
    requests.post(lineNotifyApi, headers=headers, data=data)


while(True):
    print("トラッキングしました")
    time.sleep(10)
    NikkeiPrice()

     
# NikkeiPrice()

Amazonのスクレイピングをやりたい方へ
下記で値は取れるらしいが何度も言うように違法だ。また取得するといっても
python amazon-search.pyを実行すると
最初:Learning Python: Powerful Object-Oriented Programming (English Edition)
次:入門 Python 3 第2版
最終的に:"None"をループするらしい。

from urllib.request import Request, urlopen
from bs4 import BeautifulSoup



amazonURL = "https://www.amazon.co.jp/s?k=python+%E3%82%AA%E3%83%A9%E3%82%A4%E3%83%AA%E3%83%BC&__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=34KC426KLCM3U&sprefix=python+%E3%82%AA%E3%83%A9%E3%82%A4%E3%83%AA%E3%83%BC%2Caps%2C217&ref=nb_sb_noss_1"
hdr = {
    'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11',
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
    'Accept-Charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.3',
    'Accept-Encoding': 'none',
    'Accept-Language': 'ja-JP,en-US;q=0.7,en-GB;q=0.3',
    'Connection': 'keep-alive'}

def amazonTrackingPrice():
    amazonPage = urlopen(Request(amazonURL,headers=hdr))
    soup = BeautifulSoup(amazonPage,"lxml")
    # print(soup)
    
    title = soup.select_one("#search > div.s-desktop-width-max.s-desktop-content.s-wide-grid-style-t1.s-opposite-dir.s-wide-grid-style.sg-row > div.sg-col-20-of-24.s-matching-dir.sg-col-16-of-20.sg-col.sg-col-8-of-12.sg-col-12-of-16 > div > span.rush-component.s-latency-cf-section > div.s-main-slot.s-result-list.s-search-results.sg-row > div:nth-child(6) > div > div > div > div > div.a-section.a-spacing-small.puis-padding-left-small.puis-padding-right-small > div.a-section.a-spacing-none.a-spacing-top-small.s-title-instructions-style > h2 > a > span").get_text()
    
    print(title)
    
    
    
amazonTrackingPrice()

hdrなどいらなさそうな要素を付与しているが、アマゾンでその情報をいれないとはじかれる。

0
3
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
0
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?