آنالیز کردن اکانت های اینستاگرام (بات برای اینستاگرام)

ربات‌های زیادی برای اینستاگرام ساخته شده که کارهایی مثل لایک کردن، ریکوست دادن و ... انجام می‌دهد. برای این کارها سایت‌هایی هست که خدمات رو ارائه میده هم کلی مطلب هست که چجوری برای خودتون رو بسازید. البته که کلا اینستاگرام استفاده از این ربات‌ها رو ممنوع کرده و باهاش سعی کرده مقابله‌هایی انجام بده ولی به صورت گسترده هنوز استفاده میشه. هدف این مقاله ولی یکم متفاوت‌تر از ساخت ربات برای کار‌های بالا هست.


هدف اصلی اینه که بتونیم اسکریپتی با پایتون بنویسیم که اکانت‌های مختلف اینستاگرام رو آنلایز کنه. مثلا تعداد پست‌ها، تعداد لایک‌ها هر پست، روند پست گذاشتن پیج‌های مختلف و ... را آنلایز کرد. تو چند مقاله‌ای که بعدا همین جا لینکشو اضافه میکنم نتایجی که از آنلایز شرکت‌های بزرگ استارت‌آپی ایران انجام دادم رو می‌نویسم.



خوب اول از همه پکیج هایی که لازم هست رو نصب کنیم. برای شروع کار نیاز به selenium برای رفتن به اکانت اینستاگرام و خارج کردن دیتا داریم و برای تحلیل کردن دیتا و جمع کردن دیتا به pandas نیاز داریم، که با استفاده از pip میتونیم هر دوی آن ها رو نصب کنیم.

from selenium import webdriver
import pandas as pd

پس از نصب پکیج‌ها برای کار با سلنیوم باید درایور بروزر مورد نظرتون نصب کنید. برای این مقاله از فایرفاکس استفاده شد که برای دانلود کردن درایور آن می‌تونید به اینجا برید.

قدم بعدی ساختن اکانت اینستاگرام است،‌ که از این لینک می‌تونید استفاده کنید. سپس، با استفاده از تابع زیر وارد اینستاگرام می‌شوید. ( بهتر است از اکانت شخصی خودتون استفاده نکنید)

