ویکی‌پدیا (Wikipedia) یک دانشنامهٔ اینترنتی چندزبانه با محتوای آزاد است که با همکاری افراد داوطلب نوشته می‌شود و هر کسی که به اینترنت دسترسی داشته باشد می‌تواند مقالات آن را ویرایش کند. نام ویکی‌پدیا واژه‌ای ترکیبی است که از واژه‌های ویکی (وبگاه مشارکتی) و اِنسایکلوپدیا (Encyclopedia) (دانشنامه یا دائرةالمعارف) گرفته شده‌است. هدف ویکی‌پدیا آفرینش و انتشار جهانی یک دانشنامهٔ آزاد به تمامی زبان‌های زندهٔ دنیا است.

امروزه ویکی پدیا یکی از مهمترین منبع های داده بر روی وب است که می توانیم برای یادگیری مفاهیم متفاوت، از آن استفاده کنیم. با اینکه ویکی پدیا منبعی مناسبی برای ارجاع در پژوهش ها، پایانامه ها و نوشتارها (مقاله ها) نیست، ولی بازهم نقش مهمی را در یادگیری مفاهیم متفاوت ایفا می کند. در این مطلب می خواهیم یاد دهیم چگونه به داده های درون جدول های ویکی پدیا دسترسی داشته باشید. همچنین در مطلب های پیش رو و به روش های متفاوت (API ویکی پدیا در پایتون و زبان Sparql) به شما چگونگی بدست آوردن داده های ویکی پدیا را آموزش داده ایم.

متد ()findAll در کتابخانه bs4

در مطلب  در مورد متد ()find و چگونگی دسترسی به یک تگ ویژه بوسیله نام و خصوصیت های آن تگ، را آموزش دادیم. به طور معمول دو پارامتر به متد ()find فرستاده می شوند که پارامتر نخست رشته ای است که نام تگ را مشخص می کند و پارامتر دوم دیکشنری است که کلیدهای آن نام خصوصیت تگ و مقدار کلید، برابر با مقداری است که برای خصوصیت انتظار داریم. متد ()find تنها یک تگ و به عبارت بهتر نخستین تگ مطابق با ورودی هایش را بر می گرداند.

در این مطلب می خواهیم متد دیگری به نام ()findAll را برای دسترسی به تمامی تگ های ویژه مانند تگ table یا img درون صفحه وب را آموزش دهیم. به صور نمونه می خواهیم تمامی تگ های td درون یک تگ table پیدا شده را بدست آوریم. برای این منظور ابتدا از متد ()find استفاده می کنیم تا به جدولی با class با مقدار wikitable sortable پیدا کنیم و سپس توسط متد ()findAll تمامی تگ های td را پیدا کنیم.

پیش از هر چیز و مطابق کدهای زیر باید محتوای صفحه را از روی وب بخوانیم و سپس یک نمونه از کلاس BeautifulSoup ایجاد کرده و در نهایت توسط متد ()find تگ table با کلاس با مقدار wikitable sortable را پیدا کنیم. همچنین چهار متغیر به نام های name و brith_date و country و launch_date را ایجاد کرده ایم که به ترتیب مقدار ستون های مرتبط با خود را برای هر سطر نگه می دارند.

توجه کنید که متیغر launch_date به صورت یک لیست است زیرا ممکن است یک فضانورد چندین بار پرتاپ به فضا داشته باشد. پس از کدهای بالا و تنها برای آزمایش و بدست آوردن آنچه که می خواهیم بدست آوریم، (نام، کشور و تاریخ پرواز) مطابق کدهای زیر می خواهیم به ازای هر تگ tr (هر سطر)، تمامی تگ های (ستون های) آنها را پیدا کنیم. در کدهای زیر می بینید از متد ()findAll همراه با رشته tr در یک حلقه for استفاده کردیم تا در هر تکرار و به اندازه تمامی تگ های tr، ستون های آن، یعنی تگ های td در متغیر cols ذخیره شوند. توجه کنید جدول فهرست فضانواردن این مطلب دارای ۶ ستون است، پس مطابق شکل زیر متغیر cols دارای ۶ عنصر (اندیس صفرتا ۵) است.

