前回の続きです。前回は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         {         }     } } | 
