Quiero analizar los seguidores de un sitio web con BeautifulSoup. Esto es lo que tengo hasta ahora:

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'})

Esta es la parte que quiero analizar:

enter image description here

Algo dentro de mi función soup.find () está mal, pero no puedo entenderlo. Al regresar f, está vacío. ¿Alguna idea de lo que estoy haciendo mal?

3
calicationoflife 1 mar. 2018 a las 09:31

5 respuestas

La mejor respuesta

Creo que puede usar el módulo re para buscar el recuento correcto.

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 mar. 2018 a las 07:01

soup.find('head', attrs={'class':'count'}) busca algo que se parece a <head class="count">, que no existe en ninguna parte del HTML. Los datos que busca están contenidos en la etiqueta <script> que comienza con window._sharedData:

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

A partir de ahí, puede quitar la asignación de variables y el punto y coma para obtener un JSON válido:

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

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

Analízalo y todo lo que necesitas está contenido en el objeto:

import json

data = json.loads(page_json)
follower_count = data['entry_data']['ProfilePage'][0]['user']['followed_by']['count']
2
Blender 1 mar. 2018 a las 07:04

Tienes que buscar las scripts, luego busca las salidas 'window._sharedData' en él. Si sale, realice la operación de expresión regular.

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()

Resultado,

"followed_by":{"count":407426}
0
Rahul K P 1 mar. 2018 a las 06:59

La mayor parte del contenido se genera dinámicamente con JS. Esa es la razón por la que obtienes resultados vacíos.

Pero, el recuento followers está presente en la fuente de la página. Lo único es que no está disponible directamente en la forma que desea. Puedes verlo aqui:

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

Si desea raspar el recuento de seguidores sin expresiones regulares, puede usar esto:

>>> 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 mar. 2018 a las 07:08

Gracias a todos, terminé usando la solución de William. En caso de que alguien tenga proyectos futuros, aquí está mi código completo para extraer un montón de URL para su conteo de seguidores:

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 mar. 2018 a las 07:18