Как парсить несколько фотографий/видео в одном посте в инстаграме на python?
Хочу извлечь линки всех изображений с ссылки, но у меня возникла проблема с извлечением информации с тега script
Код вот:
import requests
import json
from bs4 import BeautifulSoup as BS
import re
# Ссылка на полную страницу
url = 'https://www.instagram.com/p/B5n2EXjF_1C/'
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like
Gecko) Chrome/83.0.4103.116 Safari/537.36'}
r = requests.get(url, headers=headers, allow_redirects=True)
soup = BS(r.content, 'html.parser')
script = soup.find('script', attrs={'type':"text/javascript"}, text=re.compile('window._sharedData'))
data = json.loads(script.next)
image_url = data['display_url']
print(image_url)
Вот ошибка:
Traceback (most recent call last): File "C:/Users/Desktop/test/venv/Test.py", line 19, in data = json.loads(script.next) File "C:\Users\AppData\Local\Programs\Python\Python38-32\lib\json\__init__.py", line 357, in loads return _default_decoder.decode(s) File "C:\Users\AppData\Local\Programs\Python\Python38-32\lib\json\decoder.py", line 337, in decode obj, end = self.raw_decode(s, idx=_w(s, 0).end()) File "C:\Users\AppData\Local\Programs\Python\Python38-32\lib\json\decoder.py", line 355, in raw_decode raise JSONDecodeError("Expecting value", s, err.value) from None json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
Не сильно умею работать с типами js, но если есть у кого-то желание и время помочь,буду вам очень признателен!
Ответы (1 шт):
Автор решения: gil9red
→ Ссылка
Изменения:
- Вместо
script.nextиспользовалscript.text - Добавил в регулярку правила захвата куска js
- Добавил извлечение куска js (
search(...).group(1))
Попробуйте:
import datetime as DT
import json
import re
import sys
from bs4 import BeautifulSoup as BS
import requests
JS_SHARED_DATA_PATTERN = re.compile('window._sharedData = ({.+});')
# Ссылка на полную страницу
url = 'https://www.instagram.com/p/B5n2EXjF_1C/'
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36'}
r = requests.get(url, headers=headers)
soup = BS(r.content, 'html.parser')
script = soup.find('script', attrs={'type':"text/javascript"}, text=JS_SHARED_DATA_PATTERN)
print(script)
# <script type="text/javascript">window._sharedData = {"config":{"csrf_tok ...
print(script.text)
# window._sharedData = {"config":{"csrf_token":"RtSXgxK6b0Lh4Ag3wSFRebLUfdJRA9qc","viewer":null, ...
# FIX: Если script имеет содержимое, а script.text возвращает пустую строку, то
# в регулярку можно отдавать str(script), т.е.: JS_SHARED_DATA_PATTERN.search(str(script))
# В bs4 версии 4.7.1 проблемы не было, а в 4.9.1 уже есть
m = JS_SHARED_DATA_PATTERN.search(script.text)
if not m:
print(f'Not found "window._sharedData = "!')
sys.exit()
shared_data_text = m.group(1)
print(shared_data_text)
# {"config":{"csrf_token":"RtSXgxK6b0Lh4Ag3wSFRebLUfdJRA9qc","viewer":null,"viewerId":null},"country_code": ...
data = json.loads(shared_data_text)
print(data)
# {'config': {'csrf_token': 'RtSXgxK6b0Lh4Ag3wSFRebLUfdJRA9qc', 'viewer': None, 'viewerId': None}, 'country_code': ...
Я бы еще добавил дамп html, что не прошли проверку, это полезно для разбора ошибок, например:
import datetime as DT
...
m = JS_SHARED_DATA_PATTERN.search(script.text)
if not m:
file_name_dump = str(DT.datetime.now()).replace(':', '') + '.html'
with open(file_name_dump, 'wb') as f:
f.write(rs.content)
print(f'Not found "window._sharedData = ", see: {file_name_dump}!')
sys.exit()
Без bs4:
import datetime as DT
import json
import re
import sys
import requests
JS_SHARED_DATA_PATTERN = re.compile('window._sharedData = ({.+});')
# Ссылка на полную страницу
url = 'https://www.instagram.com/p/B5n2EXjF_1C/'
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36'}
r = requests.get(url, headers=headers)
m = JS_SHARED_DATA_PATTERN.search(r.text)
if not m:
print(f'Not found "window._sharedData = "!')
sys.exit()
print(shared_data_text)
data = json.loads(shared_data_text)
print(data)