BeautifulSoup」タグアーカイブ

python スクレイピング、BeautifulSoupライブラリ

#株探先物オプションのスクレイピング。取得した文字列をコピペしてTEXTにして、
#CSVに出力してMysqlにインサートするコード
#URLと日付と月限は手動で毎回入力する必要がある。

#以前はファイル作成まで手動で作業していた。
#WEBページを開き
#先物オプションの出来高データを取得して
#テキストファイルにする
#所定のフォルダにコピー、移動する
#個人用クラスメソッドを使う。

いままでWebdriverライブラリを使用していたが、空白部分が自動で削除されてしまった。
削除してほしくなかったので、BeautifulSoupライブラリを使用した。こちらのほうはクロムは起動しないし純粋にhtmlの文字を空白を含めて取得してくれた。
以下は今回作ったコードの一部。class cGetOption()
なおdef returnDriver(self,lurl)はwebdriverを使用したもので実際には採用しなかった。
株探の先物オプションのURLを取得して
そのページの文字列を取得。このとき、ある文字列Aと文字列Bの間の文字を取得(findFirstStrのところ)
そしてタプルで、文字列とファイル名文字列を出力する

https://github.com/maseda1030/yahoofinance_python.git

import MySQLdb
import os
import re
import sys
import time
import datetime
import glob#ファイル一覧
import shutil#move
from selenium import webdriver
import importlib#再読み込みのためのライブラリ

import requests#スクレイピング
from bs4 import BeautifulSoup#スクレイピング

import methodMysql#個人用メソッド pyファイル

###START
importlib.reload(methodMysql)

##以下は毎回手動で確認すること
#株探の市況の先物オプション、市場が開いている当日のPM4:06分頃と、翌日の朝AM6:30以降に更新される。
#土日祝は更新されないが、前日が市場が開いていると更新される。
optionUrl='https://kabutan.jp/news/marketnews/?b=n202103010692'#都度修正、毎日
useDate='2021/3/1'#オプション取り込みの日付               #都度修正、毎日
useMonth=3#月限 12月の作業はたいてい翌月である1月            #都度修正、月
useTable='Table_StockOption'#テーブルは固定

#
print('START')
print('chrome起動')
obj=methodMysql.cGetOption()
#このURLは手動でコピペする
#BeautifulSoup版
tupleArray=obj.getOptionDataByBeautifulSoup(optionUrl)

#webdriver版
#tupleArray=obj.getOptionData(optionUrl)
a,b=tupleArray
print(a)#text
print(b)#年月日時分


path='/Users/toshiromaseda/Documents/2020年株関連/kabu_python/'
obj.outputText(path,tupleArray)
#file名は、年月日時分.txtになって保存される。

#ファイルの存在チェックで拡張子をつけてチェックする
if b.find('.txt')>=0:
    pass
else:
    ifile=b+'.txt'

##--
checkFlag='nashi'
files=glob.glob(path+'*.txt')
for file in files:
    if ifile in file:#ファイル名を含んでいればTRUE
        print(file)
        checkFlag='ari'
        break
    else:
        #print(file)
        checkFlag='nashi'
if checkFlag=='nashi':
    print('ファイルが存在しないか、ファイル名が間違っています')
    sys.exit()

        
csvfile='c_'+ifile.split('.')[0]+'.csv'

methodMysql.checkFile(ifile)#check 取り込み済みのファイルかどうかを調べる

try:
    ofile=open(csvfile,'tw') 
except FileNotFoundError as e: # FileNotFoundErrorは例外クラス名
   print("ファイルが見つかりません", e)
   #print("強制終了")
   sys._exit()#ファイルがなければ終了#tryのときは_exit()が良いらしい
except Exception as e: # Exceptionは、それ以外の例外が発生した場合
   print(e)

try:#ファイルが存在しないときのエラー処理try
    with open(ifile,'tr') as fin:
        for iline in fin:
            #ilineに、”コール”、”出来高”の文字がある行は無視するようにする
            #countで探すか 1行目、2行目は不要なのでDBにインサートしないための処理
            if iline.count('コール')>=1 or iline.count('出来高')>=1:
                continue#以下は実行されない
            if len(iline)==1:#1文字は改行コードだろうから何もしない
                continue
            try:
                ofile.write(methodMysql.outMojiMKIII(iline)+'\n')#MKIII改良版2020/12/18
                #次はMysqlに直接インサートするバージョンを作業する
            except Exception:
                print("do not")
        ofile.close()
except FileNotFoundError as e: # FileNotFoundErrorは例外クラス名
    print("ファイルが見つかりません。パス、ファイル名を確認してください", e)
    ofile.close()
    print("強制終了")
    sys._exit()#ファイルがなければ終了 #tryのときは_exit()が良いらしい
except Exception as e: # Exceptionは、それ以外の例外が発生した場合
   print(e)

#CSVからMysqlへ CSVファイルがないと実行できない。重複チェックなし
#csvToMysql(difileはCSVファイル名,dtablename、doptionDate日付、dmonth月限)
#テスト用テーブルTest_Table_StockOption
print("csvtoMysql")
methodMysql.csvToMysql(csvfile,useTable,useDate,useMonth)

