C# Selnium 位置情報変更 Google検索 Yahoo検索

現在の位置情報を変更して現地の検索条件を検索したい時などに。Pythonでの情報は結構おちてるんだけどC#の情報がとても少ない。初めどうにも上手くいかないのでPythonでやろうか悩んだんだけどなんとかしたいなぁが勝ったのでなんとかしてみることにした結果・・・・

Pythonの位置情報変更コード

search.txtルから一行読み込み。カンマ区切りで1つ目に検索キーワード、2つ目に位置情報が入ってる感じにした。仕様としてどうだろう感はあるけどとりあえずなのでまぁいいかな感じ。
ネット情報の情報だと「位置情報が切り替わって検索できました!」って報告が多いんだけど・・・・下記のプログラムには入れてないけどスクレイピングしてみるとどうにも位置情報が切り替わってない様子・・・・

import os
from selenium import webdriver
from time import sleep
import urllib.parse

path = os.getcwd()
def start_chrome_driver():
    options = webdriver.ChromeOptions()
    options.add_argument("--headless")
    options.add_argument("--disable-gpu")
    
    driver = webdriver.Chrome(options=options)
    return driver

driver = start_chrome_driver()
driver.execute_cdp_cmd(
    "Browser.grantPermissions",
    {
        "origin": "https://www.google.co.jp/",
        "permissions": ["geolocation"]
    },
)

with open(path + '/search.txt') as f:
    for line in f:
        driver.execute_cdp_cmd(
		    "Emulation.setGeolocationOverride",
		    {
		        "latitude": (line.split(',')[1]),
		        "longitude": (line.split(',')[2]),
		        "accuracy": 100,
		    },
		)
        
        driver.get('https://www.google.co.jp?q=' + urllib.parse.quote(line.split(',')[0]))
        sleep(10)

–headless入れてるので画面が見えないのでとりあえず外して見てみると位置情報変わってないっぽい?というか位置情報自体は変わっているけど適用されてない感じ。Browser.grantPermissions部分があれば切り替わるって話だったんけどどうにも駄目みたい。

ということで下記を追加。一度検索をかけた後に現在の正確な位置を使用ボタンを押してセットした位置情報変更を適用させると検索内容も意図したものが出るようになった。

gmb_name = driver.find_element(By.CLASS_NAME, "gLFyf")
gmb_name.send_keys("焼肉")
gmb_name.send_keys(Keys.ENTER)

for elem_a in driver.find_elements(By.TAG_NAME, "a"):
    if elem_a.get_attribute("jsname") == "gXWYVe":
        elem_a.click()
        break

sleep(2)
for elem_button in driver.find_elements(By.TAG_NAME, "g-raised-button"):
    if elem_button.get_attribute("class") == "Gfzyee VDgVie jREHUb R1smN Pjsr7c":
        elem_button.click()
        break

sleep(10)

C#の位置情報変更コード

下記コードで。位置情報の変更が適用されないのは同じだったので・・・・その辺りを考慮してコードを書いた。PythonもC#もマルチスレッドでゴリゴリ行くもんだろうと思うけど迷惑かけるのでシングルスレッドにしておくwコンソールプログラムにて・・・・

using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.DevTools;
using OpenQA.Selenium.Support.UI;
using OpenQA.Selenium.Interactions;

using OpenQA.Selenium.DevTools.V108.Emulation;

