TL;DR
Добавьте user-agent в заголовок запроса на получение в строке 20:
r = s.get(link, headers={'User-Agent': 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10r = s.get(link, headers={'User-Agent': 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10_7_3 rv:3.0; sl-SI) AppleWebKit/533.38.2 (KHTML, like Gecko) Version/5.0 Safari/533.38.2'})
3 rv:3.0; sl-SI) AppleWebKit/533.38.2 (KHTML, like Gecko) Version/5.0 Safari/533.38.2'})
Длинный ответ
Если мы посмотрим на сообщение об ошибке, которое вы опубликовали, мы сможем начать анализировать, что пошло не так. Строка 21 пытается найти атрибут csrf_token на странице входа в Instagram а>.
Диагностика
Из сообщения об ошибке видно, что индекс списка выходит за пределы диапазона, что в данном случае означает, что список, возвращенный re.findall
(docs) пуст. Это означает, что либо
- Ваше регулярное выражение неверно
- HTML-код, возвращенный вашим запросом на получение (документы)
r = s.get(link)
в строке 20, не содержит атрибут csrf_token
- Атрибут не существует в исходном html
Если мы зайдем на страницу и посмотрим на ее html-код, мы увидим, что атрибут csrf_token действительно присутствует в строке 261:
<script type="text/javascript">window._sharedData = {"config":{"csrf_token":"TOKEN HERE","viewer":null,"viewerId":null}}</script>
Обратите внимание: для краткости я исключил остальную часть кода.
Теперь, когда мы знаем, что он присутствует на странице, мы можем записать очищенный HTML-код, который вы получаете через запрос на получение, в локальный файл и проверить его:
r = s.get(link)
with open("csrf.html", "w") as f:
f.write(html)
Если вы откроете этот файл и нажмете Ctrl+f для csrf_token, его не будет. Вероятно, это означает, что Instagram обнаружил, что вы заходите на страницу через парсер, и вернул измененную версию страницы.
Исправление
Чтобы исправить это, вам нужно добавить пользовательский агент в заголовок вашего запроса, который по существу «обманывает» страницу, заставляя ее думать, что вы обращаетесь к ней через браузер. Это можно сделать, изменив:
r = s.get(link)
к чему-то вроде этого:
r = s.get(link, headers={'User-Agent': 'Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10_7_3 rv:3.0; sl-SI) AppleWebKit/533.38.2 (KHTML, like Gecko) Version/5.0 Safari/533.38.2'})
Обратите внимание, что это случайный пользовательский агент из здесь.
Заметки
Я понимаю, что вы не хотите использовать селен для своей задачи, но вы можете обнаружить, что чем больше динамических взаимодействий вы хотите сделать, тем сложнее добиться этого с помощью статических библиотек очистки, таких как модуль запросов. Вот несколько хороших ресурсов для изучения селена в питоне:
Документация по Selenium
Руководство по Python Selenium №1 – Парсинг веб-страниц, боты и тестирование
28.03.2021