Я хочу проанализировать количество подписчиков на сайте с BeautifulSoup. Это то, что я до сих пор:

username_extract = 'lazada_my'

url = 'https://www.instagram.com/'+ username_extract
r = requests.get(url)
soup = BeautifulSoup(r.content,'lxml')
f = soup.find('head', attrs={'class':'count'})

Это часть, которую я хочу разобрать:

enter image description here

Что-то в моей функции soup.find () неверно, но я не могу обернуть голову вокруг этого. При возврате f он пуст. Есть идеи, что я делаю не так?

3
calicationoflife 1 Мар 2018 в 09:31

5 ответов

Лучший ответ

Я думаю, что вы можете использовать повторно модуль для поиска правильного количества.

import requests
import re

username_extract = 'lazada_my'

url = 'https://www.instagram.com/'+ username_extract
r = requests.get(url)
m = re.search(r'"followed_by":\{"count":([0-9]+)\}', str(r.content))
print(m.group(1))
3
William Feirie 1 Мар 2018 в 07:01

soup.find('head', attrs={'class':'count'}) ищет что-то похожее на <head class="count">, которого нет нигде в HTML. Данные, которые вы ищете, содержатся в теге <script>, который начинается с window._sharedData:

script = soup.find('script', text=lambda t: t.startswith('window._sharedData'))

Оттуда вы можете просто удалить назначение переменной и точку с запятой, чтобы получить действительный JSON:

# <script>window._sharedData = ...;</script>
#                              ^^^
#                              JSON

page_json = script.text.split(' = ', 1)[1].rstrip(';')

Разберите его, и все, что вам нужно, содержится в объекте:

import json

data = json.loads(page_json)
follower_count = data['entry_data']['ProfilePage'][0]['user']['followed_by']['count']
2
Blender 1 Мар 2018 в 07:04

Вы должны искать scripts, а затем искать 'window._sharedData' выходы в нем. Если выход, то выполните операцию регулярного выражения.

import re

username_extract = 'lazada_my'
url = 'https://www.instagram.com/'+ username_extract
r = requests.get(url)
soup = BeautifulSoup(r.content,'lxml')
s = re.compile(r'"followed_by":{"count":\d*}')
for i in soup.find_all('script'):
     if 'window._sharedData' in str(i):
         print s.search(str(i.contents)).group()

< Сильный > Результат

"followed_by":{"count":407426}
0
Rahul K P 1 Мар 2018 в 06:59

Большая часть контента генерируется динамически с помощью JS. Вот почему вы получаете пустые результаты.

Но счет followers присутствует в источнике страницы. Единственное, он не доступен напрямую в той форме, которую вы хотите. Вы можете видеть это здесь:

<meta content="407.4k Followers, 27 Following, 2,740 Posts - See Instagram photos and videos from Lazada Malaysia (@lazada_my)" name="description" />

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

>>> followers = soup.find('meta', {'name': 'description'})['content']
>>> followers
'407.4k Followers, 27 Following, 2,740 Posts - See Instagram photos and videos from Lazada Malaysia (@lazada_my)'
>>> followers_count = followers.split('Followers')[0]
>>> followers_count
'407.4k '
1
Keyur Potdar 1 Мар 2018 в 07:08

Спасибо всем, я в конечном итоге использовал решение Уильяма. На случай, если у кого-нибудь появятся будущие проекты, вот мой полный код для сбора нескольких URL для подсчета подписчиков:

import requests
import csv 
import pandas as pd
import re

insta = pd.read_csv('Instagram.csv')

username = []

bad_urls = [] 

for lines in insta['Instagram'][0:250]:
    lines = lines.split("/")
    username.append(lines[3])

with open('insta_output.csv', 'w') as csvfile:
t = csv.writer(csvfile, delimiter=',')     #   ----> COMMA Seperated
for user in username:
   try:
       url = 'https://www.instagram.com/'+ user
       r = requests.get(url)
       m = re.search(r'"followed_by":\{"count":([0-9]+)\}', str(r.content))
       num_followers = m.group(1)
       t.writerow([user,num_followers])    #  ----> Adding Rows
   except:
       bad_urls.append(url)
0
calicationoflife 1 Мар 2018 в 07:18