Парсинг Instagram с помощью Python (используя Selenium и Beautiful Soup)
Table Of Content
Эта статья рассказывает о том, как парсить Instagram для загрузки изображений/получения информации о постах с публичной страницы профиля или хэштега. В коде используются и Selenium, и Beautiful Soup для парсинга изображений Instagram без необходимости предоставления данных учетной записи или аутентификационных токенов.
Установите Selenium с помощью pip и загрузите драйвер Chrome по следующей ссылке http://chromedriver.chromium.org/
2. Откройте веб-браузер: Selenium использует драйвер Chrome для открытия профиля с заданным именем пользователя (публичный пользователь). Например -
username='pickuplimes'
browser = webdriver.Chrome('/path/to/chromedriver')
browser.get('https://www.instagram.com/'+username+'/?hl=en')
Pagelength = browser.execute_script("window.scrollTo(0, document.body.scrollHeight);")
Если вы хотите открыть страницу хэштега -
hashtag='food'
browser = webdriver.Chrome('/path/to/chromedriver')
browser.get('[https://www.instagram.com/explore/tags/'+hashtag](https://www.instagram.com/explore/tags/'+hashtag))
Pagelength = browser.execute_script("window.scrollTo(0, document.body.scrollHeight);")
3. Разбор исходного HTML-кода страницы: Откройте исходную страницу и используйте Beautiful Soup для ее разбора. Пройдитесь по телу HTML-скрипта и извлеките ссылку для каждого изображения на этой странице и добавьте ее в пустой список 'links[]'.
**#Извлечение ссылок со страницы профиля пользователя**
links=[]
source = browser.page_source
data=bs(source, 'html.parser')
body = data.find('body')
script = body.find('script', text=lambda t: t.startswith('window._sharedData'))page_json = script.text.split(' = ', 1)[1].rstrip(';')
data = json.loads(page_json)
**#попробуйте использовать 'script.string' вместо script.text, если получите ошибку о выходе за границы индекса**for link in data['entry_data']['ProfilePage'][0]['graphql']['user']['edge_owner_to_timeline_media']['edges']:
links.append('[https://www.instagram.com'+'/p/'+link['node']['shortcode']+'/'](https://www.instagram.com'+'/p/'+post['node']['shortcode']+'/'))
**#попробуйте использовать ['display_url'] вместо ['shortcode'], если у вас нет ссылок**#Извлечение ссылок со страницы хэштега
links=[]
source = browser.page_source
data=bs(source, 'html.parser')
body = data.find('body')
script = body.find('script', text=lambda t: t.startswith('window._sharedData'))
page_json = script.text.split(' = ', 1)[1].rstrip(';')
data = json.loads(page_json)for link in data['entry_data']['TagPage'][0]['graphql']['hashtag']['edge_hashtag_to_media']['edges']:
links.append('[https://www.instagram.com'+'/p/'+link['node']['shortcode']+'/'](https://www.instagram.com'+'/p/'+post['node']['shortcode']+'/'))
Помните, что по умолчанию Selenium открывает только первую страницу. Если вы хотите прокрутиться по дополнительным страницам и получить больше изображений, разделите высоту прокрутки на число и запустите код разбора несколько раз. Это добавит новые ссылки с каждой страницы в список. Например, browser.execute_script(“window.scrollTo(document.body.scrollHeight/1.5, document.body.scrollHeight/3.0);”)
Обновление - Этот метод раньше работал для меня, но с новыми изменениями в Instagram мне не удалось получить больше 12 постов со страницы профиля.
Проверьте другие методы здесь https://dev.to/hellomrspaceman/python-selenium-infinite-scrolling-3o12
Столбцы, которые вы получаете, могут немного отличаться для страницы профиля пользователя и страницы хэштега. Проверьте столбцы и отфильтруйте то, что вам нужно.
5. Получите детали для каждого поста
Пройдитесь по каждой ссылке в списке и извлеките подробную информацию в pandas dataframe
result=pd.DataFrame()
for i in range(len(links)):
try:
page = urlopen(links[i]).read()
data=bs(page, ‘html.parser’)
body = data.find(‘body’)
script = body.find(‘script’)
raw = script.text.strip().replace(‘window._sharedData =’, ‘’).replace(‘;’, ‘’)
json_data=json.loads(raw)
posts =json_data[‘entry_data’][‘PostPage’][0][‘graphql’]
posts= json.dumps(posts)
posts = json.loads(posts)
x = pd.DataFrame.from_dict(json_normalize(posts), orient=’columns’)
x.columns = x.columns.str.replace(“shortcode_media.”, “”)
result=result.append(x) except:
np.nanresult = result.drop_duplicates(subset = ‘shortcode’)
result.index = range(len(result.index))
Вот пример вывода -
6. Загрузите изображения из pandas data frame: Используйте библиотеку requests для загрузки изображений из 'display_url' в pandas 'result' data frame и сохраните их с соответствующими shortcode в качестве имени файла.
import os
import requests
result.index = range(len(result.index))
directory="/directory/you/want/to/save/images/"
for i in range(len(result)):
r = requests.get(result['display_url'][i])
with open(directory+result['shortcode'][i]+".jpg", 'wb') as f:
f.write(r.content)
(Важное примечание: Помните, что нужно уважать права пользователей при загрузке защищенного авторским правом контента. Не используйте изображения/видео из Instagram в коммерческих целях).
Спасибо за чтение, и я надеюсь, что вы найдете эту статью полезной. Если у вас есть вопросы, я с удовольствием обсужу их.
Основная архитектура этого кода основана на информации из этих двух ресурсов -