”http://~/1”,” http://~/2”・・・と連番になっているサイトから画像をダウンロードするのに有効なツール,というかスクリプトです.個人的に使ってます.
スクリプトをいじってくれれば,応用できるかと思いますね.
まぁ,簡単なスクリプトの説明としては,wxPythonがGUIの役割をし,requestでサイトにアクセス,BeautifulSoupで画像データを取得という感じです.
追記:相対パスのトコでも取れるように改良しました.通常のサイトがターゲットの場合,ページ数は入れなくていいです.でも,取って来れない画像もいくつかあります...サイトの背景になってるものはとれないかもしれません
#-*- coding: utf-8 -*- import requests,os,sys,re from bs4 import BeautifulSoup # htmlを読み込むためBeautifulSoupをインポート from time import sleep import wx import ctypes # 保存先フォルダを選択 def folda_c(event): global folder_path # フォルダ選択ダイアログを作成 folder = wx.DirDialog(None,style=wx.DD_CHANGE_DIR | wx.OK | wx.STAY_ON_TOP,message="保存先フォルダ") # フォルダが選択されたとき if folder.ShowModal() == wx.ID_OK: folder_path = folder.GetPath() folder.Destroy() choose_text.SetLabel(folder_path) # request.get,proxyあり・なしをまとめたもの def req_get(url): proxy=edit_proxy.GetValue() if len(proxy)>4: # proxyがある場合(Noneと文字が入っていなければ?) #proxy=re.sub(r"(http:)|(https:)","",proxy) proxy_dict={"http":proxy,"https":proxy} return requests.get(url,allow_redirects=False,proxies=proxy_dict) else: # 普通にrequests.get()する return requests.get(url,allow_redirects=False) # 文字をウィンドウに表示 def now_status(text): # ステータスバーに文字列を表示させる frame.SetStatusText(text) # フォルダを作成 def folda_m(tpath): # フォルダがカレントディレクトリにない場合に作成する try: os.mkdir(tpath) # 画像ファイルを入れるフォルダを作成 print("フォルダを作成しました.") except FileExistsError: # 画像ファイルが既に作成されている場合 if len(os.listdir(tpath)) > 0: # フォルダ内のファイルをすべて削除 for file in os.listdir(tpath): os.remove(tpath+"/"+file) else: pass except OSError: return False print("フォルダは既に作成されていました.") # 画像のリンク先を取得し,指定のフォルダで画像ファイルを作成する関数 def img(data,tpath,p): global count # global宣言すれば代入可能 soup = BeautifulSoup(data.content,'html.parser') # bsでURL内を解析 sleep(0.5) print(p) # 確認用 for link in soup.find_all("img"): # imgタグを取得しlinkに格納 # 相対パスの場合は省略する check=link.get("src") if re.search(r'https*',check)==None: print('相対パス') head=soup.find("head").link.get("href")+'/' print(head+link.get("src")) if link.get("src").endswith(".jpg"): # imgタグ内の.jpgであるsrcタグを取得 try: res = req_get(head+link.get("src")) except ConnectionError: print('ConnectionError') return True try: with open(tpath + '/' + link.get("src").split('/')[-1], 'wb') as f: f.write(res.content) except FileNotFoundError: print('FileNotFoundError') return True elif link.get("src").endswith(".png"): # imgタグ内の.pngであるsrcタグを取得 try: res = req_get(head+link.get("src")) except ConnectionError: print('ConnectionError') return True try: with open(tpath + '/' + link.get("src").split('/')[-1], 'wb') as f: f.write(res.content) except FileNotFoundError: print('FileNotFoundError') return True elif link.get("src").endswith(".gif"): # imgタグ内の.gifであるsrcタグを取得 try: res = req_get(head+link.get("src")) except ConnectionError: print('ConnectionError') return True try: with open(tpath + '/' + link.get("src").split('/')[-1], 'wb') as f: f.write(res.content) except FileNotFoundError: print('FileNotFoundError') return True elif link.get("src").endswith(".svg"): # imgタグ内の.svgであるsrcタグを取得 try: res = req_get(head+link.get("src")) except ConnectionError: print('ConnectionError') return True try: with open(tpath + '/' + link.get("src").split('/')[-1], 'wb') as f: f.write(res.content) except FileNotFoundError: print('FileNotFoundError') return True sleep(0.1) continue else: pass if p==True: # 連番サイトのとき if link.get("src").endswith("top.jpg"): continue elif link.get("src").endswith(".jpg"): # imgタグ内の.jpgであるsrcタグを取得 try: res = req_get(link.get("src")) except ConnectionError: print('ConnectionError') return True try: with open(tpath + '/' + 'no' + str(count) +'.jpg', 'wb') as f: f.write(res.content) except FileNotFoundError: print('FileNotFoundError') return True count=count+1 elif link.get("src").endswith(".png"): # imgタグ内の.pngであるsrcタグを取得 try: res = req_get(link.get("src")) except ConnectionError: print('ConnectionError') return True try: with open(tpath + '/' + 'no' + str(count) +'.png', 'wb') as f: f.write(res.content) except FileNotFoundError: print('FileNotFoundError') return True count=count+1 else: # 上記以外(つまり通常時) if link.get("src").endswith(".jpg"): # imgタグ内の.jpgであるsrcタグを取得 try: res = req_get(link.get("src")) except ConnectionError: print('ConnectionError') return True try: with open(tpath + '/' + link.get("src").split('/')[-1], 'wb') as f: f.write(res.content) except FileNotFoundError: print('FileNotFoundError') return True elif link.get("src").endswith(".png"): # imgタグ内の.pngであるsrcタグを取得 try: res = req_get(link.get("src")) except ConnectionError: print('ConnectionError') return True try: with open(tpath + '/' + link.get("src").split('/')[-1], 'wb') as f: f.write(res.content) except FileNotFoundError: print('FileNotFoundError') return True elif link.get("src").endswith(".gif"): # imgタグ内の.gifであるsrcタグを取得 try: res = req_get(head+link.get("src")) except ConnectionError: print('ConnectionError') return True try: with open(tpath + '/' + link.get("src").split('/')[-1], 'wb') as f: f.write(res.content) except FileNotFoundError: print('FileNotFoundError') return True elif link.get("src").endswith(".svg"): # imgタグ内の.svgであるsrcタグを取得 try: res = req_get(head+link.get("src")) except ConnectionError: print('ConnectionError') return True try: with open(tpath + '/' + link.get("src").split('/')[-1], 'wb') as f: f.write(res.content) except FileNotFoundError: print('FileNotFoundError') return True # 実際に画像をダウンロードした時の名前をそのURLのHTMLで検索をかけると,見つかるよ! # Webサイトで右クリック→「ソースの表示」を選択すると,HTML形式で見ることができ,検索とかできる if link.get("data-src") != None: if link.get("data-src").endswith(".jpg"): # imgタグ内の.jpgであるsrcタグを取得 try: res = req_get(link.get("data-src")) except ConnectionError: print('ConnectionError') return True try: with open(tpath + '/' + link.get("data-src").split('/')[-1], 'wb') as f: f.write(res.content) except FileNotFoundError: print('FileNotFoundError') return True elif link.get("data-src").endswith(".png"): # imgタグ内の.pngであるsrcタグを取得 try: res = req_get(link.get("data-src")) except ConnectionError: print('ConnectionError') return True try: with open(tpath + '/' + link.get("data-src").split('/')[-1], 'wb') as f: f.write(res.content) except FileNotFoundError: print('FileNotFoundError') return True sleep(0.5) # 画像ダウンロード・保存処理をまとめた関数 def scrape_save(URL1): global num # プログレスバーを作成 db=wx.ProgressDialog('作成中',"{0:05.1f}%完了".format(0),100,style= wx.PD_ELAPSED_TIME) db.ShowModal() # タイトルを自動取得 d=req_get(URL1) soup = BeautifulSoup(d.content,'html.parser') t1=soup.title.string if re.search(r'所望の連番サイトを書いてください',URL1)!=None: pic=True t2=t1.split('] ') t3=t2[1] title=re.sub(r'( | )*\[[0-9]+P','',t3) title=re.sub(r'\[.+','',title) title=re.sub(r' | ','',title) else: pic=False title=t1 title=re.sub(r' | ','',title) print(pic) # 確認用 # 保存先のパス作成 folder_path a='/' b='\\' # Windowsの場合 fpath=folder_path.replace(b, a) tpath=fpath+'/'+title if folda_m(tpath) == False: tpath=fpath+'/'+'nonetitle' folda_m(tpath) data1 = req_get(URL1) if img(data1,tpath,pic): print('エラーが起きたのでやり直します') wx.MessageBox('エラーが起きたのでやり直します','エラー',wx.STAY_ON_TOP) return True result="{0:5.1f}%完了".format(1*100/page_all) print(result) db.Update(1*100/page_all,result) while True: if pic==False: break URL=URL1 + "/" +str(num)+ "/" data = req_get(URL) if (int(data.status_code) >= 500): sleep(60) continue if (int(data.status_code) >= 300): # status_codeをチェックすることで、HTTPステータスコードを確認できる. # 300以上ならリンク先が見つからなかったとして,ループを抜ける. break if img(data,tpath,pic): print('エラーが起きたのでやり直します') wx.MessageBox('エラーが起きたのでやり直します','エラー',wx.STAY_ON_TOP) continue result="{0:5.1f}%完了".format(num*100/page_all) print(result) # 確認用 db.Update(num*100/page_all,result) num=num+1 res="「"+title+"」の作成完了" print(res) # プログラムの終了確認 # スタンバイへの移行抑止を解除する ctypes.windll.kernel32.SetThreadExecutionState( ES_CONTINUOUS) db.Destroy() dial = wx.MessageDialog(None,"作成したファルダを確認するには「OK」を,\nしないで終了する場合は「キャンセル」をクリックしてください", res , wx.OK | wx.CANCEL ) dial_bt=dial.ShowModal() if dial_bt==wx.ID_OK: dial.Destroy() a='/' b='\\' # Windowsの場合 path=tpath.replace(a, b) os.popen('explorer "%s" ' % path) elif dial_bt==wx.ID_CANCEL: dial.Destroy() # ステータスバーに文字列を表示させる frame.SetStatusText(res) return False def spinbutton_value_change(event): obj = event.GetEventObject() global page_all page_all=int(obj.GetValue()) global input_page input_page.SetValue(str(page_all)) # 本プログラムの処理まとめ def pros(event): if folder_path=="保存先が選択されていません.ボタンをクリックして保存先を選択してください.": wx.MessageBox('保存先が選択されていません.選択してから実行してください.','エラー',wx.STAY_ON_TOP) return else: pass # スタンバイモードへの移行抑制 ctypes.windll.kernel32.SetThreadExecutionState(ES_SYSTEM_REQUIRED | ES_CONTINUOUS) # ボタンが押せない状態(無効) button.Disable() choose_button.Disable() editbox.Disable() edit_proxy.Disable() try: URL1 = editbox.GetValue() global count count=1 # グローバル変数 global num num=2 # ループのカウント(2番目から) while scrape_save(URL1): continue # 既存のテキスト値を全て消去 editbox.Clear() # 何も入力されてなかったり,無効なURLだった時,処理を行わずやり直す except requests.exceptions.MissingSchema: wx.MessageBox('何も入力されてなかったり,無効なURLだったので,再入力してください.','エラー',wx.STAY_ON_TOP) except ConnectionResetError: wx.MessageBox('ConnectionResetErrorが発生しました.やり直してください.','エラー',wx.STAY_ON_TOP) except requests.exceptions.ConnectionError as rc: print(str(rc)) now_status('Error') finally: # ボタンが押せる状態(有効) button.Enable() choose_button.Enable() editbox.Enable() edit_proxy.Enable() # プログラム本体 # 値の初期化(グローバル変数) ES_CONTINUOUS = 0x80000000 ES_AWAYMODE_REQUIRED = 0x00000040 ES_SYSTEM_REQUIRED = 0x00000001 ES_DISPLAY_REQUIRED = 0x00000002 count=0 num=0 folder_path="保存先が選択されていません.ボタンをクリックして保存先を選択してください." page_all=1 # アプリケーションのオプジェクトを生成 app=wx.App() # 重要なコンテナウィジェット,ウィジェットの階層で頂点 # 第一引数:親ウィンドウ(Noneで持たないことを示す),第二引数:識別子(基本-1) # 第三引数:タイトルとして表示する文字列 # posには表示位置,sizeにはサイズを指定できる←(300,300)というように指定 frame=wx.Frame(None, id=wx.ID_ANY, title='img_downloader(Windows)',size=(640,415)) # ステータスバーを使用する frame.CreateStatusBar() # ボタンなどを配置する(直接Frameに張り付けられるが)のに使用 panel1=wx.Panel(frame,wx.ID_ANY,pos=(0,0),size=(640,100)) panel2=wx.Panel(frame,wx.ID_ANY,pos=(0,100),size=(640,20)) panel3=wx.Panel(frame,wx.ID_ANY,pos=(0,120),size=(640,30)) panel4=wx.Panel(frame,wx.ID_ANY,pos=(0,150),size=(640,20)) panel5=wx.Panel(frame,wx.ID_ANY,pos=(0,170),size=(640,30)) panel6=wx.Panel(frame,wx.ID_ANY,pos=(0,200),size=(640,20)) panel7=wx.Panel(frame,wx.ID_ANY,pos=(0,220),size=(640,30)) panel8=wx.Panel(frame,wx.ID_ANY,pos=(0,250),size=(640,20)) panel9=wx.Panel(frame,wx.ID_ANY,pos=(0,270),size=(640,30)) panel10=wx.Panel(frame,wx.ID_ANY,pos=(0,300),size=(640,25)) panel11=wx.Panel(frame,wx.ID_ANY,pos=(0,325),size=(640,50)) # 文字列の表示→説明文を表示する text=""" URLを入力して,そのURLのサイトからそのサイトにある全てのJPEG・PNG画像を自動でダウンロードします.\n 以下にURLを入力して,実行ボタンをクリックすると,ダウンロードが始まります.\n proxyが設定してある場合は,proxyのURLを入力してください.\n ※実行中はスリープモードを抑制します. """ experiment=wx.StaticText(panel1,wx.ID_ANY,text,style=wx.TE_CENTER,size=(640,100)) # CENTERで中央寄せ # URLを入力 ex1=wx.StaticText(panel2,wx.ID_ANY,"URLを入力してください:",style=wx.TE_CENTER,size=(640,20)) # tkinterでいうEntryウィジェットの作成 editbox=wx.TextCtrl(panel3,id=wx.ID_ANY,size=(640,25)) # proxyを入力 ex2=wx.StaticText(panel4,wx.ID_ANY,"proxyが設定されている場合は入力してください:",style=wx.TE_CENTER,size=(640,20)) edit_proxy=wx.TextCtrl(panel5,id=wx.ID_ANY,size=(640,25)) # page数を入力 ex3=wx.StaticText(panel6,wx.ID_ANY,"ページ数を入力してください:",style=wx.TE_CENTER,size=(640,20)) input_page=wx.TextCtrl(panel7,id=wx.ID_ANY,size=(640,25)) input_page.Disable() input_page.SetValue(str(page_all)) spin_button = wx.SpinButton(panel8, style=wx.SP_HORIZONTAL,size=(640,20)) spin_button.Bind(wx.EVT_SPIN, spinbutton_value_change) # 保存先を選択 choose_text = wx.StaticText(panel9, wx.ID_ANY, folder_path) choose_button = wx.Button(panel10, wx.ID_ANY, "フォルダの選択",size=(100,25)) choose_button.Bind(wx.EVT_BUTTON,folda_c) # tkinterでいうButtonウィジェットの作成 button=wx.Button(panel11,id=wx.ID_ANY,label='実行する',size=(100,25)) # wx.EVT_BUTTON(ボタンがクリックされた)ときに実行する関数を第二引数に指定 button.Bind(wx.EVT_BUTTON,pros) # ツールチップ設定 #button.SetToolTip('クリックして実行') # Show() メソッドを呼び出してスクリーンに表示←tkinterのpack()やgrid() frame.Show() # イベント待ち状態へ遷移←tkinterのmainloop() app.MainLoop()
参考サイト
他に参考にしたサイトの”https://qiita.com/kirsch874/items/8709b89cf0fe225a57c1”は今はないかもしれないです...