CoderCastrov logo
CoderCastrov
Питон

Парсинг Instagram с помощью Python (используя Selenium и Beautiful Soup)

Парсинг Instagram с помощью Python (используя Selenium и Beautiful Soup)
просмотров
3 мин чтение
#Питон
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 в коммерческих целях).

    Спасибо за чтение, и я надеюсь, что вы найдете эту статью полезной. Если у вас есть вопросы, я с удовольствием обсужу их.

    Основная архитектура этого кода основана на информации из этих двух ресурсов -