Home » Tutorials » How to Automate Web Searches Using Selenium in Python

How to Automate Web Searches Using Selenium in Python

In the age of information, we constantly find ourselves searching the web for answers, insights, or just out of curiosity. From looking up the latest news to researching deep technical topics, web searches have become an integral part of our daily routines. But what if you could automate those searches? Imagine saving time by letting a tool do the heavy lifting for you, searching across multiple websites with just a few clicks.

Today, you’ll learn how to automate web searches using Selenium in Python. We’ll walk you through setting up a simple yet effective Tkinter GUI, configuring Selenium WebDriver, and performing automated searches on popular websites like Google, Bing, and Wikipedia. By the end of this tutorial, you’ll have a powerful tool at your fingertips, ready to simplify your web search tasks and enhance your automation skills.

Let’s get started!

Table of Contents

Getting Started

Before we dive into the code, make sure you’ve got everything set up. You’ll need to install a few libraries to make it all work smoothly. Just open your terminal or command prompt and run these commands:

$ pip install selenium
$ pip install tk

You’ll also need to install the ChromeDriver that matches your Chrome version. Just find the right URL for your operating system and Chrome version, copy and paste it to download the driver.

Once you’ve got it, go ahead and install it, then make sure to add its path to your Environment Variables. This step ensures everything runs smoothly when you start automating your browser tasks.

Imports

import logging
import tkinter as tk
from tkinter import messagebox, ttk
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException, NoSuchElementException, WebDriverException
from datetime import datetime

As always, let’s start by gathering the necessary tools:

  1. Logging: This will help us track the flow of the program and debug any issues.
  2. tkinter: We’ll use this to create a graphical user interface (GUI), display information and errors in message boxes, and make use of themed widgets with ttk.
  3. Selenium: This library is essential for opening a browser and navigating web pages.
    • WebDriver: This is what we use to interact with the browser.
    • Keys: This helps us handle keyboard actions.
    • By: This is used to locate elements on a web page.
    • WebDriverWait: This ensures that Selenium waits for certain conditions to be met before moving forward.
    • Expected Conditions (EC): These are the predefined conditions that need to be fulfilled.
    • TimeoutException, NoSuchElementException, and WebDriverException: These are used to handle various errors that might occur during browser automation.
  4. Datetime: This is handy for adding timestamps to filenames, as it allows us to manipulate dates and times.

Setting Up Logging

