├── README.md ├── __pycache__ ├── answering.cpython-310.pyc └── set_openai_api_key.cpython-310.pyc ├── quora_automation.py ├── requirements.txt └── set_openai_api_key.py /README.md: -------------------------------------------------------------------------------- 1 | # Quora QA Automation 2 | Welcome to the Quora QA Automation project, an open-source program that utilizes Selenium and GPT-3 for answering questions on Quora. 3 | 4 | ### Overview 5 | This open-source program uses a combination of Selenium and GPT-3 to answer questions on the Quora platform. The program utilizes Selenium to automate the opening of a Chrome browser, navigates to the Quora website, extracts the first question listed on the page, and passes it to GPT-3 for a response. The response generated by GPT-3 is then posted on Quora. 6 | 7 | The program employs the OpenAI API for accessing GPT-3, which provides the necessary interface for making requests to the GPT-3 model. This integration allows the program to leverage GPT-3's state-of-the-art natural language processing capabilities, which are capable of generating human-like responses to a wide variety of questions. 8 | 9 | One key advantage of this program is its flexibility in allowing users to specify a custom data directory for the Chrome browser. This feature provides users with the option to store their browsing data, such as cookies and cache, in a location of their choosing. 10 | 11 | This program is ideal for anyone looking to automate their Quora activities, particularly those who frequently respond to questions on the platform. By leveraging GPT-3's advanced natural language processing capabilities, the program can generate high-quality responses to questions, saving users significant time and effort. 12 | 13 | ### Customization 14 | This program can be customized to your personal/organizational needs. For more information, please contact me via [LinkedIn](https://www.linkedin.com/in/harmindersinghnijjar/) or email at harmindernijjar1996@gmail.com 15 | 16 | ### Frameworks: 17 | 18 | [Selenium](https://www.selenium.dev/) - a popular automation testing framework that provides a suite of tools for web browser automation. It allows for programmatically controlling a web browser and automating user actions, such as clicking buttons, filling forms, and extracting data from web pages. 19 | 20 | [OpenAI API](https://openai.com/api/) - a powerful artificial intelligence API that provides access to GPT-3, a language model capable of generating human-like text. It can be used for a variety of natural language processing tasks, such as language translation, summarization, and conversation generation. 21 | 22 | ### Language: 23 | 24 | - [Python](https://www.python.org/) 25 | 26 | ### Flow diagrams: 27 | 28 | ### Requirements: 29 | 30 | - [API key](https://beta.openai.com/account/api-keys) 31 | 32 | ### Modules: 33 | 34 | - child_process 35 | - fs 36 | - [openai](https://www.npmjs.com/package/openai) 37 | - os 38 | - [selenium-webdriver](https://www.npmjs.com/package/selenium-webdriver) 39 | - sendkeys 40 | - util 41 | - [webdriver_manager](https://www.npmjs.com/package/webdriver-manager) 42 | 43 | ### API: 44 | 45 | - [openai-api](https://openai.com/api/) 46 | 47 | ### Classes: 48 | 49 | ### Functions: 50 | 51 | 1. answer_quora_question(answer): This function is used to post an answer received from GPT-3 on Quora and selecting a personalized answer credential. 52 | 2. extract_question(): This function is used to extract the first question listed on www.quora.com/answers and return it as a string. 53 | 3. gpt3_completion(prompt, engine='text-davinci-002', temp=0.7, top_p=1.0, tokens=400, freq_pen=0.0, pres_pen=0.0, stop=['JAX:', 'USER:']): This function is used to ask GPT-3 the question extracted from Quora and return the respone text as a string. 54 | 4. launch_test_case(): This function is used to open Quora in a Chrome instance. 55 | 5. open_file(filepath): This function is used to open a file and read the contents. 56 | 6. quit_application(): This function is used to close the Chrome browser. 57 | 7. setup(): This function is used to maximize Chrome window and have the driver wait for 10 seconds. 58 | 8. main(): This function is the main method in JavaScript. 59 | 9. loop(): This function is used to call the main method in a loop. 60 | 61 | ### Procedure: 62 | 63 | 1. Install the required libraries: openai, selenium-webdriver, and chrome. 64 | 2. Copy your API key from the OpenAI website. 65 | 3. Define Chrome options. 66 | 4. Instansiate Google Chrome with the above options. 67 | 5. Create a method to post answer received from GPT-3 on Quora and selecting a personalized answer credential. 68 | 6. Create a method to extract the first question listed on www.quora.com/answers and return it as a string. 69 | 7. Create a method to ask GPT-3 the question extracted from Quora and return the respone text as a string. 70 | 8. Create a method to open Quora in a Chrome instance. 71 | 9. Create a method to open a file and read the contents. 72 | 10. Create a method to close the Chrome browser. 73 | 11. Create a setup method to maximize the Chrome window and have the driver wait for 10 seconds. 74 | 12. Create a main method to call the above methods. 75 | 13. Call the main method in a loop. 76 | 77 | ### Resources: 78 | 79 | 1. OpenAI 80 | 81 | - [Best Practices for API Key Safety](https://help.openai.com/en/articles/5112595-best-practices-for-api-key-safety) 82 | 83 | 2. YouTube 84 | 85 | - [Build a Desktop App with Electron... But Should You?](https://www.youtube.com/watch?v=3yqDxhR2XxE) 86 | 87 | 3. Playwright Documentation 88 | 89 | - [launch](https://playwright.dev/docs/api/class-browsertype#browser-type-launch) 90 | 91 | ### Additional notes: 92 | 93 | ### Potential errors: 94 | 95 | If you encounter the error message "timeout: Timed out receiving message from renderer" while attempting to paste an answer into a text box, it is possible that the page load timeout has been set too low. In such instances, it is advisable to increase the page load timeout using the set_page_load_timeout() method. 96 | 97 | For example, if you are using the Selenium library in Python, you can increase the page load timeout by executing the following code: 98 | 99 | ``` 100 | from selenium import webdriver 101 | 102 | driver = webdriver.Chrome() 103 | driver.set_page_load_timeout(X) # Increase the timeout to X seconds 104 | ``` 105 | 106 | In the code above, the set_page_load_timeout() method is responsible for specifying the maximum time the browser should wait for a page to load before throwing an error. By increasing this timeout value, you may be able to circumvent the "timeout: Timed out receiving message from renderer" error. 107 | 108 | It is important to remember to adjust the timeout value based on your specific needs and internet speed. A lengthier timeout may result in slower test execution, so finding the appropriate balance is crucial. 109 | -------------------------------------------------------------------------------- /__pycache__/answering.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harmindersinghnijjar/quora-qa-automation/ffa087d678a7232239064f4b1f7500cc1e0f6832/__pycache__/answering.cpython-310.pyc -------------------------------------------------------------------------------- /__pycache__/set_openai_api_key.cpython-310.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/harmindersinghnijjar/quora-qa-automation/ffa087d678a7232239064f4b1f7500cc1e0f6832/__pycache__/set_openai_api_key.cpython-310.pyc -------------------------------------------------------------------------------- /quora_automation.py: -------------------------------------------------------------------------------- 1 | # Description: This script automates the process of answering a question on Quora using GPT-3. 2 | # Author: harmindesinghnijjar 3 | # Date: 2023-02-24 4 | # Version: 1.0.0 5 | # Usage: python quora_automation.py 6 | 7 | # Import modules. 8 | from selenium import webdriver 9 | from selenium.webdriver.chrome.options import Options 10 | from selenium.webdriver.common.by import By 11 | from selenium.webdriver.support.ui import WebDriverWait 12 | from selenium.webdriver.support import expected_conditions as EC 13 | from selenium.common.exceptions import TimeoutException 14 | from selenium.common.exceptions import NoSuchElementException 15 | from time import sleep 16 | from webdriver_manager.chrome import ChromeDriverManager 17 | import getpass 18 | import openai 19 | import os 20 | import set_openai_api_key 21 | import time 22 | 23 | # Set OpenAI API key. 24 | openai.api_key = os.getenv("OPENAI_API_KEY") 25 | 26 | # Set username. 27 | user = getpass.getuser() 28 | 29 | # Define a Selenium class to automate the browser. 30 | class Selenium(webdriver.Chrome): 31 | # Constructor method. 32 | def __init__(self, webdriverval): 33 | driver = webdriverval 34 | 35 | 36 | # Method to post answer received from GPT-3 on Quora and selecting a personalized answer credential. 37 | def answer_quora_question(self, answer): 38 | try: 39 | 40 | # Click on button to open answer pop-up. 41 | answer_popup = self.find_element(By.CSS_SELECTOR, '#mainContent > div > div > div:nth-child(1) > div > div:nth-child(2) > div:nth-child(1) > div > div > div > div > div > div > div > div.q-box.qu-zIndex--action_bar > div > div > div:nth-child(1) > button.q-click-wrapper.qu-active--textDecoration--none.qu-focus--textDecoration--none.qu-borderRadius--pill.qu-alignItems--center.qu-justifyContent--center.qu-whiteSpace--nowrap.qu-userSelect--none.qu-display--inline-flex.qu-tapHighlight--white.qu-textAlign--center.qu-cursor--pointer.qu-hover--textDecoration--none.qu-hover--bg--darken.ClickWrapper___StyledClickWrapperBox-zoqi4f-0.iyYUZT.base___StyledClickWrapper-lx6eke-1.fJHGyh') 42 | answer_popup.click() 43 | except Exception as e: 44 | print("Error while clicking on answer popup button: ", e) 45 | return False 46 | 47 | try: 48 | 49 | # Paste answer into text box. 50 | answer_box = self.find_element(By.CSS_SELECTOR, '#root > div > div:nth-child(2) > div > div > div > div > div.q-flex.ModalContainerInternal___StyledFlex-s8es4q-2.gXhqYs.modal_content_inner.qu-flexDirection--column.qu-bg--white.qu-overflowY--auto.qu-borderAll.qu-alignSelf--center > div > div.q-flex.qu-flexDirection--column.qu-overflowY--auto > div.q-relative.qu-display--flex.qu-flexDirection--column > div > div.q-box > div:nth-child(2) > div > div > div > div > div.q-box > div') 51 | if not answer_box: 52 | raise ValueError("Could not find answer box element on the page.") 53 | else: 54 | answer_box.send_keys(answer) 55 | print(answer) 56 | except Exception as e: 57 | print("Error while pasting answer into text box: ", e) 58 | print("Unable to answer question, skipping to next question.") 59 | # Go to next question by calling the answer_quora_question method again. 60 | self.answer_quora_question(answer) 61 | 62 | # Pause for 10 seconds. 63 | time.sleep(10) 64 | 65 | try: 66 | 67 | # Post answer. 68 | post = self.find_element(By.XPATH, '//*[@id="root"]/div/div[2]/div/div/div/div/div[2]/div/div[2]/div[2]/div/div[2]/button') 69 | post.click() 70 | except Exception as e: 71 | print("Error while posting answer: ", e) 72 | return False 73 | 74 | # Pause for 2 seconds. 75 | time.sleep(2) 76 | 77 | try: 78 | 79 | # Select "I help people with technology and enjoy learning about ML" as your answer credential. 80 | first_answer_credential = self.find_element(By.XPATH, '//*[@id="root"]/div/div[2]/div/div/div/div/div[2]/div/div[2]/div[1]/div/div[1]/div[3]/div[1]/div/label/div/div[2]/div/span/span[2]') 81 | 82 | # Click on the first answer credential element. 83 | first_answer_credential.click() 84 | except Exception as e: 85 | print("Error while selecting answer credential: ", e) 86 | return False 87 | 88 | # Pause for 2 seconds. 89 | time.sleep(2) 90 | 91 | return True 92 | 93 | # Method to extract first question listed on www.quora.com/answers and return it as a string. 94 | def extract_question(self): 95 | try: 96 | question = self.find_element(By.XPATH, '//*[@id="mainContent"]/div/div/div[1]/div/div[2]/div[1]/div/div/div/div/div/div/div/div[1]/div[1]/span/span/a/div/div/div/div/span/span').text 97 | print(question) 98 | return question 99 | except NoSuchElementException: 100 | print("Could not find question element on the page.") 101 | return "" 102 | except Exception as e: 103 | print("An error occurred while extracting the question:", e) 104 | return "" 105 | 106 | # Method to ask GPT-3 the question extracted from Quora and return the respone text as a string. 107 | def gpt3_completion(prompt, engine='text-davinci-003', temp=0.7, top_p=1.0, tokens=400, freq_pen=0.0, pres_pen=0.0): 108 | try: 109 | if not prompt: 110 | raise ValueError("Prompt cannot be empty.") 111 | prompt = prompt.encode(encoding='ASCII',errors='ignore').decode() 112 | response = openai.Completion.create( 113 | engine=engine, 114 | prompt=prompt, 115 | temperature=temp, 116 | max_tokens=tokens, 117 | top_p=top_p, 118 | frequency_penalty=freq_pen, 119 | presence_penalty=pres_pen 120 | ) 121 | if not response.choices: 122 | raise ValueError("No response from OpenAI API.") 123 | text = response.choices[0].text.strip() 124 | if not text: 125 | raise ValueError("Response text cannot be empty.") 126 | return text 127 | except Exception as e: 128 | print(f"Error occurred: {e}") 129 | return None 130 | 131 | # Method to open Quora in a Chrome instance. 132 | def open_quora_questions(self): 133 | try: 134 | 135 | # Open a webpage. 136 | self.get("https://www.quora.com/answer") 137 | except Exception as e: 138 | print("An error occurred while opening Quora:", e) 139 | else: 140 | print("Selecting a question from Quora...") 141 | 142 | # Method to close the Chrome instance. 143 | def close_browser(driver): 144 | """ 145 | Closes the web browser. 146 | 147 | Args: 148 | driver (selenium.webdriver.Chrome): The Chrome web driver object. 149 | 150 | Returns: 151 | None 152 | """ 153 | driver.quit() 154 | 155 | # Method to set up the Chrome instance. 156 | def setup(self): 157 | # AttributeError: 'Selenium' object has no attribute 'w3c' 158 | # Set Chrome window size to maximize. 159 | self.maximize_window() 160 | 161 | # Set implicit wait time to 10 seconds. 162 | self.implicitly_wait(10) 163 | 164 | # Set page load timeout to 50 seconds. 165 | self.set_page_load_timeout(50) 166 | 167 | 168 | 169 | if __name__ == '__main__': 170 | # Check if the OpenAI API key is set in the environment using the set_openai_api_key module. 171 | # If it is, then run the script. 172 | if set_openai_api_key.check_openai_api_key(): 173 | for i in range(10): 174 | conversation = list() 175 | os_command = 'taskkill /im chrome.exe /f' 176 | os.system(os_command) 177 | # Create an empty list to store conversation history. 178 | conversation = list() 179 | # Define Chrome options. 180 | options = Options() 181 | options.add_experimental_option("excludeSwitches", ["enable-logging"]) 182 | # Add a user data directory as an argument for options. 183 | options.add_argument(f"--user-data-dir=C:\\Users\\{user}\\AppData\\Local\\Google\\Chrome\\User Data") 184 | options.add_argument("profile-directory=Default") 185 | # In order to prevent the "Timed out receiving message from renderer: 20.000" error, add the following options. 186 | options.add_experimental_option('extensionLoadTimeout', 60000) 187 | # Instansiate Google Chrome with the above options. 188 | driver = webdriver.Chrome(ChromeDriverManager().install(), options=options) 189 | selenium_client = Selenium 190 | selenium_client.setup(driver) 191 | # Pause for 2 seconds. 192 | time.sleep(2) 193 | # Create an infinite loop. 194 | while True: 195 | selenium_client.open_quora_questions(driver) 196 | # Pause for 2 seconds. 197 | time.sleep(2) 198 | question = selenium_client.extract_question(driver) 199 | answer = selenium_client.gpt3_completion(question) 200 | selenium_client.answer_quora_question(driver, answer) 201 | #selenium_client.quit() 202 | # If it isn't, then ask the user how they want to enter their OpenAI API key. 203 | else: 204 | print("OpenAI API key not set in environment.") 205 | # Get the OpenAI API key from the user. 206 | api_key = set_openai_api_key.get_openai_api_key() 207 | # Set the OpenAI API key in the environment. 208 | set_openai_api_key.set_openai_api_key(api_key) 209 | # Open the environment variables in the Windows GUI with OpenAI API key highlighted. 210 | set_openai_api_key.open_env() 211 | # Run the script. 212 | 213 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | openai==0.24.0 2 | requests==2.25.0 3 | requests_html==0.10.0 4 | selenium==3.141.0 5 | webdriver_manager==3.2.2 6 | -------------------------------------------------------------------------------- /set_openai_api_key.py: -------------------------------------------------------------------------------- 1 | # Description: This script is used to set the OpenAI API key in the environment. 2 | # Author: harmindesinghnijjar 3 | # Date: 2023-02-20 4 | # Updated: 2023-04-28 5 | # Version: 1.0.0 6 | # Usage: python set_openai_api_key.py 7 | 8 | 9 | # Import required libraries. 10 | from os import environ 11 | import os 12 | import sys 13 | 14 | # Define function to check if OpenAI API key exists 15 | def check_openai_api_key(): 16 | openai_api_key = os.environ.get('OPENAI_API_KEY', None) 17 | if openai_api_key is None: 18 | print('ERROR: OPENAI_API_KEY is not set in environment variables') 19 | get_openai_api_key() 20 | else: 21 | print('SUCCESS: OPENAI_API_KEY is set in environment variables') 22 | return openai_api_key 23 | 24 | # Define functions to get OpenAI API key from file. 25 | def get_openai_api_key_from_file(filepath): 26 | with open(filepath, 'r') as infile: 27 | return infile.read().strip() 28 | 29 | # Define function to get OpenAI API key from environment. 30 | def get_openai_api_key_from_env(): 31 | return os.environ['OPENAI_API_KEY'] 32 | 33 | # Define function to get OpenAI API key from user input. 34 | def get_openai_api_key_from_user(): 35 | return input("Please enter your OpenAI API key: ") 36 | 37 | # Define function to set OpenAI API key in environment. 38 | def set_openai_api_key(api_key): 39 | # Set the OpenAI API key in the environment variable by using the command line. 40 | os.system(f"setx OPENAI_API_KEY {api_key}") 41 | 42 | # Ask user how they want to enter their OpenAI API key. 43 | def get_openai_api_key(): 44 | # Run an infinite loop until the user enters a valid choice. 45 | while True: 46 | # Print the menu. 47 | print("Welcome to the Quora Automation OpenAI API key setup script.") 48 | print("How would you like to enter your OpenAI API key?") 49 | print("1. From a file") 50 | print("2. From the environment") 51 | print("3. From the console") 52 | print("4. Exit") 53 | choice = input("Please enter a number: ") 54 | # If the user enters 1, ask them for the filepath to the API key file. 55 | if choice == '1': 56 | filepath = input("Please enter the filepath to your API key file: ") 57 | return get_openai_api_key_from_file(filepath) 58 | # If the user enters 2, get the API key from the environment. 59 | elif choice == '2': 60 | return get_openai_api_key_from_env() 61 | # If the user enters 3, ask them to enter the API key. 62 | elif choice == '3': 63 | return get_openai_api_key_from_user() 64 | # If the user enters 4, exit the script. 65 | elif choice == '4': 66 | exit() 67 | # If the user enters anything else, ask them to try again. 68 | else: 69 | print("Invalid choice. Please try again.") 70 | 71 | # Define function to display the OpenAI API key in environmental variables. 72 | def open_env(): 73 | print("Your OpenAI API key is: %s" % os.environ['OPENAI_API_KEY']) 74 | 75 | 76 | 77 | # Main program of the script. 78 | if __name__ == '__main__': 79 | # Check if the environment variable is already set. 80 | if "OPENAI_API_KEY" in os.environ: 81 | print("Your OpenAI API key is already set in the environment.") 82 | print("You can now run the quora_automation.py script.") 83 | exit() 84 | # If the environment variable is not set, ask the user how they want to enter their OpenAI API key. 85 | else: 86 | print("Your OpenAI API key is not set in the environment.") 87 | print("Let's set it now.") 88 | api_key = get_openai_api_key() 89 | print("Your OpenAI API key is: %s" % api_key) 90 | set_openai_api_key(api_key) 91 | print("Your OpenAI API key has been set in the environment.") 92 | print("You can now run the quora_automation.py script.") 93 | 94 | 95 | 96 | --------------------------------------------------------------------------------