Я пытаюсь очистить веб-сайт NSE для конкретной компании, на Python. Я пытаюсь это сделать, используя библиотеку requests
и соответствующий метод get()
. Это должно вернуть файл .html
, который я затем смогу использовать для дальнейшей обработки с помощью Beautiful Soup 4.
url = 'https://www.nseindia.com/get-quotes/equity?symbol=20MICRONS'
response = requests.get(url)
Однако это не дает ответа даже через несколько минут, а вместо этого приводит к сбою моей системы. Судя по вопросу, Запросы GET Python требуют много времени для ответа на некоторые запросы,
Сервер может разрешать только определенные строки пользовательского агента.
Я добавил строку пользовательского агента в headers
запроса следующим образом:
url = 'https://www.nseindia.com/get-quotes/equity?symbol=20MICRONS'
headers = {
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36",
}
response = requests.get(url, headers=headers)
Этот метод также не решил проблему, дав мне понять, что это вряд ли проблема с производительностью. Вместо этого я решил попытаться исправить это, используя другой метод, упомянутый в вышеупомянутом вопросе,
IPv6 не работает, но IPv4 работает
На самом деле это было так: когда я попытался запустить его в режиме IPv6, я получил ошибку.
$ curl --ipv6 -v 'https://www.nseindia.com/get-quotes/equity?symbol=20MICRONS'
* Could not resolve host: www.nseindia.com
* Closing connection
curl: (6) Could not resolve host: www.nseindia.com
Но и в этом случае режим IPv4 оказался не намного лучше.
$ curl --ipv4 'https://www.nseindia.com/get-quotes/equity?symbol=20MICRONS' # -v removed to focus on the error
curl: (92) HTTP/2 stream 1 was not closed cleanly: INTERNAL_ERROR (err 2)
Очевидно, что сайт также не поддерживает HTTP/"# м
2, и он, наконец, запустился при запуске с режимом HTTP/1.1.
curl --ipv4 -v 'https://www.nseindia.com/get-quotes/equity?symbol=20MICRONS' --http1.1
* Host www.nseindia.com:443 was resolved.
* IPv6: (none)
* IPv4: 184.29.25.143
* Trying 184.29.25.143:443...
* Connected to www.nseindia.com (184.29.25.143) port 443
* ALPN: curl offers http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* CAfile: /etc/ssl/certs/ca-certificates.crt
* CApath: none
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 / x25519 / RSASSA-PSS
* ALPN: server accepted http/1.1
* Server certificate:
* subject: C=IN; ST=Maharashtra; L=Mumbai; O=National Stock Exchange of India Ltd.; CN=www.nseindia.com
* start date: May 28 00:00:00 2024 GMT
* expire date: May 22 23:59:59 2025 GMT
* subjectAltName: host "www.nseindia.com" matched cert's "www.nseindia.com"
* issuer: C=US; O=DigiCert Inc; OU=www.digicert.com; CN=GeoTrust RSA CA 2018
* SSL certificate verify ok.
* Certificate level 0: Public key type RSA (2048/112 Bits/secBits), signed using sha256WithRSAEncryption
* Certificate level 1: Public key type RSA (2048/112 Bits/secBits), signed using sha256WithRSAEncryption
* Certificate level 2: Public key type RSA (2048/112 Bits/secBits), signed using sha1WithRSAEncryption
* using HTTP/1.x
> GET /get-quotes/equity?symbol=20MICRONS HTTP/1.1
> Host: www.nseindia.com
> User-Agent: curl/8.8.0
> Accept: */*
>
* Request completely sent off
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
Однако запрос cURL все еще не завершен. Затем я просмотрел вопросы, касающиеся самого веб-сайта NSE India , и нашел вопрос: Запросы Python получают код ответа 401 для веб-сайта NSE India,
Чтобы получить доступ к сайту NSE (api) несколько раз, затем установите файлы cookie в каждом последующем запросе.
по сути рекомендую добавить cookies
к запросу.
baseurl = 'https://www.nseindia.com/'
url = 'https://www.nseindia.com/get-quotes/equity?symbol=20MICRONS'
headers = {
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36',
'accept-language': 'en,gu;q=0.9,hi;q=0.8',
'accept-encoding': 'gzip, deflate, br'
}
session = requests.Session()
request = session.get(baseurl, headers=headers, timeout=5)
cookies = dict(request.cookies)
response = session.get(url, headers=headers, timeout=5, cookies=cookies)
Это решение по-прежнему сталкивалось с той же проблемой: запрос просто никогда не завершался. Этот вопрос был задан и дан ответ для NSE India API , и вполне понятно, что он не работает. Я также проверил, добавив заголовок Accept
согласно комментарию @GTK,
вам нужен заголовок
accept
[...]
url = 'https://www.nseindia.com/get-quotes/equity?symbol=20MICRONS'
headers = {
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36",
"Accept": "text/html"
}
response = requests.get(url, headers=headers)
К сожалению, это не влияет на проблему, возможно, потому, что для заголовка Accept
уже установлено значение */*
, что позволяет использовать любой тип MIME.
Как мне поступить в этой ситуации и почему это происходит. Действительно ли запрос настолько медленный или произошла какая-то ошибка?
@GTK У запросов уже нет заголовка accept
, включая text/html
?
это ваш пользовательский агент (Linux), попробуйте этот пользовательский агент Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36
возможно, сначала используйте DevTools в Chrome/Firefox, чтобы увидеть, какие заголовки отправляет реальный веб-браузер, и начните со всех заголовков из браузера. А позже вы сможете проверить, какие заголовки можно пропустить. Возможно, ему также придется вести себя как настоящий пользователь и сначала посетить главную страницу, чтобы получить файлы cookie, а затем использовать файлы cookie на следующих страницах. Но я думаю, что может быть и другая проблема - эта страница использует JavaScript для добавления некоторых элементов в HTML - поэтому, если вы планируете получать данные из HTML, тогда запросы могут быть бесполезны, и может потребоваться использование Selenium для управления реальным веб-браузером, который может запускать JavaScript.
Кстати: когда я использую DevTools (вкладка Network
), чтобы увидеть запрос, он показывает мне, что этот сервер использует HTTP/2
. Насколько я знаю, requests
не поддерживает HTTP/2
— и его нужно будет использовать httpx
. Но по-прежнему реальной проблемой является JavaScript, и даже httpx
не может ее решить.
Мне удалось получить ответ от сервера с другим заголовком User-Agent
(скорее всего, сервер занес в черный список некоторые конкретные пользовательские агенты):
import requests
url = "https://www.nseindia.com/get-quotes/equity?symbol=20MICRONS"
headers = {
"User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:126.0) Gecko/20100101 Firefox/126.0",
}
response = requests.get(url, headers=headers)
print(response.text)
Распечатки:
<!DOCTYPE html>
<html lang = "en">
<head>
<meta http-equiv = "Content-Type" content = "text/html; charset=utf-8" />
<meta http-equiv = "Content-Type" content = "text/html; charset=ISO-8859-1">
<meta http-equiv = "X-UA-Compatible" content = "IE=edge,chrome=1" />
<meta name = "viewport" content = "width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />
<title>
20 Microns Limited Share Price Today, Stock Price, Live NSE News, Quotes, Tips – NSE India
</title>
...
Этот заголовок User-Agent
работал, но откуда я мог знать, что это необходимое значение заголовка?
@Shirsak Нет документации - это метод проб и ошибок.
вам нужен заголовок
accept
иuser-agent
.