#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()
, а затем вызвал функцию getobjTorResponse = objTorSession.get("https://chartink.com/")
. Но я получаю ошибку «AttributeError: объект _GeneratorContextManager’ не имеет атрибута «get»». Есть идеи, в чем причина этого?