scraping وب سمت مشتری با JavaScript با استفاده از jQuery و Regex

هنگامی که من در حال ساخت اولین پروژه منبع باز من ، codeBadges بودم ، فکر کردم به راحتی می توان اطلاعات پروفایل کاربر را از تمام وب سایتهای اصلی یادگیری کد بدست آورد.

من با تماس های API آشنا بودم و درخواست می کردم. فکر کردم فقط می توانم از jQuery برای واکشی داده ها از API های مختلف استفاده کرده و از آن استفاده کنم.

var name = 'codemzy'؛ $ .get ('https://api.github.com/users/' + نام ، عملکرد (پاسخ) {var followers = پاسخ.فروشنده ها؛})؛

خوب ، این آسان بود اما معلوم می شود که همه وب سایت ها دارای یک API عمومی نیستند که بتوانید فقط داده های مورد نظر خود را از آن بگیرید.

404: API یافت نشد

اما فقط به دلیل عدم وجود یک API عمومی به این معنی نیست که باید تسلیم شوید! فقط با کمی کار اضافی می توانید از scraping وب برای گرفتن اطلاعات استفاده کنید.

بیایید ببینیم که چگونه می توانیم از scraping وب سمت مشتری با JavaScript استفاده کنیم.

به عنوان مثال ، من اطلاعات کاربر خود را از پروفایل عمومی FreeCodeCamp من دریافت خواهم کرد. اما می توانید از این مراحل در هر صفحه HTML عمومی استفاده کنید.

اولین قدم برای ضبط داده ها ، گرفتن صفحه کامل html با استفاده از درخواست jQuery .get است.

var name = "codemzy"؛ $ .get ('https://www.freecodecamp.com/' + نام ، عملکرد (پاسخ) {console.log (پاسخ)؛})؛

عالی ، کل کد منبع صفحه فقط وارد کنسول شده است.

توجه: اگر در این مرحله به خطا رسیدید ، در کنار خط No "Access-Control-Allow-Origin" در منبع درخواستی وجود دارد ، نترسید. به قسمت Do Not CORS Stop You در این پست بروید.

آن آسان بود. با استفاده از JavaScript و jQuery ، کد فوق مانند یک مرورگر می خواهد یک صفحه از www.freecodecamp.org درخواست کند. و freeCodeCamp با صفحه پاسخ می دهد. به جای اینکه یک مرورگر کد را برای نمایش صفحه اجرا کند ، کد HTML را دریافت می کنیم.

و این همان چیزی است که scraping وب ، استخراج داده ها از وب سایت ها است.

خوب ، پاسخ دقیقاً به اندازه داده هایی که از API برگردانده ایم ، مرتب نیست.

اما ... ما در آنجا اطلاعات داریم.

هنگامی که ما منبع منبع اطلاعات مورد نیاز خود را در آنجا قرار دادیم ، فقط باید داده های موردنیاز خود را بگیریم!

ما می توانیم از طریق پاسخ جستجو کنیم تا عناصر مورد نیاز خود را پیدا کنیم.

بیایید بگوییم که می خواهیم بدانیم که چقدر چالش های کاربر را تمام کرده است ، از پاسخ پروفایل کاربر که برگشتیم.

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

یک راه این است که کل پاسخ را در یک جی کوئری پیچانده کنیم تا بتوانیم از روشهای جی کوئری مانند .find () برای به دست آوردن داده ها استفاده کنیم.

// تعداد چالش های تکمیل شده چالش های مختلف = $ (پاسخ). یافتن ('tbody tr') طول.

این خوب است - ما به نتیجه مناسب می رسیم. اما آن راهی خوب برای به دست آوردن نتیجه ای نیست که ما پس از آن داریم. تبدیل پاسخ به یک جی کوئری در واقع بارگذاری کل صفحه ، از جمله تمام اسکریپت های خارجی ، فونت ها و شیوه نامه های آن صفحه است ... اوه اوه!

ما به چند بیت داده نیاز داریم. ما واقعاً به بارگذاری صفحه نیازی نداریم ، و مطمئناً به تمام منابع خارجی که با آن همراه هستند نیست.

ما می توانیم برچسب های اسکریپت را از بین ببریم و سپس بقیه پاسخ را از طریق جی کوئری اجرا کنیم. برای این کار می توانیم از Regex استفاده کنیم تا به دنبال الگوهای اسکریپت در متن و حذف آنها باشیم.

