در این مطلب، الگوریتم و کد جمع کردن چند جمله ای ها همراه با ارائه مثالی بیان شده است؛ همچنین، کد جمع کردن دو چند جملهای در زبانهای برنامهنویسی «سیپلاسپلاس» (++C)، «جاوا» (Java)، «پایتون 3» (Python3)، «سیشارپ» (#C) , «پیاچپی» (PHP)ارائه شده است.
دو چند جملهای به صورت دو آرایه زیر تعریف شدهاند. هدف نوشتن تابعی است که بتواند دو چندجملهای داده شده را با یکدیگر جمع کند.
ورودیها:
A[] = {5, 0, 10, 6}
B[] = {1, 2, 4}
خروجی:
sum[] = {6, 2, 14, 6}
اولین آرایه ورودی، نشاگر «5 + 0x^1 + 10x^2 + 6x^3» و دومین آرایه، نشانگر «1 + 2x^1 + 4x^2» است. آرایه خروجی نیز نشانگر چندجملهای «6 + 2x^1 + 14x^2 + 6x^3» است.
جمع کردن دو چند جملهای، از ضرب کردن آنها سادهتر است. مقداردهی اولیه با یکی از دو چندجملهای انجام میشود، سپس، چند جملهای دیگر خوانده و همه عبارات آن به نتیجه، اضافه میشوند. الگوریتم مورد استفاده برای جمع کردن دو چند جملهای، به صورت زیر است.
افزودن ([A[0..m-1], B[0..n01)
در ادامه، پیادهسازی الگوریتم جمع کردن دو چند جملهای، در زبانهای برنامهنویسی گوناگون انجام شده است.
First polynomial is 5 + 0x^1 + 10x^2 + 6x^3 Second polynomial is 1 + 2x^1 + 4x^2 Sum polynomial is 6 + 2x^1 + 14x^2 + 6x^3
پیچیدگی زمانی الگوریتم و برنامه بالا، برابر با (O(m+n است که در آن، m و n به ترتیب مرتبه چند جملهایهای داده شده هستند.
در این مقاله برخی مفاهیم مهم مرتبط با برنامه نویسی ناهمگام و کارکرد آنها در مرورگرهای وب و جاوا اسکریپت را بررسی میکنیم. پس از مطالعه مقاله حاضر، این مفاهیم را درک خواهید کرد و آماده مطالعه بخشهای بعدی این سری مقالات آموزشی جاوا اسکریپت خواهید بود. همچنین برای مطالعه قسمت قبلی این مجموعه مطلب آموزشی میتوانید به مطلب «تمرین ساخت شیئ در جاوا اسکریپت (بخش دوم) — راهنمای کاربردی» مراجعه کنید.
به طور معمول کد یک برنامه به صورت خطی و مستقیم اجرا میشود و هر لحظه تنها یک کار در حال انجام است. اگر تابعی برای اجرا به نتیجه تابع دیگری نیاز داشته باشد، باید منتظر بماند تا تابع دیگر کار خود را تمام کرده و نتیجه را بازگشت دهد و تا زمانی که این اتفاق بیفتد، کل برنامه عملاً از نظر کاربر متوقف میشود.
برای نمونه کاربران Mac برخی اوقات این وضعیت را به شکل یک کرسر رنگینکمانی در حال چرخش تجربه میکنند. سیستم عامل با نمایش این کرسر در واقع اعلام میکند که برنامه کنونی که استفاده میکنید باید متوقف مانده و منتظر باشد تا چیز دیگری انجام یابد و این کار به مدتزمانی نیاز دارد و بدینوسیله اعلام میکنیم که جای نگرانی نیست و مشغول کار هستیم.

این تجربه ناخوشایندی است و استفاده مناسبی از توان پردازشی رایانه به خصوص در این عصر که رایانهها چندین هسته پردازشی دارند، به حساب نمیآید. این که منتظر بنشینیم تا کار دیگری پایان یابد، در حالی که میتوان آن را به هسته پردازشی دیگری واگذار کرد تا در زمان خاتمه کار به ما اطلاع دهد. بدین ترتیب میتوان کارها را به صورت همزمان پیش برد که اساس «برنامهنویسی ناهمگام» (asynchronous programming) را تشکیل میدهد. همه چیز به محیط برنامه که استفاده میکنید بستگی دارد تا با ارائه API–های مختلف امکان اجرای نامتقارن وظایف را فراهم سازد. در زمینه برنامهنویسی وب این محیط مرورگر وب است.
تکنیکهای ناهمگام در برنامهنویسی و به خصوص برنامهنویسی وب بسیار مهم هستند. زمانی که یک وب اپلیکیشن در مرورگر اجرا میشود و یک دسته کد سنگین را بدون بازگرداندن کنترل به مرورگر اجرا میکند، ممکن است این گونه به نظر برسد که مرورگر قفل شده است. این وضعیت «مسدودسازی» (blocking) نامیده میشود. در این حالت مرورگر نمیتواند ورودی کاربر را مدیریت و وظایف دیگر را اجرا کند و تا زمانی که کنترل از پردازنده به مرورگر بازنگردد تداوم خواهد داشت.
در ادامه به بررسی چند مثال میپردازیم تا معنی دقیق مسدودسازی را درک کنیم.
در این مثال (+) چنان که ملاحظه میکنید یک «شنونده رویداد» به دکمه اضافه شده است تا زمانی که دکمه کلیک میشود یک عملیات زمانگیر را اجرا کند. در این عملیات 10 میلیون تاریخ محاسبه میشود و نتیجه در کنسول نمایش پیدا میکند. سپس یک پاراگراف به DOM اضافه خواهد شد.
زمانی که این مثال را اجرا میکنید، کنسول جاوا اسکریپت را باز کنید و سپس روی دکمه کلیک کنید، متوجه خواهید شد که پاراگراف مزبور به جز تا زمانی که تاریخها محاسبه نشده باشند و پیام نهایی در کنسول نمایش نیافته باشد در صفحه ظاهر نمیشود. این کد به همان ترتیب که نوشته شده اجرا میشود و عملیات بعدی تا زمانی که عملیات قبلی به پایان نرسیده باشد اجرا نخواهد شد.
نکته: مثال قبلی بسیار غیر واقعگرایانه است. ما هرگز در یک وب اپلیکیشن یک میلیون تاریخ را محاسبه نمیکنیم. این مثال صرفاً جهت این ارائه شده است که ایده اولیهای از موضوع داشته باشید.
در مثال دوم (+) چیزی را شبیهسازی میکنیم که اندکی واقعگرایانهتر است و احتمال بیشتری برای دیدن آن در یک صفحه وب وجود دارد. ما تعاملپذیری کاربر را از طریق رندر کردن UI مسدود میکنیم. در این مثال دو دکمه داریم:
اگر دکمه اول را کلیک کنید و سپس به سرعت روی دکمه دوم کلیک نمایید، متوجه خواهید شد که هشدار تا زمانی که رندر شدن دایرهها به پایان نرسیده است، ظاهر نمیشود. عملیات نخست، عملیات دوم را مسدود میکند تا این که اجرایش به پایان برسد.
نکته: در این مورد کد زشت است و قصد ما صرفاً ایجاد حالت مسدودسازی بوده است، اما این مشکل رایجی است که توسعهدهندگان وباپلیکیشنهای واقعی همواره با آن دستبهگریبان هستند.
دلیل این وضعیت آن است که جاوا اسکریپت به بیان کلی یک زبان برنامهنویسی «تک نخی» (single threaded) است. در این مرحله ابتدا باید با مفهوم «نخ» (thread) در برنامهنویسی آشنا شویم.
نخ اساساً یک پردازش منفرد است که برنامه میتواند برای اجرای وظیفهای به خدمت بگیرد. هر نخ میتواند در هر زمان تنها یک وظیفه منفرد را اجرا کند:
Task A --> Task B --> Task C
هر وظیفه به صورت ترتیبی اجرا میشود و برای این که وظیفهای بتواند شروع شود باید وظیفه قبلی به پایان رسیده باشد.
چنان که پیشتر گفتیم، بسیاری از رایانهها در حال حاضر دارای پردازندههای چندهستهای هستند و از این رو میتوانند چندین کار را به طور همزمان اجرا کنند. زبانهای برنامهنویسی که میتوانند از چندین نخ پشتیبانی کنند، میتوانند برای اجرای وظایف به صورت همزمان چند هسته پردازشی را به کار بگیرند.
Thread 1: Task A --> Task B Thread 2: Task C --> Task D
جاوا اسکریپت به صورت سنتی یک زبان تک نخی است. حتی اگر چندین هسته پردازشی را به کار بگیرید، در هر حال باید وظایف را روی یک نخ منفرد اجرا کنید که «نخ اصلی» (main thread) نام دارد. بدین ترتیب مثال فوق به صورت زیر اجرا میشود:
Main thread: Render circles to canvas --> Display alert()
البته پس از مدتی جاوا اسکریپت از برخی ابزارها کمک گرفت تا چنین مشکلاتی را رفع کند. «وب ورکر» (Web worker) امکان ارسال چند پردازش جاوا اسکریپت به یک نخ جدا را که worker نام دارد فراهم میسازد. بدین ترتیب میتوان چندین دسته کد جاوا اسکریپت را به صورت همزمان اجرا کرد. به طور کلی از یک worker برای اجرای پردازشهای سنگین و برداشتن این وظیفه از دوش نخ اصلی استفاده میشود. بدین ترتیب تعامل کاربر با مرورگر مسدود نمیشود.
Main thread: Task A --> Task C Worker thread: Expensive task B
با در نظر داشتن این موضوع، نگاهی به این مثال (+) میاندازیم. کنسول مرورگر را باز نگهدارید. در واقع این مثال یک بازنویسی از مثال قبلی است که 10 میلیون تاریخ را در نخ worker جداگانهای اجرا میکرد. اکنون زمانی که روی دکمه کلیک کنید، مرورگر میتواند پاراگراف را پیش از اتمام محاسبه تاریخها نمایش دهد. به این ترتیب عملیات نخست موجب مسدود شدن عملیات دوم نمیشود.
وب ورکرها کاملاً مفید هستند، اما آنها نیز محدودیتهای خاص خود را دارند. مهمترین محدودیت وب ورکرها این است که نمیتوانند به DOM دسترسی داشته باشند. بنابراین نمیتوان انتظار داشت که یک وب ورکر مستقیماً کاری برای بهروزرسانی UI انجام دهد. ما نمیتوانیم 1 میلیون دایره آبی را درون worker رندر کنیم، چون وظیفه آن صرفاً محاسبات است.
دومین مشکل این است که گرچه کد در یک ورکر مسدودسازی ندارد، اما همچنان در ذات خود همگام است. این وضعیت در مواردی که تابعی به نتایج پردازشهای قبلی نیاز داشته باشد، مشکلساز خواهد بود. نمودارهای نخ زیر را در نظر بگیرید:
Main thread: Task A --> Task B
در این حالت، وظیفه A کاری مانند واکشی کردن یک تصویر از سرور را انجام میدهد و وظیفه B کاری مانند اعمال یک فیلتر را روی تصویر اجرا میکند. اگر ابتدا شروع به اجرای وظیفه A و سپس بیدرنگ شروع به اجرای وظیفه B بکنید، با خطایی مواجه خواهید شد، چون تصویر هنوز آماده نشده است.
Main thread: Task A --> Task B --> |Task D| Worker thread: Task C -----------> | |
در این حالت، فرض کنید وظیفه D از نتایج هر دو وظیفه B و C استفاده میکند. اگر بتوانیم تضمین کنیم که این نتایج هر دو به صورت همزمان آماده خواهند بود، در این صورت مشکلی وجود نخواهد داشت، اما چنین وضعیتی نامحتمل است. اگر وظیفه D تلاش کند زمانی که ورودیاش هنوز آماده نشده است، اجرا شود با خطا مواجه خواهد شد.
مرورگرها برای اصلاح چنین خطاهایی به ما اجازه میدهند که برخی عملیات را به صورت ناهمگام اجرا کنیم. قابلیتهایی مانند Promise-ها امکان تعیین حالت اجرایی برای یک عملیات (برای نمونه واکشی یک تصویر از سرور) و سپس صبر کردن برای بازگشت نتیجه تا پیش از اجرای عملیات بعدی را فراهم میسازند:
Main thread: Task A Task B Promise: |__async operation__|
از آنجا که عملیات در جای دیگری اتفاق میافتد، در زمانی که عملیات ناهمگام در حال پردازش است، نخ اصلی مسدود نمیشود. در بخش بعدی این سری مقالات آموزشی به بررسی روشهای نوشتن کدهای ناهمگام خواهیم پرداخت.
اصول طراحی مدرن نرمافزار به طور فزایندهای پیرامون استفاده از برنامهنویسی ناهمگام توسعه مییابند تا به برنامهها امکان اجرای همزمان چندین کار را بدهند. زمانی که از API-های مدرن و قدرتمندتر استفاده میکنید، مواردی بیشتری را خواهید یافت که تنها راه اجرای یک وظیفه برنامهنویسی ناهمگام است. نوشتن کد ناهمگام دشوارتر است و عادت کردن به آن به کمی زمان نیاز دارد، اما به مرور آسانتر خواهد شد. در بخشهای بعدی این سری مقالات آموزشی به بررسی بیشتر دلیل اهمیت کدهای ناهمگام و روشهای طراحی کد که از بروز مشکلات مطرح شده در این مقاله جلوگیری میکنند خواهیم پرداخت. برای مطالعه بخش بعدی به لینک زیر رجوع کنید:
منبع: فرادرس
زمانی که بخواهیم اطلاعاتی در مورد کاربران یک وبسایت ذخیره کنیم، سیستم ورود و ثبت نام کاربر بسیار مفید خواهد بود. این موضوع در مورد همه وبسایتها از وبسایتهای آموزشی که میتوانند روند پیشرفت کاربر در طی دوره آموزشی را ذخیره کنند و به آن نمره بدهند تا وبسایتهای فروشگاهی که اطلاعاتی در مورد خریدهای گذشته مشتری ذخیره میکنند کاربرد دارد. در این راهنما، روش ایجاد فرم ورود و ثبت نام کاربر را از صفر تا صد با هم مرور خواهیم کرد.
نخستین گام، ساخت خود فرم ورود و ثبت نام است. این فرمها در واقع بسیار ساده هستند. فرم ثبت نام تنها نام کاربری، ایمیل و رمز عبور کاربر را میپرسد. نام کاربری و ایمیل برای همه افرادی که میخواهند ثبت نام کنند باید یکتا باشند. اگر هر کس تلاش کند با استفاده از آدرس ایمیل مشابهی دو حساب باز کند، یک پیام خطا به وی نمایش داده میشود که این ایمیل قبلاً استفاده شده است.
در ادامه کد HTML فرم ثبت نام را میبینید. شما باید آن را در فایلی به نام register.php ذخیره کنید:
این فرم کاملاً ابتدایی است، اما در آن از HTML5 استفاده کردهایم تا برخی اعتبارسنجیهای بسیار مقدماتی ورودی را اجرا کنیم. برای نمونه استفاده از “type=”email به کاربران هشدار میدهد که آدرس ایمیلی که وارد کردهاند دارای قالببندی صحیح نیست. به طور مشابه، استفاده از خصوصیت pattern روی نام کاربری موجب میشود مطمئن شویم در نام کاربری تنها کاراکترهای حرف و رقم وجود دارند.
در ادامه کد HTML فرم ورود را مشاهده میکنید. این کدها را در فایلی به نام login.php قرار دهید:
در ادامه برخی کدهای CSS را میبینید که روی این فرمها اعمال میشوند:
این فایل شامل برخی قواعد استایلدهی برای نمایش پیامهای خطا و عناوین است. کدهای HTML و CSS که در این بخش ارائه شدند میتوانند به عنوان مبنایی برای پروژه شما جهت ایجاد فرمهای اختصاصی استفاده شوند و ممکن است استایلدهی و فیلدهای ورودی متفاوتی داشته باشند.

گام بعدی ایجاد یک جدول کاربر است که همه اطلاعات را در مورد کاربران ثبت نام کرده ذخیره میکند. در این مورد جدول صرفاً شامل چهار ستون به این صورت خواهد بود: یک ستون برای شناسه با افزایش خودکار، یک نام کاربری یکتا، یک ایمیل و یک رمز عبور
میتوان از گزارههای SQL زیر برای ایجاد سریع جدول استفاده کرد:
سپس یک فایل به نام config.php ایجاد کرده و کدهای زیر را در آن مینویسیم تا به پایگاه داده وصل شویم:
نام پایگاه داده را در کد فوق به نام پایگاه دادهای که استفاده میکنید تغییر دهید. از این فایل برای برقراری یک اتصال به پایگاه داده استفاده میشود.
در نهایت زمان آن فرا میرسد که کارکرد ثبت نام را بنویسیم. تابع اصلی این کد به بررسی سوابق ثبت نام قبلی ایمیل ارائه شده میپردازد. اگر چنین نباشد، نام کاربری، ایمیل و رمز عبور را در پایگاه داده وارد میکنیم.
کد زیر را در فایل registration.php قرار دهید:
گام نخست این است که فایل config.php را بگنجانیم و یک «نشست» (Session) را آغاز کنیم. این فرایند به ما کمک میکند هر اطلاعاتی را که میخواهیم روی صفحههای مختلف به آن دسترسی داشته باشیم ذخیره کنیم.
سپس با وارسی تعیین شدن متغیر [‘POST[‘register_$، بررسی میکنیم که آیا کاربر روی دکمه Register کلیک کرده و فرم را تحویل داده است یا نه. همواره به یاد داشته باشید که ذخیرهسازی رمزهای عبور به صورت متن ساده ایده بدی است. به همین دلیل از تابع ()password_hash استفاده میکنیم. سپس هش محاسبه شده را در پایگاه داده خود ذخیره میکنیم. این تابع خاص یک هش 60 کاراکتری را با استفاده از salt محاسبه شده به صورت تصادفی ایجاد میکند.
در نهایت کوئری را اجرا میکنیم و بررسی میکنیم آیا هیچ ردیف غیر صفر برای آن آدرس ایمیل وجود دارد یا نه. اگر وجود داشته باشد پیامی به کاربر نمایش خواهیم داد که این آدرس ایمیل قبلاً در این وبسایت ثبت نام کرده است.
اگر هیچ ردیفی با مشخصه آدرس ایمیل ارائه شده موجود نباشد، اطلاعات عرضه شده را در پایگاه داده وارد میکنیم و به کاربر اطلاع میدهیم که ثبت نام موفق بوده است.
در آخرین گام از مراحل طراحی فرمهای ورود و ثبت نام، کدی را مینویسیم که باعث میشود کاربران بتوانند در سایت لاگین کنند. این بار کافی است اطلاعات موجود در پایگاه داده را بررسی کنیم تا ببینیم آیا ترکیب نام کاربری و رمز عبور وارد شده در فرم صحیح است یا نه.
در ادامه کد این بخش را ملاحظه میکنید که باید در فایلی به نام login.php قرار گیرد.
یک نکته مهم که باید توجه داشته باشید این است که ما نامهای کاربری و رمز عبور را در همزمان مقایسه نمیکنیم، چون رمز عبور عملاً به شکل هش شده ذخیره شده است. ابتدا باید هش را به کمک نام کاربری ارائه شده واکشی کنیم. زمانی که هش را به دست آوردیم، میتوانیم با استفاده از تابع اقدام به مقایسه رمز عبور و هش بکنیم.
زمانی که رمز عبور با موفقیت تأیید شود، متغیر [‘SESSION[‘user_id_$ را برابر با ID آن کاربر در پایگاه داده تعیین میکنیم. همچنین میتوانید مقدار متغیرهای دیگر را نیز بسته به نیاز تعیین کنید.
اغلب وبسایتها که از کاربر تقاضای ثبت نام میکنند، صفحههای دیگری نیز دارند که کاربران در آن اقدام به دسترسی و ذخیرهسازی دادههای خصوصی خود میکنند. میتوان از متغیرهای نشست برای حفاظت این صفحهها استفاده کرد. اگر متغیر نشست تعیین نشده باشد، میتوانید کاربر را به صفحه ورود هدایت کنید و در غیر این صورت کاربر میتواند به محتوای صفحات خود دسترسی داشته باشد.
تنها کاری که در این مرحله باید انجام دهید، این است که مطمئن شوید اسکریپت شامل ()session_start در ابتدای خود است.
در این راهنما آموختیم که یک سیستم ثبت نام و ورود کاربر را با استفاده از PHP بسازیم. زمانی که با مبانی سیستمهای ورود و ثبت نام آشنا شوید، میتوانید منطقهای پیچیدهتری را نیز پیادهسازی کنید و به کاربر امکان ریست کردن رمز عبور، تأیید کردن آدرس ایمیل و کارهایی از این دست را بدهید. همچنین میتوانید اعتبارسنجی فرانتاند بیشتری را با استفاده از خصوصیتهای HTML5 و JQuery اجرا کنید تا فرم کاربرپسندتری داشته باشید.
منبع: فرادرس

در روزگار قدیم جاوا اسکریپت از callback استفاده میکرد که در آن درون هر تابع یک تابع ناهمگام نیز قرار میگرفت و بدین ترتیب چیزی ایجاد میشد که به نام «هرم مرگ» (pyramid of doom) یا «جهنم کالبک» (callback hell) مشهور بود. مثال زیر یک نمونه ساده از آن است:
در ES6 ساختار جدیدی معرفی شد که کار دیباگ کردن کدهای ناهمگام را بسیار سادهتر و آسانتر میساخت. این ساختار بر اساس شیئی به نام Promise و متدهای then و catch بنا شده بود:
در نهایت ES7 دو کلیدواژه به نامهای Async و Await معرفی کرد که امکان کدنویسی ناهمگام را به صورتی که تا حد امکان به کد همگام جاوا اسکریپت شبیه باشد فراهم میساخت. نمونهای از آن را در مثال زیر میبینید. این توسعه اخیر به تدریج خواناترین روش برای اجرای وظایف ناهمگام در جاوا اسکریپت تلقی شد و در مقایسه با ساختار معمولی Promise حتی از نظر کارایی حافظه نیز موجب ارتقا میشود.
در گذشته بازیابی دادهها از دامنه دیگر مستلزم استفاده از XMLHttpRequest یا شیء XHR بود. امروزه میتوانیم از API واکشی جاوا اسکریپت به این منظور استفاده کنیم. متد ()fetch یک آرگومان الزامی دارد که نشاندهنده مسیر منبعی است که میخواهیم واکشی کنیم و یک Promise بازگشت میدهد.
برای استفاده از ()fetch در Node.js باید یک پیادهسازی از fetch را ایمپورت کنید. Isomorphic Fetch یک گزینه رایج محسوب میشود. آن را با وارد کردن دستور زیر در ترمینال نصب کنید:
npm install isomorphic-fetch es6-promise
سپس آن را در ابتدای سند به صورت زیر الزام (require) کنید:
اگر میخواهید دادههای JSON را واکشی کنید، باید پیش از پردازش کردن پاسخ، متد ()json را روی آن اجرا کنید:
JSON دریافت دادههای مورد نیاز و پردازش کردن آنها را به فرایندی نسبتاً سرراست تبدیل کرده است. اما اگر دادهها در قالب JSON نباشند چطور؟
در مورد اغلب وبسایتها باید دادههایی را که میخواهیم، از قالب HTML استخراج کنیم. در وبسایتهای استاتیک، دو روش به این منظور وجود دارد:
اگر نیازهای شما ساده هستند و با نوشتن regex نیز مشکلی ندارید، میتوانید به سادگی از متد ()text استفاده کنید و سپس دادههایی که لازم دارید را با استفاده از متد match استخراج کنید. برای نمونه، در ادامه کدی را میبینید که برای استخراج محتوای تگ نخست h1 در یک صفحه مورد استفاده قرار میگیرد:
اگر با سندهای پیچیدهتری سروکار دارید، بهتر است از آرایهای از متدهای داخلی جاوا اسکریپت برای کوئری زدن به DOM استفاده کنید. به این منظور از متدهایی مانند getElementById و querySelector استفاده کنید.
اگر بخواهیم کد فرانتاند را بنویسیم، میتوانیم از اینترفیس DOMParser استفاده کنیم. از آنجا که ما از Node.js استفاده میکنیم، میتوانیم از ماژول node نیز به جای آن بهره بگیریم. یک گزینه رایج jsdom است که میتوان با دستور زیر آن را نصب کرد:
npm i jsdom
همچنین با دستورهای زیر آن را require میکنیم:
با استفاده از jsdom میتوانیم HTML ایمپورت شده را مانند شیء DOM خود و با بهرهگیری از querySelector و متدهای مرتبط ایمپورت کنیم:
اگر بخواهیم دادهها را از یک وبسایت دینامیک مانند یک شبکه اجتماعی دریافت کنیم چطور؟ محتوای چنین وبسایتهایی به صورت در لحظه تولید میشود و لذا فرایند کار کاملاً متفاوت خواهد بود. در این حالت اجرای یک درخواست fetch عملی نخواهد بود، زیرا کدِ استاتیکِ سایت را بازگشت میدهد و نه محتوای دینامیک آن را که احتمالاً مورد نظر ما است.
اگر چنین نیتی در سر دارید بهترین ماژول node برای اجرای این کار puppeteer است، چون جایگزین اصلی آن PhantomJS دیگر توسعه نمییابد.
Puppeteer امکان اجرای کروم یا کرومیوم را روی پروتکل DevTools فراهم ساخته است و قابلیتهایی مانند ناوبری خودکار صفحه و تهیه تصویری از صفحه را دارد. DevTools به صورت پیشفرض یک مرورگر headless را اجرا میکند، اما تغییر دادن این تنظیمات برای دیباگ کردن مفید خواهد بود.
برای نصب Puppeteer به دایرکتوری پروژه در ترمینال بروید و عبارت زیر را وارد کنید:
npm i puppeteer
در ادامه مقداری کد اولیه برای شروع کار را مشاهده میکنید:
ابتدا puppeteer را راهاندازی میکنیم. حالت adless را نیز غیرفعال میکنیم به طوری که میتوانیم ببینیم چه کار میکنیم. سپس یک برگه جدید باز میکنیم. متد زیر اختیاری است و امکان استفاده از متدهای abort ،continue و respond را در ادامه میدهد. در نهایت به صفحه منتخب میرویم.
page.setRequestInterception(true)
در مثال DOM Parser فوق میتوانیم عناصر را با استفاده از document.querySelector و متدهای مرتبط کوئری کنیم.
اگر لازم باشد در یک وبسایت لاگین کنیم این کار با استفاده از متدهای type و click به سادگی انجامشدنی است. بدین ترتیب عناصر DOM با استفاده از همان ساختار querySelector شناسایی میشوند:
وبسایتهای دینامیک عموماً از طریق مکانیسم اسکرول بینهایت محتوا را به نمایش میگذارند. برای فائق آمدن بر این مشکل، باید کاری کنیم که puppeteer بر مبنای نوعی معیار اقدام به اسکرول کردن بکند.
در ادامه مثال سادهای را میبینید که 5 بار اسکرول میکند و به مدت 1 ثانیه بین هر اسکرول صبر میکند تا محتوا بارگذاری شود.
از آنجا که زمانهای بارگذاری متفاوت هستند، کد فوق لزوماً هر بار تعداد نتیجه یکسانی را بارگذاری نمیکند. اگر با چنین مشکلی مواجه شدید، میتوانید تا زمانی که تعداد مشخصی از عناصر پیدا نشدهاند، اسکرول کنید و یا معیار دیگری را انتخاب کنید.
در نهایت چند روش وجود دارند که میتوانند موجب بهینهسازی کدهای ما شوند و از این رو کد تا حد امکان سریع و روان اجرا شود. به عنوان مثال در ادامه روشی را ملاحظه میکنید که موجب میشود puppeteer از بارگذاری فونتها و تصاویر منع شود.
همچنین میتوان CSS را به روش مشابهی غیرفعال کرد، اما در پارهای موارد CSS در دادههای دینامیکی که میخواهید بارگذاری کنید، یکپارچهسازی شده است و از این رو باید در این زمینه هوشیار باشید.
مطالبی که در این نوشته مطرح کردیم تقریباً همه آن چیزی بود که برای ساخت یک وب اسکرپر کارآمد لازم بود. زمانی که دادهها را در حافظه گردآوری کردید، میتوانید آنها را با استفاده از ماژول fs در یک سند محلی ذخیره کنید، روی پایگاه داده آپلود کنید یا با استفاده از یک API مانند گوگل شیتز مستقیماً به یک سند ارسال کنید. اگر در زمینه وب اسکرپینگ تازهکار هستید یا در این زمینه معلوماتی دارید اما در زمینه Node.js مبتدی هستید، این مقاله احتمالاً برای شما مفید بوده است و شما را با برخی از ابزارهای قدرتمند Node.js که امکان وب اسکرپینگ را مهیا میسازند آشنا ساخته است.
منبع: فرادرس
لاراول تابعهای کمکی زیادی دارد که روشی آسان برای کار با مسیرها، آرایهها و رشتهها به دست میدهند. البته شناخت همه آنها کاری تقریباً ناممکن است. اغلب توسعهدهندگان انواع بسیار رایجتر را میشناسند، اما برخی تابعهای کمکی بسیار مفید دیگر نیز وجود دارند که در صورت کمی تأمل بیشتر با آنها آشنا میشوید. در این مقاله تابعهای کمکی لاراول که باید با آنها آشنا شوید را معرفی میکنیم.
تابع کمکی Logger میتواند برای نوشتن پیامی با سطح debug در لاگ مورد استفاده قرار گیرد.
که در نتیجه خط زیر را به لاگ اضافه میکند:
اگر هیچ مقداری به تابع Logger ارسال نشود، یک وهله از Logger بازگشت میدهد. بدین ترتیب میتوانیم پیامهایی با سطوح مختلف در لاگ بنویسیم:
کد فوق خط زیر را به لاگ اضافه میکند:
متد ()Arr::divide امکان افراز یک آرایه به دو آرایه را فراهم میسازد. متد تقسیم دو آرایه بازگشت میدهد که یکی شامل کلیدها و آرایه دیگر شامل مقادیر است.
تابع کمکی Blank بررسی میکند که آیا یک مقدار خالی است یا نه. منظور از مقدار خالی null است، یعنی یک رشته که صرفاً شامل کاراکتر فاصله یا آرایه یا رشته خالی است.
نکته: مقادیر بولی به عنوان مقادیر خالی تلقی میشوند.
معکوس این تابع کمکی، تابع کمکی filled است.
دامپ کردن متغیرها در صورتی که بخواهیم یک یا چند متغیر را دیباگ کنیم بسیار کارآمد خواهد بود.
امکان دامپ کردن متغیرهای چندگانه با ارسال متغیرهای دیگر به تابع dump نیز وجود دارد:
در کنار تابع کمکی dump، تابع کمکی دامپ دیگری نیز وجود دارد. این تابع کمکی به نام dd شناخته میشود که به معنی «dump and die» است. تابع مذکور همانند تابع دامپ کار میکند و تنها تفاوت این است که تابع dd به جای این که صرفاً متغیر را دامپ کند، اجرای اسکریپت را نیز خاتمه میبخشد.
لاراول چند تابع کمکی دارد که میتوان برای دریافت مسیر کامل به دایرکتوریهای خاص مورد استفاده قرار گیرد. اینها تابعهای کمکی هستند که لاراول در زمان استفاده از مسیرها استفاده میکند:
همچنین میتوانید یک آرگومان را به تابعهای کمکی مسیر ارسال کنید که به مسیر الحاق میشود:
برای تولید رشته مناسب URL از یک رشته میتوان از تابع کمکی Str::slug استفاده کرد.
جداکننده پیشفرض خط تیره (-) است، اما میتوانید این کاراکتر را با ارسال آرگومان دوم به تابع بازنویسی کنید:
متد Arr:has میتواند با بهرهگیری از نمادگذاری نقطه (.) برای بررسی این که یک یا چند آیتم در یک آرایه وجود دارند یا نه استفاده شود.
برای بررسی وجود آیتمهای چندگانه کافی است به جای یک رشته، آرایهای را به متد ارسال کنید:
متد Str::uuid یک UUID ایجاد میکند:
تابع کمکی Optional امکان دسترسی به مشخصهها را با فراخوانی متدها روی یک شیء که به صورت آرگومان ارسال شده فراهم میسازد. هر آرگومانی در این تابع پذیرفته است.
اگر شیء ارسالی به تابع null باشد، مشخصهها و متدها به جای ایجاد خطا مقدار null بازگشت میدهند.
اگر نویسنده بلاگ در مثال فوق تنظیم شده باشد، در این صورت نام کامل نویسنده نمایش خواهد یافت. اگر به هر دلیلی نویسنده تعیین نشده باشد، خطایی وجود نخواهد داشت و هیچ اتفاقی هم نمیافتد.
متد Arr::pluck همه مقادیر را از یک کلید مفروض در آرایه بازیابی میکند.