namespace GeolocationSearch
{
    class Program
    {
        static void Main(string[] args)
        {
            strFileName = Environment.CurrentDirectory + "\\search.txt";
            if (!System.IO.File.Exists(strFileName))
            {
                Console.WriteLine("search.txtがありません。終了します。");

                Console.ReadLine();
                return;
            }
            sr = new StreamReader(Environment.CurrentDirectory + "\\search.txt", System.Text.Encoding.GetEncoding("shift_jis"));
            while (sr.Peek() > -1)
            {
                string strRet = string.Empty;
                strRet = sr.ReadLine();
                string[] search = strRet.Split(' ');
                GeoLocation_Google(search[0], search[1], search[2]).GetAwaiter().GetResult();
            }
        }

public static async Task GeoLocation_Google(string strSearch, string strLatittude, String strLongitude)
        {
        ChromeDriver driver = new ChromeDriver();

            DevToolsSession devToolsSession = driver.GetDevToolsSession();
            var geoLocationOverrideCommandSettings = new SetGeolocationOverrideCommandSettings();

            geoLocationOverrideCommandSettings.Latitude = double.Parse(strLatittude);
            geoLocationOverrideCommandSettings.Longitude = double.Parse(strLongitude);
            geoLocationOverrideCommandSettings.Accuracy = 1;

            await devToolsSession
                .GetVersionSpecificDomains<OpenQA.Selenium.DevTools.V108.DevToolsSessionDomains>()
                .Emulation
                .SetGeolocationOverride(geoLocationOverrideCommandSettings);

            driver.Url = "https://www.google.co.jp";
            driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(5);
            Thread.Sleep(1000);
            var WebElement = driver.FindElement(By.ClassName("gLFyf"));
            WebElement.SendKeys(strSearch);
            WebElement.SendKeys(Keys.Enter);

            //現在の正確な位置を使用を押下
            foreach (var elem in driver.FindElements(By.TagName("a")))
            {
                if (elem.GetAttribute("jsname") == "gXWYVe")
                {
                    elem.Click();
                    break;
                }
            }

            driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(5);
            Thread.Sleep(1000);
            foreach (var elem in driver.FindElements(By.TagName("g-raised-button")))
            {
                if (elem.GetAttribute("class") == "Gfzyee VDgVie jREHUb R1smN Pjsr7c")
                {
                    elem.Click();
                    break;
                }
            }
            driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(5);
            Thread.Sleep(1000);

            //driver.Quit();
        }
    }
}

結局わからなかった所

C#には、Pythonのexecute_cdp_cmdと同じExecuteCdpCommandがあるのだけれど使い方がいまいちわからなかった。ただ、使えたとしてもPython側でも位置情報が変更されていなかったのでおなじけっかだったかなと思う。

Yahoo位置情報変更、検索コード

YahooはPC検索での位置情報変更はできないみたい。Chromeのモバイルエミュレートを使用して位置情報を変更する。googleと同じでそのままだと位置情報が適用されないのでこれも位置情報適用のURLをポチッとなする。Pythonの方の追加部分はこんな感じ。後は位置情報変更部分を叩けばいいので後述のC#のコードから要素名取ってくるか自分で調べてポチッとなしてもらえると。

options = webdriver.ChromeOptions()
options.add_argument('--headless')
mobile_emulation = { "deviceName": "Galaxy S5" }
options.add_experimental_option("mobileEmulation", mobile_emulation)

driver = webdriver.Chrome(service=chrome_service, options=options)

C#のコードchromeドライバーはオプション付きで。

ChromeOptions options = new ChromeOptions();
options.EnableMobileEmulation("Galaxy S5");
ChromeDriver driver = new ChromeDriver(options);

driver.Url = strURL;
            driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(5);
            Thread.Sleep(1000);

            var WebElement = driver.FindElement(By.ClassName("SearchInput_SearchInput__input__jrTvD"));
            WebElement.SendKeys(strSearch);
            WebElement.SendKeys(Keys.Enter);

            driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(5);
            Thread.Sleep(1000);

            //現在位置変更ボタンを押下。位置情報を更新する
            foreach (var elem in driver.FindElements(By.TagName("a")))
            {
                if (elem.Text == "現在地を取得")
                {
                    elem.Click();
                    break;
                }
            }
            driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(5);
            Thread.Sleep(1000);

最後に

とりあえず動くようにはできましたが・・・・もっといい方法がきっとあるのだろうなぁと思いつつ・・・動けばいいんだよ精神で乗り切りました。「あほやなぁ・・・・こうしたらええねのに・・・・」な人がおられましたら厳しくない言葉でコメントで指摘してくださいwコンピューター関連のできる人は言葉きつい人多いので嫌ですw

コメント

タイトルとURLをコピーしました