ماژول BeautifulSoup که در حال حاظر نسخه ۴ آن وجود دارد یکی از چندین ماژول پایتونی است که برای web scraping و web crawling استفاده می شود. BeautifulSoup که آنرا از این پس bs4 می نامیم برای بدست آوردن داده ها از فایل های html و xml استفاده می شود.

bs4 برای انجام عملکرد خود و بدست آوردن داده های وب، مبتنی بر یک سری اصطلاحا parser  است که هر یک برای بدست آوردن داده ها از فرمت های مختلف html و xml استفاده می شوند. به وطر مثال برای کار بر روی html یک parser پیشفرض به نام html.parser وجود دارد ولی در حال حاظر به وجود html5 یک parser دیگر به نام html5lib نیز وجود دارد. برای نصب آن در محیط مجازی virtualenv باید از دستورهای زیر استفاده کنید.

اولین برنامه وب اسکرپینگ با bs4

نخستین گام در وب اسکرپینگ باز کردن صفحه وب و خواندن و دریافت محتوای آن است که مطابق مطلب های پیشین برای این منظور از ماژول urllib.request استفاده می کنیم. در نهایت باید کلاس BeautifulSoup از ماژول bs4 را مطابق کد زیر به درون برنامه ضمیمه کنید.

پس از ضمیمه کردن ماژول ها باید توسط متد ()urlopen از ماژول urllib.request محتوای آدرس صفحه وب مورد نظر را خوانده و درون یک متغیر ذخیره کنید. به طور مثال می خواهیم محتوای آدرس https://python.org را بخوانیم و محتوای آنرا درون متغیر response ذخیره کنیم و در نهایت محتوای آنرا توسط متد ()read از شی response نشان دهیم.

پس از دریافت محتوای صفحه وب باید ابتدا یک شی از کلاس BeautifulSoup ایجاد کنیم در این مطلب آنرا soup نامگذاری کرده ایم. کلاس BeautifulSoup دارای متدهای گوناگون برای کاربردهای متفاوت است. یکی از این متدها ()pertify است که محتوای متغیر response را که شامل تگ های html می شود را به صورت مرتب و قابل خوانده شدن ساده تر نمایش می دهد .

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

نمایش کدهای html صفحه وب

برای انجام وب اسکرپینگ باید بتوایند سورس صفحه وب را بخوانید، به عبارت دیگر باید درون تگ های html بگردید تا با ساختار و نام شناسه ها و class های آن آشنا شوید تا در نهایت از این نام ها درون ابزارهای ماژول bs4 استفاده کنید تا به محتوای وب دسترسی پیدا کنید. برای این منظور از در کرروم با راست کلیک کردن روی صفحه و انتخاب Inspect ، می توانید کدهای html صفحه وب را مشاهده کنید. همچنین برای آگاهی در مورد دیگر مرورگرها می توانید اینجا را بخوانید.

شکل زیر کدهای html صفحه hhtps://python.org را نشان می دهد. فرض کنید می خواهید تمامی فایل های css درون صفحه را دانلود کنید، پس ابتدا باید تمامی تگ های link دسترسی داشته باشید و سپس مقدار خصوصیت href آن که به فایل css اشاره می کند را دریافت و در نهایت آنرا درون سیستم فایل (دیسک) ذخیره کنیم. برای این کار باید گام های زیر را انجام دهیم:

۱ – دسترسی به تمامی تگ های link که در بخش head قرار دارند.

۲ – دسترسی به فایل یا آدرس فایل css که خصوصیت href به این فایل یا آدرس اشاره می کند.

۳ – احتمالا بررسی اینکه آیا پسوند فایل بدست آمده css است (در این مورد در مطلب تجزیه URL مولفه ها توسط پایتون و urllib.parse صحبت شده است و در ادامه مطلب ها مجدد به آن اشاره می کنیم)

۴ – استفاده از تابع ()open پایتون برای نوشتن محتوای فایل های css بر روی دیسک

همانطور که گفتیم اگر فرض کنیم نام شی که از کلاس BeautifulSoup ایجاد کردیم را soup نامگذاری کرده باشیم، پس می توانیم از طریق خصوصیت title و به صورت soup.title یا soup.title.string به عنوان صفحه دسترسی داشته باشیم. بنابراین احنمالا می توانیم مطابق کد زیر و توسط خصوصیت link تمامی تگ های link را درون یک متغیر ذخیره کنیم.

در خروجی دستورهای بالا و مطابق شکل زیر می بینید که تنها یکی و در واقع اولین تگ link از میان تمامی تگ های درون بخش head در متغیر all_link_tags ذخیره شده اند. بنابراین نتیجه می گیریم که خصوصیت هایی مانند link, title یا حتی img که در ادامه مثالی از آن گفته ایم، تنها و تنها اولین تگ معادل خودشان را از میان تمامی تگ های معادل دیگر برگشت می دهند.

دسترسی به خصوصیت های تگ ها

در شکل زیر می بینید که نوع متغیر all_link_tags از نوع کلاس bs4.element.Tag است و از این رو می توانیم همانند قطعه کد زیر به خصوصیت تگ ها دسترسی پیدا کنیم. به طور مثال می خواهیم خصوصیت href از تگ link را که شامل فایل یا مسیر (آدرس URL) فایل های css است. همانطور که می بینید نام خصوصیت به صورت یک رشته و به عنوان کلید تعیین شده است.

دانلود نشان واره (لوگو) سایت https://python.org

در این بخش و به عنوان جمع بندی می خواهیم تصویر نشان واره (لوگو) سایت https://python.org را دانلود کنیم، پس باید تگ img که مسیر فایل تصویر را در خود دارد را پیدا و سپس مقدار خصوصیت src آن خوانده شود و در نهایت توسط تابع ()open از پایتون تصویر را درون دیسک ذخیره کنیم. برای این منظور اگر از کروم استفاده می کنید روی صفحه راست کلیک و سپس Inspect را انتخاب کنید و توسط گزینه Select Element روی تصویر بروید تا مطابق شکل زیر تگ (img) مربوط به آن در قسمت پایینی نشان داده می شود. همچنین همانطور که می بینید وقتی روی تصویر بروید، نام تگ و نام کلاس آن به صورت img.python-logo نشان داده می شود.

اگر در شکل بالا دقت کنید می بینید که تگ img که تصویر نشان واره (لوگو) سایت را نگه می دارد، اولین تگ img در بخش body کدهای html صفحه است، پس می توانیم به آن از طریق کد soup.img دسترسی داشته باشیم. همچنین چون می خواهیم فایل را ذخیره کنیم پس در نهایت باید توسط دستور زیر به مقدار خصوصیت src از تگ img دسترسی پیدا کنیم.

در شکل زیر خروجی دستور بالا نشان داده شده است و می بینید که مسیر برگشتی فاقد آدرس دامنه سایت است، پس در کدهای زیر ابتدا این دامنه را به مسیر اضافه می کنیم و سپس توسط متد ()urlopen آنرا خوانده و در نهایت توسط تابع ()open و به صورت wb (یعنی write binary) فایل تصویر را در دایرکتوری جاری (جایی که کد وجود دارد) ذخیره می کنیم.