یا بهتر است ، چرا از Regex استفاده نمی کنیم تا در وهله اول آنچه را که ما به دنبالش هستیم پیدا کنیم؟

// تعداد چالش های کامل شده = چالش های مختلف = پاسخ [\ s | \ S] *؟ <\ / thead> / g) .match (/ /g).l طول؛

و کار می کند! با استفاده از کد Regex در بالا ، ردیف های سر جدول را جدا می کنیم (که هیچ مشکلی برای آنها وجود ندارد) ، و سپس با تمام ردیف های جدول مطابقت می دهیم تا تعداد چالش های انجام شده را بشماریم.

حتی اگر داده هایی که می خواهید در پاسخ با متن ساده وجود داشته باشد ، ساده تر است. در زمان نوشتن ، نکات کاربر در html قرار داشت [1498] فقط منتظر خراشیدن هستم

امتیازات = پاسخ.match (/ \ [([[d] *؟) \] <\ / h1> /) [1]؛

در الگوی Regex فوق با عنصر h1 که به دنبال آن هستیم ، مطابقت داریم با [] که نقاط را احاطه می کند ، و هر شماره ای را با ([\ d] *؟) گروه بندی کنید. ما یک آرایه عقب می گیریم ، اولین [0] عنصر کل مسابقه و دومین مسابقه مسابقه گروهی ما (امتیازات ما) است.

Regex برای تطبیق انواع الگوها در رشته ها مفید است ، و جستجوی پاسخ از طریق پاسخ ما برای بدست آوردن داده های مورد نیاز بسیار مفید است.

می توانید از همان مراحل 3 مرحله ای برای ضبط داده های پروفایل از انواع وب سایت های مختلف استفاده کنید:

  1. از JavaScript سمت مشتری استفاده کنید
  2. برای ضبط کردن داده ها از jQuery استفاده کنید
  3. برای فیلتر کردن اطلاعات برای اطلاعات مربوطه از Regex استفاده کنید

تا وقتی که مشکلی پیش نیامدم ، CORS.

CORS: دسترسی رد شد

اجازه ندهید CORS شما را متوقف کند!

CORS یا به اشتراک گذاری منابع Cross-Origin ، می تواند یک مشکل واقعی برای scraping وب سمت مشتری باشد.

به دلایل امنیتی ، مرورگرها درخواستهای HTTP با منشاء متقابل را که از درون اسکریپت ها شروع شده اند محدود می کنند. و از آنجا که ما در قسمت جلویی برای جاگذاری وب از Javascript در سمت مشتری استفاده می کنیم ، خطاهای CORS ممکن است رخ دهد.

در اینجا مثالی در تلاش است تا داده های نمایه را از CodeWars ضبط کنید ...

var name = "codemzy"؛ $ .get ('https://www.codewars.com/users/' + نام ، عملکرد (پاسخ) {console.log (پاسخ)؛})؛

در زمان نوشتن ، اجرای کد فوق خطایی در رابطه با CORS به شما می دهد.

اگر از جایی که می خواهید سرصفحه noAccess-Control-Allow-Origin نباشد ، می توانید با مشکل روبرو شوید.

خبر بد این است که شما باید این نوع درخواست ها را از طریق سرور اجرا کنید تا به این مشکل برسید.

اواااااا ، این قرار است وب سایت مشتری را دستگیر کند ؟!

خبر خوب این است که ، به لطف بسیاری از توسعه دهندگان شگفت انگیز دیگر که در همان موضوعات قرار گرفته اند ، نیازی نیست خود را به عقب برگردانید.

کاملاً با اسکریپت جلوی خود بمانیم ، می توانیم از ابزارهای متشکل از حوزه های متقابل مانند Any Origin ، What Origin، All Origins، crossorigin و احتمالاً موارد دیگر استفاده کنیم. من فهمیدم که شما اغلب باید تعدادی از این موارد را آزمایش کنید تا بتوانید محلی را پیدا کنید که در سایتی که می خواهید سرقت کنید کار می کند.

به مثال CodeWars ما ، می توانیم درخواست خود را از طریق یک ابزار دامنه متقابل ارسال کنیم تا مسئله CORS را دور بزنیم.

var name = "codemzy"؛ var url = "http://anyorigin.com/go؟url=" + encodeURIComponent ("https://www.codewars.com/users/") + name + "& callback =؟"؛ $ .get (آدرس اینترنتی ، عملکرد (پاسخ) {console.log (پاسخ) ؛})؛

و درست مثل جادو ، ما پاسخ خود را داریم.