• Home
  • Archive by category "Web automation"

Never say no..

Google My Business is a service from Google which “lets you manage your online presence across Google Search and Maps”. Most of the companies online would have signed up for Google My Business by now, if not for improving their online presence, then to respond to reviews that people leave on their maps locations.

Normally, a business owner would control the information on Google My Business by editing the listing pages of their business, after signing in to the Google My Business app. If your business has flexible working hours, and you need to edit listing information on your website or other booking sites, editing information on two or more sites every time your information changes, becomes tedious. Wouldn’t it be good to have an API (application programmable interface) to automate this? Google does have an API. But it is not open for use by anyone. You need to apply to get access to it.

In my case, I have developed a software to comprehensively manage electronic medical records of hospitals and clinics. As part of the software, MyOPIP.com has a setting to enable working and break hours of doctors. It is much more comprehensive than what Google offers on its GMB pages. I wanted to automatize setting working hours on GMB every time information of MyOPIP.com is updated. At the time I didnt have GMB API access, so I did it with Selenium:

The example below will open your Google MyBusiness page after logging in, and then remove all the current working hours information and replace it with dummy information, setting the Opens at to 6am, and Closes at to 6pm. If you need this different, just edit it to what you need.

from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import 
from selenium.common.exceptions import 
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options
import os
import re
import time
# For testing compatibility, check http://chromedriver.chromium.org/downloads
options = webdriver.ChromeOptions()
# options.add_argument('--headless')
options.add_argument('--disable-dev-shm-usage')
options.add_argument("start-maximized")#; // open Browser in maximized mode
options.add_argument("disable-infobars")#; // disabling infobars
options.add_argument("--disable-extensions")#; // disabling extensions
options.add_argument("--disable-gpu")#; // applicable to windows os only
options.add_argument("--disable-dev-shm-usage") # // overcome limited resource problems
options.add_argument("--no-sandbox") # Bypass OS security model
options.binary_location = "/opt/google/chrome/chrome"
options.add_argument("--verbose")
options.add_argument("--log-path=/home/joel/chrome.log")
driver = webdriver.Chrome(chrome_options=options)

def AuthenticationDetails():
    myemail = '[email protected]'
    mypassword = 'mypassword'
    return (myemail, mypassword)

def LoginGMB(driver):
    print("Logging in..")
    (myemail, mypassword) = AuthenticationDetails()
    # Entering Username
    WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, 'identifierId'))).send_keys(myemail)
    WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, 'identifierNext'))).click()
    # Entering Password
    WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.NAME, 'password'))).send_keys(mypassword)
    WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.ID, 'passwordNext'))).click()
    # Submitting Password
    WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, '//*[@id="main_viewpane"]/div[2]/div/div/div[1]/div[2]/content/div[6]'))).click()
    WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, '[data-day-of-week="1"]')))
    print("Searching for Remove buttons")

    print("Removing excess boxes") 
    for day in range(0,7):
        sel = f'[data-day-of-week="{day}"]'
        dayel = driver.find_element_by_css_selector(sel)
        print(f'Day of week: {day}')
        btns = dayel.find_elements_by_xpath('./div/div/div/div[3]')
        for btn in btns:
            try:
                btn.click()        
            except:
                print(f"Click didnt work for {btn} of day {day}")        

    for day in range(0,7):
        sel = f'[data-day-of-week="{day}"]'
        dayel = driver.find_element_by_css_selector(sel)
        print(f'Day of week: {day}')      
        openbtns = dayel.find_elements_by_xpath('.//input[@aria-label="Opens at"]')
        print(f'No: of opens at elements is {len(openbtns)}')
        if len(openbtns)==0:
            print("No boxes found")
            AddHours(dayel)

    ClearBoxes()

    apply_btn = driver.find_element_by_xpath('//span[contains(text(),"Apply")]')
    print(f'Clicking Apply button {apply_btn}')
    apply_btn.click()

        
def AddHours(dayel):
    print("Adding Day boxes")
    try:
        Addhrbtn = dayel.find_element_by_xpath('./div[2]/div[2]')
        Addhrbtn.click()
    except:
        print(f"Couldnt add hours for this day {day}")
        pass


def ClearBoxMethod1(dayel):
    try:
        iopen = dayel.find_element_by_xpath('.//input[@aria-label="Opens at"]')
        iclose = dayel.find_element_by_xpath('.//input[@aria-label="Closes at"]')
        iopen.click()
        iopen.clear()
        iopen.send_keys("6:00 am")
        iclose.click()
        iclose.clear()
        iclose.send_keys("6:00 pm")
    except:
        print("Couldnt find open or close element")
        pass    

def ClearBoxes():
    print("Now adding new values")            
    for day in range(0,7):
        sel = f'[data-day-of-week="{day}"]'
        dayel = driver.find_element_by_css_selector(sel)
        print(f'Day of week: {day}')
        ClearBoxMethod1(dayel)

def OpenGMB(url):    
    driver.get(url)
    print(driver.current_url)

    pattern = re.compile(".*accounts.google.com/signin.*")
    match = re.search(pattern, driver.current_url)
    if match:
        LoginGMB(driver)
    print("Ok we're back")
    
# Replace url by yours
url = 'https://business.google.com/edit/l/000000000001?hl=en-GB'
OpenGMB(url)

Update: Now, I’ve been granted API access. See this post for using the API with python to update information