# Set up logging
logging.basicConfig(filename='selenium_test.log', level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

This is our behind-the-scenes hero, recording all our actions by saving log messages to the selenium_test.log file. Messages with INFO level and higher (like WARNING and ERROR) will be logged with a timestamp and the severity level.

Web Search Information Dictionary

For this step, let’s meet the drivers of our program, where the searches will happen. We’ve created a dictionary that holds the names of the websites we’ll be using as keys. Each key has a value that includes the website’s URL and the name of the search box we’ll use to perform the search.

# Dictionary to map website names to URLs and search box names
websites = {
   "Python.org": {"url": "http://www.python.org", "search_box": "q"},
   "Google": {"url": "http://www.google.com", "search_box": "q"},
   "Wikipedia": {"url": "http://www.wikipedia.org", "search_box": "search"},
   "Bing": {"url": "http://www.bing.com", "search_box": "q"}
}

Now, we’ve reached the core of our script, where the real action happens—the part that performs the search on the selected website. The perform_search() function kicks things off by retrieving the selected site’s URL and search box name from the websites dictionary. Then, webdriver starts a new Chrome browser session.

After that, the function uses driver.get() to navigate to the selected URL. If everything goes smoothly and the website opens, we log a success message. But if any errors pop up during this process, an error message will be displayed.

def perform_search(search_term, selected_site):
   site_info = websites[selected_site]
   url = site_info["url"]
   search_box_name = site_info["search_box"]

   # Start the WebDriver and open the website
   try:
       driver = webdriver.Chrome()
       logging.info("WebDriver started successfully.")
       driver.get(url)
       logging.info(f"Website {url} opened successfully.")
   except WebDriverException as e:
       logging.error(f"Error starting WebDriver or opening website: {e}")
       messagebox.showerror("Error", f"Error starting WebDriver or opening website: {e}")
       return

With the website now open, By.NAME helps locate the search box, while WebDriverWait and EC.presence_of_element_located ensure the script pauses until the search box is found, up to 10 seconds. If the search box isn’t found within this time, TimeoutException will step in and display an error message about the search results.

If everything goes well, the script clears any pre-existing text in the search box with elem.clear(), enters the search term using elem.send_keys(search_term), and presses the Enter key with elem.send_keys(Keys.RETURN). Finally, a log message confirms that the search has been successfully initiated.

   try:
       # Find the search box and perform the search
       elem = WebDriverWait(driver, 10).until(
           EC.presence_of_element_located((By.NAME, search_box_name))
       )
       elem.clear()
       elem.send_keys(search_term)
       elem.send_keys(Keys.RETURN)
       logging.info(f"Search for '{search_term}' executed on {selected_site}.")

Once the search is initiated successfully, the script waits for the page to load by checking for the presence of the body tag. If the page loads and the body tag is found, the script checks if the phrase “No results found” is present. If it is, the script raises an AssertionError and displays an error message. If not, it sets a path for saving a screenshot of the loaded page.

The screenshot is then saved using driver.save_screenshot(), and the success is celebrated with a message box confirming that the screenshot has been saved.

       # Check if there are results and take a screenshot
       WebDriverWait(driver, 10).until(
           EC.presence_of_element_located((By.TAG_NAME, "body"))
       )
       assert "No results found." not in driver.page_source
       logging.info("Search results found.")
       # Take a screenshot
       screenshot_path = f"screenshot_{datetime.now().strftime('%Y%m%d_%H%M%S')}.png"
       driver.save_screenshot(screenshot_path)
       logging.info(f"Screenshot saved at {screenshot_path}.")
       messagebox.showinfo("Success", f"Search completed successfully. Screenshot saved at {screenshot_path}.")

Finally, if any errors occur, the script has built-in error handling that displays error messages and ensures the WebDriver closes properly. This error handling covers scenarios like TimeoutException when a condition isn’t met within the specified time, AssertionError when the expected results aren’t found, NoSuchElementException when an element can’t be found, and WebDriverException for any other WebDriver-related issues.

   except (TimeoutException, AssertionError, NoSuchElementException) as e:
       logging.error(f"Error with search results: {e}")
       messagebox.showerror("Error", f"Error with search results: {e}")
   finally:
       try:
           driver.quit()
       except WebDriverException as e:
           logging.error(f"Error closing WebDriver: {e}")

Initiating the Search Function

We have already talked about the perform_search() function, but let’s not forget about the start_search() function and why it’s so important:

This function is key because it doesn’t just call perform_search(), it also makes sure everything is ready to go. It grabs the search term you entered using entry.get() and the website you selected from the combobox with site_combobox.get(). If you didn’t provide either of these, it will pop up a warning message asking you to fill them in. But if everything’s in place, it hands things over to perform_search() to get the search going.

def start_search():
   search_term = entry.get()
   selected_site = site_combobox.get()
   if search_term and selected_site:
       perform_search(search_term, selected_site)
   else:
       messagebox.showwarning("Input Error", "Please enter a search term and select a website.")

Setting Up the Main Window

We’re finally at the endgame, this is where we create the main window using tk, set its title, and define its size with geometry.

root = tk.Tk()
root.title("Selenium Search App - The Pycodes")
root.geometry("400x200")

Next, we create a frame to hold our widgets, giving it some padding for a neat layout.

frame = tk.Frame(root)
frame.pack(padx=10, pady=10)

We add a label to indicate the search term entry field and then create the entry widget where the user will input the search term.

label = tk.Label(frame, text="Enter search term:")
label.grid(row=0, column=0, padx=5, pady=5)

entry = tk.Entry(frame)
entry.grid(row=0, column=1, padx=5, pady=5)

After that, we add a label for the website selection and a combobox that lists the website names from our dictionary. We set Python.org as the default selection.

site_label = tk.Label(frame, text="Select website:")
site_label.grid(row=1, column=0, padx=5, pady=5)

site_combobox = ttk.Combobox(frame, values=list(websites.keys()))
site_combobox.grid(row=1, column=1, padx=5, pady=5)
site_combobox.set("Python.org")  # Set default value

We then create a “Search” button that, when clicked, calls the start_search() function to initiate the search process.

search_button = tk.Button(frame, text="Search", command=start_search)
search_button.grid(row=2, columnspan=2, pady=10)

Lastly, we use the mainloop() method to start the event loop, keeping the main window running and responsive to user interactions.

root.mainloop()

Example

Full Code

import logging
import tkinter as tk
from tkinter import messagebox, ttk
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import TimeoutException, NoSuchElementException, WebDriverException
from datetime import datetime


# Set up logging
logging.basicConfig(filename='selenium_test.log', level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')


# Dictionary to map website names to URLs and search box names
websites = {
   "Python.org": {"url": "http://www.python.org", "search_box": "q"},
   "Google": {"url": "http://www.google.com", "search_box": "q"},
   "Wikipedia": {"url": "http://www.wikipedia.org", "search_box": "search"},
   "Bing": {"url": "http://www.bing.com", "search_box": "q"}
}


def perform_search(search_term, selected_site):
   site_info = websites[selected_site]
   url = site_info["url"]
   search_box_name = site_info["search_box"]


   # Start the WebDriver and open the website
   try:
       driver = webdriver.Chrome()
       logging.info("WebDriver started successfully.")
       driver.get(url)
       logging.info(f"Website {url} opened successfully.")
   except WebDriverException as e:
       logging.error(f"Error starting WebDriver or opening website: {e}")
       messagebox.showerror("Error", f"Error starting WebDriver or opening website: {e}")
       return


   try:
       # Find the search box and perform the search
       elem = WebDriverWait(driver, 10).until(
           EC.presence_of_element_located((By.NAME, search_box_name))
       )
       elem.clear()
       elem.send_keys(search_term)
       elem.send_keys(Keys.RETURN)
       logging.info(f"Search for '{search_term}' executed on {selected_site}.")


       # Check if there are results and take a screenshot
       WebDriverWait(driver, 10).until(
           EC.presence_of_element_located((By.TAG_NAME, "body"))
       )
       assert "No results found." not in driver.page_source
       logging.info("Search results found.")
       # Take a screenshot
       screenshot_path = f"screenshot_{datetime.now().strftime('%Y%m%d_%H%M%S')}.png"
       driver.save_screenshot(screenshot_path)
       logging.info(f"Screenshot saved at {screenshot_path}.")
       messagebox.showinfo("Success", f"Search completed successfully. Screenshot saved at {screenshot_path}.")
   except (TimeoutException, AssertionError, NoSuchElementException) as e:
       logging.error(f"Error with search results: {e}")
       messagebox.showerror("Error", f"Error with search results: {e}")
   finally:
       try:
           driver.quit()
       except WebDriverException as e:
           logging.error(f"Error closing WebDriver: {e}")


def start_search():
   search_term = entry.get()
   selected_site = site_combobox.get()
   if search_term and selected_site:
       perform_search(search_term, selected_site)
   else:
       messagebox.showwarning("Input Error", "Please enter a search term and select a website.")


# Set up the Tkinter GUI

root = tk.Tk()
root.title("Selenium Search App - The Pycodes")
root.geometry("400x200")


frame = tk.Frame(root)
frame.pack(padx=10, pady=10)


label = tk.Label(frame, text="Enter search term:")
label.grid(row=0, column=0, padx=5, pady=5)


entry = tk.Entry(frame)
entry.grid(row=0, column=1, padx=5, pady=5)


site_label = tk.Label(frame, text="Select website:")
site_label.grid(row=1, column=0, padx=5, pady=5)


site_combobox = ttk.Combobox(frame, values=list(websites.keys()))
site_combobox.grid(row=1, column=1, padx=5, pady=5)
site_combobox.set("Python.org")  # Set default value


search_button = tk.Button(frame, text="Search", command=start_search)
search_button.grid(row=2, columnspan=2, pady=10)


root.mainloop()

Happy Coding!

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top