def login_instagram(username, password):
    driver = webdriver.Firefox() 
    driver.get(&quothttps://instagram.com&quot)
    time.sleep(4)
    driver.find_element_by_xpath(&quot//input[@name=\&quotusername\&quot]&quot).send_keys(username) 
    driver.find_element_by_xpath(&quot//input[@name=\&quotpassword\&quot]&quot).send_keys(password)
    driver.find_element_by_xpath('//button[@type=&quotsubmit&quot]').click()
    time.sleep(10)
    driver.find_element_by_xpath(&quot//button[contains(text(), 'Not Now')]&quot).click()
    return driver

driver = login_instagram(username, passrword)

در تابع ۲ قسمت اسلیپ اسلیپ وجود دارد که برای لود شدن کامل صفحه استفاده شده‌است. اگر سرعت اینترنتون پایین تر بود این تایم‌ها رو می‌توانید بیشتر کنید، البته کار‌های بهتری هم می‌شد انجام داد که مطمئن بشیم صفحه کامل لود شده باشد ولی پیچیدگی کار رو بیشتر می‌کرد.

در ادامه با استفاده از کلاسی که تعریف می‌کنیم به پیج‌های مختلف می‌ریم و تعداد پست‌ها، تعداد دنبال‌کننده و تعداد دنبال‌شونده هر پیج رو بدست میاریم. بعد هم با لود کردن کل پست‌ها لینک هر پست رو بدست میاریم.

در قسمت اول پارامتر هایی که لازم داریم بدست بیاریم رو تعیین می‌کنیم. برای هر پیج همان‌طور که بالا گفتیم ۴ تا پارامتر بدست میاوریم، ۳ تای آن ها عددی و یکی از آن ها دیتابیس است. num_post نشان دهنده تعداد پست‌ها، num_follwors و num_following نشان دهنده دنبال شوندگان و دنبال کنندگان است. برای بدست آوردن این اعداد از ۳ تابع n_followrs ،n_post و n_following استفاده شده‌است. که در هر ۳ تابع برای پیدا کردن عدد از آدرس xpath استفاده شده‌.


نمیش اینستاگرام در دو سایز صفحه
نمیش اینستاگرام در دو سایز صفحه


تغییر سایز صفحه‌ای که در init نیز انجام شد برای این است که نمایش پست در اندازه صفحه‌های مختلف اینستاگرام نمایش مختلفی دارد. برای این که xpath های تکرار پذیری بتوانیم استفاده کنیم گفتیم یک اندازه صفحه را به عنوان مبنا در نظر بگیریم.

class anayles_post:
    def __init__(self, driver, page_name):
        self.driver = driver
        self.page_name = page_name
        self.num_posts = None
        self.num_followrs = None
        self.num_following = None
        self.data_set = pd.DataFrame(columns=['url'])
        self.driver.get(f&quothttps://instagram.com/{page_name}&quot) # go to page
        self.driver.set_window_size(800, 500)

    def get_header_data(self, xpath):
        elemnt_find = self.driver.find_elements_by_xpath(xpath=xpath)[0]
        data_inheader = elemnt_find.get_attribute(&quottitle&quot)
        if len(data_inheader) == 0:
            data_inheader = elemnt_find.text
        return int(data_inheader.replace(',',''))
    def n_posts(self):
            posts_xpath = &quot/html/body/div[1]/section/main/div/header/section/ul/li[1]/span/span&quot
            self.num_posts = self.get_header_data(num_posts_xpath)
            return self.num_posts
    def n_followrs(self):
        num_followrs_xpath = 
         &quot/html/body/div[1]/section/main/div/header/section/ul/li[2]/a/span&quot
        self.num_followrs = self.get_header_data(num_followrs_xpath)
        return self.num_followrs
    def n_following(self):
        following_xpath =  &quot/html/body/div[1]/section/main/div/header/section/ul/li[3]/a/span&quot
        self.num_following = self.get_header_data(num_following_xpath)
        return self.num_following
    def url_all_posts(self):
        page_height = 0
        self.driver.execute_script(f&quotwindow.scrollTo(0, {page_height})&quot)
        if self.n_posts() > 0:         # Check hilight
            xpath = '/html/body/div[1]/section/main/div/div[3]/article/div[1]/div/div/div'
            list_post = self.driver.find_elements_by_xpath(xpath=xpath)
            if len(list_post) == 0:
                xpath = '/html/body/div[1]/section/main/div/div[2]/article/div[1]/div/div/div'          
        while len(self.data_set) < self.n_posts() :
            xpath = xpath
            list_post = self.driver.find_elements_by_xpath(xpath=xpath)
            for this_post in list_post:
                herf_this_post = this_post.find_elements_by_xpath('a')
                if len(herf_this_post) > 0:
                    herf_this_post = herf_this_post[0].get_attribute('href')
                    check_this_link = self.data_set[self.data_set['url'] == herf_this_post]
                    if check_this_link.empty:
                        self.data_set = self.data_set.append(pd.DataFrame(data={'url':[herf_this_post]}))
            page_height += 1000
            self.driver.execute_script(f&quotwindow.scrollTo(0, {page_height})&quot)
            time.sleep(1)
        self.data_set.reset_index(inplace=True)
        return self.data_set


در ادامه کد تابع url_all_posts لینک تمامی پست‌های گذاشته شده رو به یک دیتابیس اضافه می‌کند، برای این کار نیاز داریم صفحه رو اسکرول کنیم به سمت پایین تا پست‌های قدیمی‌تر لود شوند. هر بار که صفحه لود می‌شود قسمتی از پست‌های قبلی هم باقی می‌ماند برای همین چک می‌کنیم که لینک تکراری در دیتابیس نریخته باشیم.

برای اجرای تابع‌های بالا نیاز به اجرای آن‌ها است.

username = &quotYOUR_USERNAME&quot
password = &quotYOUR_PASSWORD&quot
driver = login_instagram(username, password)
page_name = &quotPAGE_NAME&quot
page_instagram = anayles_post(driver=driver, page_name=page_name)
print('Number of Posts : ', page_instagram.n_posts())
print('Number of Following : ', page_instagram.n_following())
print('Number of Followers :', page_instagram.n_followers())
data_set_page = page_instagram.url_all_posts()

که خروجی آن تعداد پست‌ها، دنبال‌کنندگان و دنبال شوندگان را می‌دهد.

همین قسمت کد را می‌توان به صورت روزانه یا ساعاتی برای پیج‌هایی که می‌خواهید دیتای آن ها را بررسی کنید اجرا کنید و خروجی را بر روی دیتابیسی بریزید. (مثلا برای قرار داد بستن با پیج اینفلوئنسر مورد نظرتون نیاز دارید نرخ افزایش دنبال‌کنندگان آن‌ها را بررسی کنید.)

خوب تا اینجای کار می‌تونیم تعداد این عدد‌ها رو برای هر پیجی بدست بیاوریم، به عنوان مثال در تاریخ ۲۷ مرداد ۱۴۰۰ برای صفحه digikala.life این اعداد به این صورت است :

پس از این که لینک همه‌ی پست‌ها رو بدست آوردیم نیاز داریم که لینک‌ها رو باز کنیم و اعدادی مثل تعداد کامنت و تاریخ اشتراک گذاری را بدست آوریم.برای این کار یک کلاس تعریف می‌کنیم که به صورت زیر است، همان طور که پیش‌بینی می‌شود این قسمت از کار برای این که نیاز هست تک‌ تک صفحات باز شود زمان‌بر است ( البته در ادامه میگیم چجوری می‌شه کل این پروسه رو سریع‌تر انجام داد.)

from selenium.common import exceptions
from datetime import datetime, timedelta
class post_analyse:
    def __init__(self, url, driver):
        self.driver = driver
        self.driver.get(f&quot{url}&quot)
        time.sleep(1)
    def post_content(self):
        try:
            self.driver.find_element(By.TAG_NAME, 'video')
            content = 'video'
        except exceptions.NoSuchElementException:
            content = 'photo'
        return content
    def post_action(self):
        page_source = self.driver.page_source 
        if 'views' in page_source:
            action = 'views'
        else:
            action = 'likes'
        return action
    def xpath_action(self, action):
        if action == 'views':
            xpath = '/html/body/div[1]/section/main/div/div[1]/article/div[3]/section[2]/div/span/span'
        else:
            xpath = '/html/body/div[1]/section/main/div/div[1]/article/div[3]/section[2]/div/div/a/span'
        return xpath    
    def post_time(self):
        xpath_date = '/html/body/div[1]/section/main/div/div[1]/article/div[3]/div[2]/a/time'
        time_posted = self.driver.find_elements_by_xpath(xpath=xpath_date)[0].text
        if 'AGO' in time_posted:
            if 'DAYS' in time_posted:
                days_ago = int(time_posted.split(' ')[0])
                time_posted = datetime.now().date() - timedelta(days=days_ago)
            else:
                # else means (x hours ago, x seconds ago, ...)
                time_posted = datetime.now()
        else:
            try:
                time_posted = datetime.strptime(time_posted, '%B %d, %Y').date()
            except ValueError:
                time_posted = datetime.strptime(time_posted, '%B %d').date()
                time_posted = time_posted.replace(year=datetime.now().year)
        return time_posted    
    def post_action_count(self, action):
        self.driver.set_window_size(1000, 500)
        xpath = self.xpath_action(action)
        n_action = self.driver.find_elements_by_xpath(xpath=xpath)
        if len(n_action) > 0:
            n_action = int(n_action[0].text.replace(',',''))
        else:
            n_action = 0
        return n_action

خوب اول از همه بررسی می‌کنیم که پست گذاشته شده دارای چه محتوایی است (ویدیو یا تصویر). این کار رو با تابع post_content انجام‌ می‌دهیم. روش کار هم به این صورت است که سورس کد صفحه باز شده دارای المنت video است یا خیر. در تابع بعدی اکشنی که انجام شده‌است را پیدا می‌کنیم. معمولا برای پست‌های تصویر تعداد لایک‌های زده شده گزارش می‌شود و برای فیلم‌ها تعداد دیده شدن ( البته برای فیلم‌هایی که در چند صفحه گذاشته می‌شوند تعداد لایک‌ها زده می‌شود). برای پیدا کردن اکشن انجام شده از تابع post_action استفاده می‌کنیم. مانند تابع قبلی در سورس کد دنبال آن می‌گردیم.

تابع بعدی xpath_action است که برای بدست آوردن xpath محلی که تعداد لایک یا ویوو زده شده است تعریف کردیم، که در post_action_count استفاده شده‌. یک تابع هم برای بدست آوردن تایم گذاشتن پست تعریف کردیم (post_time) که ۲ قسمت بودن آن به دلیل نمایش تاریخ زیر پست‌ها می‌باشد. اگر پست در ۷ روز اخیر گذاشته شده باشد به صورت DAYS AGO زده می‌شود و اگر قدیمی‌تر باشد تاریخ آن را می‌زند. برای این که همه‌ی فرمت‌ها به یک شکل شود همه را به صورت yyyy-mm-dd تبدیل کردیم.

قسمت بعدی لازمه دیتابیس url ها رو توی یک لوپ قرار بدیم که برای هر پست این دیتا‌ها رو بدست بیاوریم. برای قرار دادن پانداس داخل لوپ از روش‌های مختلفی میشه استفاده کرد ( یه مقاله خیلی خوب اینجاست) ولی از اون‌جایی که تعداد پست‌های هر پیج عدد خیلی زیادی نیست از یک for استفاده می‌کنیم.

data_set_page = pd.concat([data_set_page,pd.DataFrame(columns=['content', 'action', 'num_action', 'time'])])
for this_num_post in range(len(data_set_page)):
    this_post = post_analyse(data_set_page['url'][this_num_post], driver)
    data_set_page['content'][this_num_post] = this_post.post_content()
    data_set_page['action'][this_num_post] = this_post.post_action()
    data_set_page['num_action'] = this_post.post_action_count(data_set_page['action'][this_num_post])
    data_set_page['time'] = this_post.post_time()

برای همون صفحه digikala.life که بالا بررسی کرده‌بودیم به این صورت است.

این مرحله از کار همونجوری که گفتیم زمان‌بر ترین بخش است، برای این که سریع‌تر انجام بدیم می‌تونیم تنظیمات driver را به گونه‌ای تنظیم کنیم که عکس‌ها و ویدیو‌ها لود نشود. (البته میتوان به صورت کلی headless هم اجرا کرد driver را) برای این کار این قسمت کد را به تابع login_instagram اضافه می‌کنیم.

firefox_profile = webdriver.FirefoxProfile()
firefox_profile.set_preference('permissions.default.image', 2)
firefox_profile.set_preference('dom.ipc.plugins.enabled.libflashplayer.so', 'false')    firefox_profile.set_preference('media.mp4.enabled', False)    
driver = webdriver.Firefox(firefox_profile=firefox_profile)


خوب چند تا پارامتر را به عنوان مثال تحلیل کنیم :

  • نسبت تعداد محتوای منتشر شده به صورت فیلم یا عکس:
  • تعداد لایک‌ها یا وییو‌ها برای پست‌ها:
برای پست‌های عکسی
برای پست‌های عکسی
برای پست‌های فیلم
برای پست‌های فیلم


  • 4 پستی که بیشترین تعداد لایک را داشتند:

۲ تا از محبوب ترین پست‌های گذاشته شده در مورد کار بانوان است.

محبوب ترین پست‌ها
محبوب ترین پست‌ها
  • تعداد پست‌های گذاشته شده در سال‌ها:
تعداد پست‌ها در سال
تعداد پست‌ها در سال




خوب مختصر استفاده‌ای که می‌شد از این قسمت انجام داد را با چند مثال توضیح دادیم، در مقاله بعدی ادامه‌ی دیتاهایی که می‌توانیم بدست بیاریم رو می‌بینیم ( مثل تعداد کامنت‌های گذاشته شده، هشتگ‌های زده شده، بار مثبت‌ یا منفی کامنت‌ها و ...). بعد از این که دیتا‌ها تکمیل شد به سراغ بررسی اینستاگرام چند شرکت بزرگ میریم.