Format: text/x-python
⬇ Download File (4.6 KB)
   1  """googlesearch is a Python library for searching Google, easily."""
   2  from time import sleep
   3  from bs4 import BeautifulSoup
   4  from requests import get
   5  from urllib.parse import unquote # to decode the url
   6  from .user_agents import get_useragent
   7  
   8  
   9  def _req(term, results, lang, start, proxies, timeout, safe, ssl_verify, region):
  10      resp = get(
  11          url="https://www.google.com/search",
  12          headers={
  13              "User-Agent": get_useragent(),
  14              "Accept": "*/*"
  15          },
  16          params={
  17              "q": term,
  18              "num": results + 2,  # Prevents multiple requests
  19              "hl": lang,
  20              "start": start,
  21              "safe": safe,
  22              "gl": region,
  23          },
  24          proxies=proxies,
  25          timeout=timeout,
  26          verify=ssl_verify,
  27          cookies = {
  28              'CONSENT': 'PENDING+987', # Bypasses the consent page
  29              'SOCS': 'CAESHAgBEhIaAB',
  30          }
  31      )
  32      resp.raise_for_status()
  33      return resp
  34  
  35  
  36  class SearchResult:
  37      def __init__(self, url, title, description):
  38          self.url = url
  39          self.title = title
  40          self.description = description
  41  
  42      def __repr__(self):
  43          return f"SearchResult(url={self.url}, title={self.title}, description={self.description})"
  44  
  45  
  46  def search(term, num_results=10, lang="en", proxy=None, advanced=False, sleep_interval=0, timeout=5, safe="active", ssl_verify=None, region=None, start_num=0, unique=False):
  47      """Search the Google search engine"""
  48  
  49      # Proxy setup
  50      proxies = {"https": proxy, "http": proxy} if proxy and (proxy.startswith("https") or proxy.startswith("http")) else None
  51  
  52      start = start_num
  53      fetched_results = 0  # Keep track of the total fetched results
  54      fetched_links = set() # to keep track of links that are already seen previously
  55  
  56      while fetched_results < num_results:
  57          # Send request
  58          resp = _req(term, num_results - start,
  59                      lang, start, proxies, timeout, safe, ssl_verify, region)
  60          
  61          # put in file - comment for debugging purpose
  62          # with open('google.html', 'w') as f:
  63          #     f.write(resp.text)
  64          
  65          # Parse
  66          soup = BeautifulSoup(resp.text, "html.parser")
  67          result_block = soup.find_all("div", class_="ezO2md")
  68          new_results = 0  # Keep track of new results in this iteration
  69  
  70          for result in result_block:
  71              # Find the link tag within the result block
  72              link_tag = result.find("a", href=True)
  73              # Find the title tag within the link tag
  74              title_tag = link_tag.find("span", class_="CVA68e") if link_tag else None
  75              # Find the description tag within the result block
  76              description_tag = result.find("span", class_="FrIlee")
  77  
  78              # Check if all necessary tags are found
  79              if link_tag and title_tag and description_tag:
  80                  # Extract and decode the link URL
  81                  link = unquote(link_tag["href"].split("&")[0].replace("/url?q=", "")) if link_tag else ""
  82              # Extract and decode the link URL
  83              link = unquote(link_tag["href"].split("&")[0].replace("/url?q=", "")) if link_tag else ""
  84              # Check if the link has already been fetched and if unique results are required
  85              if link in fetched_links and unique:
  86                  continue  # Skip this result if the link is not unique
  87              # Add the link to the set of fetched links
  88              fetched_links.add(link)
  89              # Extract the title text
  90              title = title_tag.text if title_tag else ""
  91              # Extract the description text
  92              description = description_tag.text if description_tag else ""
  93              # Increment the count of fetched results
  94              fetched_results += 1
  95              # Increment the count of new results in this iteration
  96              new_results += 1
  97              # Yield the result based on the advanced flag
  98              if advanced:
  99                  yield SearchResult(link, title, description)  # Yield a SearchResult object
 100              else:
 101                  yield link  # Yield only the link
 102  
 103              if fetched_results >= num_results:
 104                  break  # Stop if we have fetched the desired number of results
 105  
 106          if new_results == 0:
 107              #If you want to have printed to your screen that the desired amount of queries can not been fulfilled, uncomment the line below:
 108              #print(f"Only {fetched_results} results found for query requiring {num_results} results. Moving on to the next query.")
 109              break  # Break the loop if no new results were found in this iteration
 110  
 111          start += 10  # Prepare for the next set of results
 112          sleep(sleep_interval)
 113