from selenium.webdriver.common.action_chains import ActionChains from dateutil.parser import parse from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.chrome.options import Options from fake_useragent import UserAgent def load_topic(topic, headless=True): # instantiate driver options = Options() if headless: options.headless = True # fake a user agent to not be denied service ua = UserAgent() userAgent = ua.random options.add_argument(f'user-agent={userAgent}') driver = webdriver.Chrome(options=options) # open webpage url = f'https://twitter.com/search?q=%23{topic}&src=typed_query&f=live' driver.get(url) # wait for popup and click it timeout = 30 # seconds xpath_str = "//*[text()='Not now']" element = WebDriverWait(driver, timeout).until(EC.presence_of_element_located((By.XPATH, xpath_str))) element.click() return driver def list_tweets(driver): timeout = 30 # seconds _ = WebDriverWait(driver, timeout).until(EC.presence_of_element_located((By.CSS_SELECTOR, '[data-testid="tweet"]'))) return driver.find_elements(By.CSS_SELECTOR, '[data-testid="tweet"]') def scroll_to(driver, tweet): action = ActionChains(driver) action.move_to_element(tweet).perform() def get_id(tweet): return tweet.id def get_timestamp(tweet): timestamp = tweet.find_element(By.TAG_NAME, "time").get_attribute("datetime") return parse(timestamp) def get_content(tweet): return tweet.find_element(By.CSS_SELECTOR, 'div[lang]').text def get_username(tweet): return tweet.find_element(By.XPATH, ".//span[contains(text(), '@')]").text def extract(driver, limit=100): id_list = list() username_list = list() timestamp_list = list() content_list = list() while len(id_list) < limit: tweet_list = list_tweets(driver) for tweet in tweet_list: id = get_id(tweet) if id in id_list: continue scroll_to(driver, tweet) username_list.append(get_username(tweet)) timestamp_list.append(get_timestamp(tweet)) content_list.append(get_content(tweet)) id_list.append(id) return username_list, timestamp_list, content_list def scrape(topic, limit=100, headless=True): try: # prepare driver driver = load_topic(topic, headless) except Exception as e: print('failed instantiating webdriver') print(e) return [], [], [] try: # extract information username_list, timestamp_list, content_list = extract(driver, limit) except Exception as e: print('error when extracting tweets') print(e) return [], [], [] finally: # close driver driver.close() driver.quit() return username_list, timestamp_list, content_list