#Testが終わったら試す。 単独実行可能 但し、ファイルの移動先チェックがないので、他で移動がないことをチェックする必要あり
methodMysql.fileMove(ifile,'./option_python_execute')
methodMysql.fileMove(csvfile,'./option_python_execute')

#表、グラフを出力する 単独実行可能
##methodMysql.selectMysql('Table_StockOption')

print("終わりました。")
print('+++++++')
print('chrome終了')
print('END')


'''
mysql> mysql> SELECT SUM(Volume1) as callVolume1, ExercisePrice,  SUM(Volume2) as putVolume2 
FROM Table_StockOption WHERE Month=3 GROUP BY ExercisePrice ORDER BY Exerce Desc;
'''

 

#先物オプションテキストコピペ 2021/02/28
class cGetOption():
    def __init__(self):
        pass

    def returnDriver(self,lurl):
        # 仮想ブラウザ起動、URL先のサイトにアクセス
        driver = webdriver.Chrome('/usr/local/bin/chromedriver')#ここでエラーになったらパスが違うかchromedriverをインストールする
        #他のエラーで、「unexpectedly exited. Status code was:-9」だったら、Macの場合はシステム環境設定 → セキュリティとプライバシー で許可すればよい
        url=lurl
        driver.get(url)
        mydriver=driver
        return mydriver
    #BeautifulSoup版はクロムは起動しない
    def getOptionDataByBeautifulSoup(self,lurl):#BeautifulSoup対応版、別途Importが必要、2021/03/01
        target_url = lurl
        r = requests.get(target_url)         #requestsを使って、webから取得
        soup = BeautifulSoup(r.text, 'lxml') #要素を抽出
        shijyounews=soup.find(id="shijyounews")#id
        article=shijyounews.find("article")#tag
        tagTime=article.find("time")#tag
        mono=article.find(class_="mono")#class

        print("BeautifulSoup")
        #print(mono.text)
        outputFileName=tagTime.text#年月日時分
        #ここに処理を入れる。
        #2021/03/01
        findFirstStr='コール      プット'#を探して
        findSecondStr='株探ニュース'#の前までを取得する
        findFirstPosition=mono.text.find(findFirstStr)
        findSecondPosition=mono.text.find(findSecondStr)
        if(findFirstPosition>=0 and findSecondPosition>=0):
            print('search success.')
            outputText=mono.text[findFirstPosition:findSecondPosition]
        else:
            print('先物オプションが見つかりませんでした。URLが正しいか確認してください。')
            sys.exit()       

        output=()#初期化
        output=(outputText,outputFileName)#タプルで出力する,この時点で拡張子.txtは付記していない。
        time.sleep(1)       
        return output

    #webdriver版は、クロムが起動する。こっちは文字の先頭に空白を自動で削除する。この処理がよいときもあるが、今回は空白が必要だったのでB4にした
    def getOptionData(self,lurl):
        driver=self.returnDriver(lurl)
        time.sleep(1)
        #tag,id,css
        main = driver.find_element_by_id("wrapper_main")
        container=main.find_element_by_id("container")
        container_main=container.find_element_by_id("main")
        shijyounews=container_main.find_element_by_id("shijyounews")
        article=shijyounews.find_element_by_tag_name("article")

        tagTime=article.find_element_by_tag_name("time")
        mono=article.find_element_by_class_name("mono")
        #brs=mono.find_elements_by_tag_name("br")
        print(tagTime.text)
        outputFileName=tagTime.text#年月日時分
        #tagTimePosition=tagTime.text.find('日')
        #print(tagTime.text[0:tagTimePosition+1])#年月日
        #print(mono.text)

        findFirstStr='コール      プット'#を探して
        findSecondStr='株探ニュース'#の前までを取得する
        findFirstPosition=mono.text.find(findFirstStr)
        findSecondPosition=mono.text.find(findSecondStr)
        if(findFirstPosition>=0 and findSecondPosition>=0):
            print('search success.')
            outputText=mono.text[findFirstPosition:findSecondPosition]
        else:
            print('先物オプションが見つかりませんでした。URLが正しいか確認してください。')
            sys.exit()
        output=()#初期化
        output=(outputText,outputFileName)#タプルで出力する,この時点で拡張子.txtは付記していない。
        time.sleep(1)
        driver.close()#起動したウィンドウを閉じる
        return output

    def outputText(self,path,tupleArray):#ここで受け取るタプルは2つ
        #getOptionData()からテキストとファイル名をタプルを受け取る
        outputText,filename = tupleArray
        if outputText=='' or filename=='' or path=='':
            print("パスかファイル名かテキストがありませんでした。filename,outputText")
            sys.exit()
        os.chdir(path)#ディレクトリ変更
        print(os.getcwd())#ディレクトリ確認
        if filename.find('.txt')>=0:
            pass
        else:
            filename+='.txt'
        try:
            ofile=open(filename,'tw') 
        except FileNotFoundError as e: # FileNotFoundErrorは例外クラス名
           print("ファイルが見つかりません", e)
           sys._exit()#ファイルがなければ終了#tryのときは_exit()が良いらしい
        except Exception as e: # Exceptionは、それ以外の例外が発生した場合
           print(e) 
        
        ofile.write(outputText)
        ofile.close()