Копирование и вставка не работает с браузером без головы в python selenium

#python-3.x #selenium #firefox #firefox-headless

Вопрос:

Я использую selenium с python, чтобы нажать кнопку на веб-странице. Это копирует данные в формате csv в буфер обмена. Затем я использую данные в буфере обмена для создания массива, который используется в дальнейшем в программе. Все работает нормально, пока я не запускаю веб-драйвер в безголовом режиме. Есть ли какое-либо решение этой проблемы? Может ли весь этот код быть написан без селена? Я открыт для идей и улучшений в своем коде.

 try:  objFFOptions = Options()  objFFOptions.add_argument('--headless')  objFFWebDriver = webdriver.Firefox(options= objFFOptions ) # start hidden  #objFFWebDriver = webdriver.Firefox()  except:  print("Error in initiating the Firefox webdriver")  objFFWebDriver.quit()  quit()    try:  objFFWebDriver.get("https://chartink.com/screener/90dis")  except:  print("Error in opening the webpage")  objFFWebDriver.quit()  quit()   # loop for waiting before query data loads  intAttemptCounter = 0  boolStockDataFetched = False   while True:  intAttemptCounter = intAttemptCounter   1   print("tFetching attempt ", intAttemptCounter)  try:  objFilterMessageElement = WebDriverWait(objFFWebDriver, (intDelaySeconds * intAttemptCounter)).   until(expected_conditions.presence_of_element_located((By.ID, 'DataTables_Table_0_info')) or   expected_conditions.presence_of_element_located((By.CLASS_NAME, 'dataTables_empty')))   print("tEither of the two marker elements found")   if re.search(r"Filtereds [0-9] s stockss ([0-9] s tos [0-9] )",  objFilterMessageElement.text) is not None:  print("t",objFilterMessageElement)   try:  # click copy button  objFFWebDriver.find_element(By.XPATH,   "//*[@class='btn btn-default buttons-copy buttons-html5 btn-primary']").click()  except NoSuchElementException:  if intAttemptCounter lt;= intMaxAttempt:  continue   # store the query result from clipboard to a string  strCSVData = pyperclip.paste()  pyperclip.copy("")   # create array from the csv string containing stock data  arrDataList = list(csv.reader(StringIO(strCSVData),delimiter='t'))  arrFinalDataList = [arrDataRecord[2] for arrDataRecord in arrDataList[3:]]    boolStockDataFetched = True  break  elif objFilterMessageElement.text == "No stocks filtered in the Scan":  print("t",objFilterMessageElement.text)  break  else:  if intAttemptCounter lt;= intMaxAttempt:  continue   except TimeoutException:  print("tTimeout Exception")  if intAttemptCounter lt;= intMaxAttempt:  continue  else:  break   if boolStockDataFetched == False:  print("Error in fetching records or no records fetched")    objFFWebDriver.quit()  

Ответ №1:

Вы, вероятно, не сможете скопировать и вставить в браузер без головы. Вместо этого вы могли бы прочитать данные из визуальной таблицы.

Однако в любом случае вам вообще не нужен селен, если вы используете инспектор своего браузера для просмотра запросов, которые делает страница, вы можете сформулировать что-то, что выполняет аналогичную последовательность, например так:

 import re from pprint import pprint import requests  sess = requests.Session() sess.headers["User-Agent"] = "Mozilla/5.0 Safari/537.36"  # Do initial GET request, grab CSRF token resp = sess.get("https://chartink.com/screener/90dis") resp.raise_for_status() csrf_token_m = re.search(r'lt;meta name="csrf-token" content="(. ?)" /gt;', resp.text) csrf_token = csrf_token_m.group(1)  # Do data query resp = sess.post(  "https://chartink.com/screener/process",  data={  "scan_clause": "( {cash} ( latest count( 90, 1 where latest ha-low gt; latest ichimoku cloud top( 9 , 26 , 52 ) ) = 90 ) )",  },  headers={  "Referer": "https://chartink.com/screener/90dis",  "x-csrf-token": csrf_token,  "x-requested-with": "XMLHttpRequest",  }, ) resp.raise_for_status() data = resp.json() pprint(data)  

Это выводит, например

 {'data': [{'bsecode': None,  'close': 18389.5,  'name': 'NIFTY100',  'nsecode': 'NIFTY100',  'per_chg': 1.28,  'sr': 1,  'volume': 0},  {'bsecode': '532978',  'close': 18273.8,  'name': 'Bajaj Finserv Limited',  'nsecode': 'BAJAJFINSV',  'per_chg': 2.25,  'sr': 2,  'volume': 207802},  ...  

Комментарии:

1. Большое спасибо @AKX. Мне придется много исследовать, чтобы полностью понять предложенное вами решение. Как будто я понятия не имею, что такое токен csrf? 🙂 Я попытался изучить код веб-страницы с помощью инструмента веб-разработчика, но не смог понять, как отображается таблица данных. Является ли это кодом Javascript в atlas.js? Я не смог понять, где искать запросы, которые делает веб-страница. Это где-то на вкладке «Инспектор» инструмента веб-разработчика?

2. Хорошо, я думаю, что понял, где искать запросы, которые делает эта страница. Инструменты веб-разработчика — gt; Консоль -gt;gt; GEThttps://chartink.com/screener/90dis. Но как вы вычислили код «sess.post (…». Как вы нашли строку запроса («scan_clause»)?

3. Зависит от вашего браузера. В моем Chrome это находится в подтаблице полезной нагрузки. Вы также можете щелкнуть правой кнопкой мыши запрос и «Скопировать как выборку», чтобы получить вызов Javascript, который вы можете перевести на Python.

4. Большое спасибо @AKX. Я узнал, где искать запрос на публикацию в Firefox.

5. Я пытался реализовать приведенный выше код с помощью torpy, но получаю ошибку. Я создал объект objTorRequest = TorRequests() TorRequests, а затем извлек объект сеанса objTorSession = objTorRequest.get_session() , а затем вызвал функцию get objTorResponse = objTorSession.get("https://chartink.com/") . Но я получаю ошибку «AttributeError: объект _GeneratorContextManager’ не имеет атрибута «get»». Есть идеи, в чем причина этого?