前回の続きです。前回はYahoo画像検索を使いましたが、今回はGoogle画像検索を使います。Google先生は強敵です。
実際に検索をしてurlはhttps://www.google.co.jp/search?q=%E9%BD%8B%E8%97%A4%E9%A3%9B%E9%B3%A5&tbm=ischであることが判明。あとは
1 2 3 4 |
ChromeDriver driver = new ChromeDriver(); driver.Url = "https://www.google.co.jp/search?q=%E9%BD%8B%E8%97%A4%E9%A3%9B%E9%B3%A5&tbm=isch"; System.Threading.Thread.Sleep(3000); string html = driver.PageSource; |
これでHTMLを解析して前回同様にすれば・・・と思ったら
1 |
<img class="rg_i Q4LuWd" src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBxASEhUQDxIVFRUVFRUVFRYVEBUVFRUQFRUWFhUVFRUYHSggGBolHRUVITEhJSkrLi4uFx8zODMtNygtLisBCgoKDg0OFxAQGi0dHR0tLS0tLS0tLS0tLS0rLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLSsrLS0tLS0tK/ |
BASE64エンコードだ。
しかも
1 |
<img class="rg_i Q4LuWd" data-src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQPvWdrJOGUjTsu1O-KAKsejte7U4rhUCX9Bg&usqp=CAU" data-lt="" jsname="Q4LuWd" width="240" height="180" data-index="0" alt="乃木坂46 齋藤飛鳥の2/her 「プレッピー」をキーワードに着こなす2つのスタイル | FASHION | MEN'S NON-NO WEB | メンズノンノウェブ" src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQPvWdrJOGUjTsu1O-KAKsejte7U4rhUCX9Bg&usqp=CAU"></div><div class="c7cjWc"> |
urlタイプのものもあります。今回はちょっと面倒です。
Yahoo画像検索では画像は検索対象のものだけでしたが、Google画像検索では上のほうに別の検索ワードの画像も表示されます。目的の画像のimgタグは div#islrgタグの配下にあります。また「もっと見る」は
1 |
<input jsaction="Pmjnye" class="mye4qd" type="button" value="結果をもっと表示"> |
となっています。
以下のコードでimgタグのsrc属性を取得することができます。
NuGetでSelenium.WebDriverとSelenium.Support、そして操作したいブラウザのDriverをインストールします。今回はChromeを操作するのでSelenium.Chrome.WebDriverをインストールします。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
using OpenQA.Selenium; using OpenQA.Selenium.Chrome; public partial class Form1 : Form { private void button1_Click(object sender, EventArgs e) { ChromeDriver driver = new ChromeDriver(); driver.Url = "https://www.google.co.jp/search?q=%E9%BD%8B%E8%97%A4%E9%A3%9B%E9%B3%A5&tbm=isch"; // ページが読み込まれるのを待つ System.Threading.Thread.Sleep(3000); // Google画像検索は200件までしか表示されない List<string> srcs = GetImgSrcs(driver, 200); driver.Quit(); driver.Dispose(); } List<string> GetImgSrcs(ChromeDriver driver, int max) { List<string> ids = new List<string>(); List<string> urls1 = new List<string>(); while (true) { var imgElms = driver.FindElementById("islrg").FindElements(By.TagName("img")); // img要素はみつからないなら終了 if (imgElms.Count == 0) return urls1; List<string> urls2 = new List<string>(); foreach (var elm in imgElms) { string id = elm.ToString(); if (ids.Any(x => x == id)) continue; ids.Add(id); urls2.Add(elm.GetAttribute("src")); } urls1.AddRange(urls2); // 新しいデータを取得できないなら終了 if (urls2.Count == 0) return urls1; // 取得されたデータのなかに不適切なものがある場合は排除 urls1 = urls1.Where(x => x != null && x != "").ToList(); // 最大取得数に達している場合は終了 if (urls1.Count > max) { urls1 = urls1.Take(max).ToList(); return urls1; } if (urls1.Count == max) return urls1; // スクロールさせて新しいデータを読み込む int y = imgElms.Last().Location.Y; string script = string.Format("window.scrollBy(0, {0})", y); driver.ExecuteScript(script); // 「結果をもっと表示"」ボタンをクリックできるならクリックする var inputElms = driver.FindElementsByTagName("input"); foreach (var elm in inputElms) { if (elm.GetAttribute("value").IndexOf("結果をもっと表示") != -1) { try { elm.Click(); } catch { } } } // ページが読み込まれるのを待つ System.Threading.Thread.Sleep(5000); } } } |
imgタグのsrc属性を取得できたらあとはurlかどうか調べてurlであれば前回同様に GetJpgFile(string filePath, string url)メソッドで画像ファイルとして保存します。base64エンコードされていたら、Convert.FromBase64Stringメソッドでbyteの配列に変換してSystem.IO.File.WriteAllBytesメソッドでファイルとして保存します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
public partial class Form1 : Form { private void button1_Click(object sender, EventArgs e) { ChromeDriver driver = new ChromeDriver(); driver.Url = "https://www.google.co.jp/search?q=%E9%BD%8B%E8%97%A4%E9%A3%9B%E9%B3%A5&tbm=isch"; System.Threading.Thread.Sleep(3000); List<string> srcs = GetImgSrcs(driver, 200); driver.Quit(); driver.Dispose(); // 保存するフォルダを選択する FolderBrowserDialog dialog = new FolderBrowserDialog(); dialog.ShowDialog(); string path = dialog.SelectedPath; dialog.Dispose(); int i = 0; StringBuilder sb = new StringBuilder(); foreach (var src in srcs) { if (src.Length < 4) continue; i++; string filePath = String.Format("{0}\\{1}.jpg", path, i.ToString()); if (src.Substring(0, 4) == "http") { GetJpgFile(filePath, src); } string datastring = "data:image/jpeg;base64,"; if (src.Substring(0, datastring.Length) == datastring) { string base64 = src.Substring(datastring.Length); byte[] vs = Convert.FromBase64String(base64); System.IO.File.WriteAllBytes(filePath, vs); } } } // 指定したファイルパスに画像ファイルを保存する public static void GetJpgFile(string filePath, string url) { var ms = new System.IO.MemoryStream(); try { var req = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(url); var res = (System.Net.HttpWebResponse)req.GetResponse(); var st = res.GetResponseStream(); Byte[] buf = new Byte[1000]; while (true) { int read = st.Read(buf, 0, buf.Length); if (read > 0) ms.Write(buf, 0, read); else break; } System.IO.File.WriteAllBytes(filePath, ms.ToArray()); } catch { } } } |