"آن کس که نداند و بداند که نداند" هستم
کتابخانه سلنیوم چیه و چیکار میکنه؟(قسمت دوم)
سلام بر همگی
توی این قسمت میخوایم کمی بیشتر با کتابخانه سلنیوم آشنا شویم.
اگر با کتابخانه requests کار کرده باشید، شما فقط صحنه را میبینید و خبری از پشت صحنه ندارید. منظورم از پشت صحنه، صفحه وبسایت هست. یعنی اگر با کتابخانه requests به یک سایت درخواست بدهید، نمیتوانید ببینید که سایت در چه صفحه ای هست... نمیتوانید ببینید آیا متن های سایت تغییر کرده یا نه... فقط و فقط میتوانید درخواست بدهید و نتیجه رو در قالب کد html ببینید.
اما کتابخانه سلنیوم کاملا با کتابخانه requests فرق دارد. در سلنیوم هم صحنه معلومه هم پشت صحنه. یعنی یک صفحه مرورگر باز میشود(کروم، فایرفاکس و...)، آدرسی که شما دادید رو سرچ میکنه و کاری که بهش گفتید رو براتون انجام میده. شما همه این کار ها رو به چشم میبینید تا اگر اشتباهی پیش اومده بود، سریع متوجه شوید. البته که سلنیوم از requests کندتره. ولی قابلیت هایی سلنیوم به ما میده، راحت تر هستن.
نکته : توی سلنیوم، چیزی به نام driver وجود داره که مثل یه browser معمولی میمونه با این تفاوت که به ما اجازه جستجو توی اینترنت رو میده. وقتی میخواهیم driver هارو از کتابخانه سلنیوم import کنیم، به این صورت مینویسیم:
from selenium import webdriver
در مرحله بعدی driver مون رو انتخاب میکنیم. یعنی انتخاب میکنیم که driver مون فایرفاکس باشه یا کروم یا ...
ما کروم رو انتخاب میکنیم:
path = "path/chromedriver.exe"
driver = webdriver.Chrome(path)
حواستون باشه که path رو بهش بدین. منظورم از path، آدرس فایل driver کروم هست.
از اینجا میتوانید دانلودش کنید.
تا اینجای که چیز خاصی نگفتیم. حالا میخوایم با انجام یک کار، کلیت کار رو متوجه بشیم. پروژه ای که میخوایم انجام بدیم، اینه که با استفاده از کتابخانه selenium وارد سایت دیجی کالا بشیم و یه گوشی ارزون قیمت بخریم:
خب بیاید کارهایی که باید برای رسیدن به این عزیز انجام بدیم رو لیست کنیم:
- به صفحه خرید این محصول در دیجیکالا برویم.
- این محصول رو به سبد خریدمان اضافه کنیم.
- وقتی صفحه ورود دیجیکالا بالا آمد، آنرا پر کنیم و وارد شویم.
- وارد صفحه "آدرس و زمان ارسال" شویم و محل تحویل کالا رو مشخص کنیم.
- نزدیک ترین زمان تحویل کالا رو مشخص کنیم.
- در صفحه پرداخت، گزینه پرداخت در محل را انتخاب کنیم.
- دکمه ثبت سفارش را میزنیم و تمام!
خب بریم کدش رو بزنیم:
به صفحه خرید این محصول در دیجیکالا برویم.
برای انجام این کار، از کتابخانه سلنیوم، webdriver رو فراخوانی میکنم.
from selenium import webdriver
حالا کروم رو به عنوان driver مون انتخاب میکنم.
path = 'chromedriver.exe'
driver = webdriver.Chrome(path)
در مرحله بعدی باید وارد صفحه کالا بشیم. پس در متغییر product_url، آدرس صفحه محصولمون رو میذاریم.
product_url = "https://www.digikala.com/product/dkp-2062198/%DA%AF%D9%88%D8%B4%DB%8C-%D9%85%D9%88%D8%A8%D8%A7%DB%8C%D9%84-%D8%A7%D9%BE%D9%84-%D9%85%D8%AF%D9%84-iphone-11-a2223-%D8%AF%D9%88-%D8%B3%DB%8C%D9%85-%DA%A9%D8%A7%D8%B1%D8%AA-%D8%B8%D8%B1%D9%81%DB%8C%D8%AA-128-%DA%AF%DB%8C%DA%AF%D8%A7%D8%A8%D8%A7%DB%8C%D8%AA"
و در مرحله بعدی با استفاده از دستور زیر وارد صفحه محصول میشویم:
driver.get(product_url)
وقتی کدمون رو اجرا کنیم، با همچین چیزی مواجه میشیم:
میبینید که یه صفحه دقیقا شبیه کروم باز میشه ولی هیچکدوم از اطلاعات شما درونش نیست. اگر یک بار دیگه واردش بشید، تاریخچه(history) پاک میشه. یه چیزی شبیه incognito کروم هست. با این تفاوت که میتوانید اون رو با پایتون کنترل کنید.
این محصول رو به سبد خریدمان اضافه کنیم.
ما برای اینکه این محصول رو به سبد خریدمون اضافه کنیم، باید چیکار کنیم؟
جوابش خیلی ساده ست. باید روی دکمه "افزودن به سبد خرید" کلیک کنیم. حالا این رو چطوری به سلنیوم بفهمونیم؟ برای اینکه بفهمیم که چطوری به سلنیوم همچنین چیزی رو بفهمونیم، باید یه چیزایی رو بدونیم.
شبه زبان html و ویژگی های اون
ما انسان ها خوندن و نوشتن بلدیم و هوش داریم. برای همین میتونیم بفهمیم که اگر روی دکمه "افزودن به سبد خرید"، کلیک کنیم، چه اتفاقی می افته. پس ما بیشتر اوقات از روی متن دکمه، متوجه کارایی اون میشیم.
ولی کامپیوتر همچنین هوشی نداره(البته میتونه داشته باشه ولی توی این کار، اصلا بهینه نیست). پس باید به زبان خودش، جایگاه دکمه رو بهش بگیم.
3 کلید ctrl + shift + i رو همزمان با هم فشار میدهیم. با یه همچنین صفحه ای روبرو میشیم(inspect):
همونطور که میبینید سمت راست کد های html و css صفحه برای ما نمایش داده میشود. اگر یه نگاهی به هر کدام از tag ها بندازید، متوجه میشوید که تقریبا همهشان دارای attribute(صفت) هستند. یا دارای id هستند یا دارای class یا...
از روی این ویژگی ها میتوانیم به کامپیوتر بفهمانیم که منظورمان کجا و چی هست. پس دنبال اون قسمت از کد میگردیم که مربوط به دکمه "افزودن به سبد خرید" هست.
3 کلید ctrl + shift + c رو همزمان با هم فشار میدهیم و بعد روی دکمه "افزودن به سبد خرید" کلیک میکنیم:
همونطور که کد هارو میبینید، قسمت انتخاب شده مربوط به جایی هست که ما رویش کلیک کردیم. یعنی همان دکمه "افزودن به سبد خرید".
به صفت class دکمه یه نگاهی بی اندازید. حدود 5 تا class داره(اگر درست گفته باشم). اولیشو کپی میکنیم و به کار قبلی مان ادامه میدیم.
آخرین کدی که زده بودیم این بود:
from selenium import webdriver
import time
path = 'chromedriver.exe'
driver = webdriver.Chrome(path)
product_url = "https://www.digikala.com/product/dkp-2062198/%DA%AF%D9%88%D8%B4%DB%8C-%D9%85%D9%88%D8%A8%D8%A7%DB%8C%D9%84-%D8%A7%D9%BE%D9%84-%D9%85%D8%AF%D9%84-iphone-11-a2223-%D8%AF%D9%88-%D8%B3%DB%8C%D9%85-%DA%A9%D8%A7%D8%B1%D8%AA-%D8%B8%D8%B1%D9%81%DB%8C%D8%AA-128-%DA%AF%DB%8C%DA%AF%D8%A7%D8%A8%D8%A7%DB%8C%D8%AA"
driver.get(product_url)
حالا باید با استفاده از سلنیوم، دکمه ای رو با کلاس btn-add-to-cart انتخاب میکنیم:
button = driver.find_element_by_class_name("btn-add-to-cart")
با کد بالا، دکمه مورد نظر رو پیدا میکنیم. حالا باید رویش کلیک کنیم:
button.click()
بعد از اجرای کد بالا با همچنین چیزی مواجه میشویم:
حالا باید روی دکمه "ادامه فرآیند خرید" کلیک کنیم. مثل قبل صفت class اون رو پیدا میکنیم و کد زیر رو مینویسیم:
button = driver.find_element_by_class_name("o-btn")
button.click()
وقتی کد بالا رو اجرا میکنیم، ارور دریافت میکنیم:(
چرا باید ارور بگیریم؟ ارور به ما میگه که سلنیوم نمیتونه مشخص کنه که اونجایی که ما مشخص کردیم دقیقا کجاست.
این ارور معمولا یه دلیل داره. دلیلش اینه که یک tag دیگه توی این صفحه وجود داره که class ش برابر o-btn هست. برای همین نمیدونه باید کدوم رو انتخاب کنه. اینجا یه چیز جدید میاد و دستمون رو میگیره.
با استفاده از xpath بدون نیاز به class و id و... میتونید جای دقیق یک تگ رو مشخص کنید.
به این صورت xpath یک تگ رو پیدا میکنید:
مثل بالا، با استفاده از ctrl + shift + c تگ دکمه رو پیدا میکنیم. بعد از آن روی تگ کلیک راست میکنیم. بعدش از آن روی گزینه "Copy" کلیک میکنیم. در آخر هم روی گزینه "Copy Xpath" کلیک میکنیم.
مثل این باید باشه :
//*[@id="cart-data"]/div[1]/div[1]/aside/div/div[1]/ul/li[4]/a
وارد پایتون میشویم و کد زیر رو وارد میکنیم:
time.sleep(5)
driver.find_element_by_xpath('//*[@id="cart-data"]/div[1]/div[1]/aside/div/div[1]/ul/li[4]/a').click()
شاید براتون سوال باشه که چرا من از دستور time.sleep استفاده کردم؟
جوابش اینه که اینکار رو کردم که صفحه به صورت کامل لود بشه و بعد بره سراغ بقیه کار ها. اگر صفحه به صورت کامل لود نشود و ما کاری رو انجام بدیم(مثلا یک فرم رو پر کنیم و اینتر رو بزنیم)، کاری انجام نمیشه و شاید ارور هم بده.
حالا اگر کد رو اجرا کنیم، با همچین چیزی روبرو میشیم:
تا اینجای کار تونستیم به صفحه ورود دیجیکالا برسیم.
وقتی صفحه ورود دیجیکالا بالا آمد، آنرا پر کنیم و وارد شویم.
حالا باید فرم ورود دیجیکالا رو پر کنیم. برای اینکار باز هم مثل قبل باید با استفاده از class یا id یا xpath یا... تگ input مربوط به صفحه ورود رو پیدا کنیم.
با استفاده از ctrl + shift + i وارد کد سایت میشویم و سپس ctrl + shift + c را فشار میدهیم. بعد از آن فیلد "شماره موبایل یا پست الکترونیک" را انتخاب میکنیم.
همونطور که میبینید، کد خاکستری رنگ، مربوط به فیلد "شماره موبایل یا پست الکترونیک" است. صفت name این تگ، برابر "login[email_phone]" است. میتونیم با استفاده از name تگمان، آن را پیدا و سپس پر کنیم.
email = "a.jalali2005@gmail.com"
field = driver.find_element_by_name('login[email_phone]')
حالا باید عبارتی که داخل متغییر email هست را به تگ input صفحه بفرستیم. برای این کار از کد زیر استفاده میکنیم:
field.send_keys(email)
دستور send_keys میتواند مقداری را که دریافت میکند، به تگ مورد نظرمان بفرستد. البته تگ حتما باید آن چیز را قبول کند. مثلا نمیتوان مقدار "سلام" رو به یک تگ بفرستید که اصلا ورودی نداره(مثل <p>).
پس از اینکه ایمیل را به تگ مربوطه ارسال کردیم، باید دکمه "ادامه" را بزنیم.
برای اینکار xpath آن را پیدا میکنیم و با استفاده از دستور click() روی آن کلیک میکنیم.
driver.find_element_by_xpath('//*[@id="loginForm"]/button').click()
حالا که روی دکمه ادامه کلیک کردیم، وارد صفحه رمزعبور میشویم:
باید رمزعبورمان رو وارد کنید و بعدش دکمه ورود رو بزنیم. پس کدش رو میزنیم:
time.sleep(2)
password = "********"
driver.find_element_by_name('login[password]').send_keys(password)
driver.find_element_by_xpath('//*[@id="authForm"]/button').click()
و بعد بالاخره به صفحه طلایی میرسیم:
همونطور که میبینید، توی دکمه قرمز رنگ، متن "برای ادامه، زمان ارسال تعیین کنید" را نوشته است. دقیقا رسیدیم به طولانی ترین جا:)
باید همه روز هارو از اول تا آخر چک کنیم که آیا تکمیل شده اند یا نه. پس از اون، نزدیک ترین روز رو انتخاب میکنیم و ادامه میدهیم.
البته این قسمت از ماجرا برای قسمت بعدی این آموزش هست.
آخرین بروزرسانی : امروز
مطلبی دیگر از این انتشارات
چگونه مسائل را با یادگیری عمیق حل کنیم ؟
مطلبی دیگر از این انتشارات
آینده از آن بات ها است
مطلبی دیگر از این انتشارات
مکعب داده در علم داده چیست؟