در شکل بالا و در جدول مربوط به زنان فضا نورد، در هر تگ tr، شش ستون (تگ td) وجود دارد که با اندیس های صفر تا شش در هر گام حلقه for درون متغیر cols ریخته می شوند. حال در کدهای زیر که بازنویسی شده کد بالا است، توسط متد ()find و ()findAll می خواهیم متغیرهایی را که در بالا ایجاده کرده بودیم را مقدار دهی کنیم. توجه کنید که چون ستون Name، سومین ستون در جدول است، پس با اندیس 2 به آن دسترسی پیدا کرده ایم. اگر به شکل بالا دقت کنید می بینید که یک لیست خالی وجود دارد، پس با شرط خط ۴ از کد زیر (بررسی برابر بودن اندازه متغیر cols با عدد ۶) ، از آن صرف نظر کرده ایم.

در کدهای بالا از خصوصیتی به نام text استفاده کرده ایم تا بتوانیم متن را از درون تگ td بدست آوریم. همچنین در خط ۷ و چون چندین تاریخ پرواز (پرتاپ به فضا) وجود دارد، دوباره از ()findAll به همراه پارامتر text=True استفاده کرده ایم تا بتوانیم متن های درون تگ td مربوط به تاریخ پرتاپ را بدست آوریم ولی یک مشکل پیش آمده است و اینکه در لیست برگشتی از متد ()findAll رشته های غیر تاریخ نیز وجود دارند. اگر به شکل بالا دقت کنید می بینید رشته تاریخ به صورت نوع تاپل (Tuple) است. کاری که باید انجام دهیم این است که تنها لیستی ایجاد کنیم که شامل این تاپل ها باشد. البته ممکن است شما بخواهید دیگر رشته ها را که محل پرتاپ است را نیز نگه دارید، پس در این صورت دیگر نیازی به حذف رشته های محل پرتاپ نیست

توجه کنید این مطلب تنها در مورد جدول فهرست فضانوردان خانم است و قرار نیست دیگر جدول های مورد دلخواه شما در ویکی پدیا ریز گام های بالا را دنبال کنند بلکه آنچه که گفته ایم جنبه سراسری دارد ولی تفاوت هایی نیز در مورد جدول های ویکی پدیا وجود دارد. همچنین نباید ریز گام های بالا را حتما برای دیگر جدول ها در نظر بگیرید، بلکه آنچه که مهم است اینکه باید به صورت تکرار بر روی سطرها (تگ tr) به مقدارهای ستون ها (تگ های td) دسترسی داشته باشید.

روشی دیگر و متد ()find_all

در این بخش می خواهیم به گونه دیگری گام های بالا را دنبال کنیم تا بتوانیم داده های ستون های هر سطر جدول را به درستی و به سادگی بدست آوریم و همچنین متد ()find_all را نیز آموزش دهیم. در کدهای زیر و یکباره و تنها در یک خط و به صورت مجزا توسط متدهای ()findAll و ()find_all تمامی سطرهای جدول دلخواه را در متغیرهای all_tr_tags_from_table1 و all_tr_tags_from_table2 ذخیره کرده ایم. همانطورکه در شکل زیر می بینید نوع برگشتی هر دو، به صورت لیست های پایتون است.

در کدهای بالا کار ویژه ای را انجام نداده ایم بلکه تنها در یک خط و بوسیله متد ()findAll یا متد ()find_all تمامی تگ های tr جدولی را بدست آورده ایم که خود این جدول را از طریق نام class آن و بوسیله متد ()find بدست آورده ایم. در کدهای بالاتر این کار را به صورت متفاوت و در چندین خط مجزا از هم انجام داده بودیم.

پس از آنکه تگ های tr را بدست آوردیم باید توسط کدهای زیر و در غالب یک حلقه for، تمامی ستون های هر سطر را بدست آوریم. توجه کنید برگشتی کدهای بالا یک list پایتون است، پس می توانیم حلقه for را اجرا کنیم. همچنین در کدهای زیر متن درون تگ های td در غالب یک لیست تازه به نام cols گردآوری می شود.

در شکل و کد بالا می بینید که درون حلقه for دوباره از متد ()find_all برای بدست آوردن تمامی تگ های td کمک گرفته شده است. همچنین از شکل مشخص است که در لیست های برگشتی کاراکترهای نادرست و نامناسبی مانند کاراکترهای n\ و xa0/ وجود دارند که باید آنها رابه کمک کد بازنویسی شده زیر پاک کنیم. در کد زیر متغیر counter شماره لیست برگشتی را نشان می دهد و چون جدول مورد نظر ما دارای ۶۲ سطر است، پس مقدار این متغیر نیز در پایان ۶۲ خواهد بود.

دانلود سورس برنامه های این مطلب findAll and find_all methods in bs4

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