انتقل إلى المحتوى

كيفية كشط بيانات الويب المخفية

غالبًا ما يبدو استخراج البيانات من الويب الحديث بمثابة لعبة الغميضة. بينما كانت معظم المعلومات قبل عقد من الزمن متاحة بسهولة بتنسيق HTML، أصبح المطورون في الوقت الحاضر يحبون إخفاء البيانات والتعتيم عليها، وعرضها ديناميكيًا باستخدام JavaScript.

يمثل هذا تحديًا مثيرًا للاهتمام للكاشطات. على الرغم من أنه لم يعد بإمكاننا الاعتماد على تحليل محتوى HTML الأولي، إلا أنه لا يزال هناك عدد كبير من البيانات في الصفحة - علينا فقط أن نعرف أين نبحث عنها.

في هذا الدليل الشامل، سنستكشف مختلف الأساليب والأدوات والتقنيات التي يمكن استخدامها لاستخراج بيانات الويب المخفية.

ما هي بيانات الويب المخفية؟

تشير بيانات الويب المخفية إلى أي بيانات غير مرئية مباشرة في مصدر HTML الأولي للصفحة. هذا يتضمن:

  • يتم تحميل البيانات ديناميكيًا عبر JavaScript بعد تحميل الصفحة. على سبيل المثال، تقديم محتويات أ <div> العلامة عن طريق إدراج عناصر HTML تم إنشاؤها ديناميكيًا.

  • البيانات المخزنة في متغيرات JavaScript والكائنات المضمنة فيها <script> العلامات. غالبًا ما تحتوي كائنات JSON على مجموعات بيانات كاملة.

  • محتوى HTML تم إنشاؤه بناءً على إجراء المستخدم عبر طلبات AJAX. على سبيل المثال، توسيع سلاسل التعليقات أو ترقيم صفحات التمرير اللانهائي.

  • بيانات طلب واجهة برمجة التطبيقات الداخلية والبيانات الوصفية التي تستخدمها الواجهة الأمامية لتعمل. على سبيل المثال، رموز CSRF، ومعلومات المستخدم، وذاكرة التخزين المؤقت المؤقتة.

  • بيانات غامضة ومشفرة تهدف إلى منع أدوات الكشط من الوصول إليها.

الموضوع الشائع هو أن هذه البيانات غير متوفرة في HTML الأصلي الذي يتم إرجاعه من الخادم، ولكن يتم إنشاؤها لاحقًا بواسطة JavaScript الذي يتم تشغيله على الصفحة.

تعتمد مواقع الويب الديناميكية الحديثة بشكل كبير على هذه التقنية لبناء تجارب واجهة أمامية سريعة. يمكن إخفاء كافة البيانات وعرضها بشكل أنيق في أجزاء صغيرة حسب الحاجة.

لسوء الحظ، هذا يعني أن أدوات الكشط يجب أن تعمل بجهد أكبر للوصول إلى تلك البيانات. دعونا نلقي نظرة على بعض الطرق التي يمكننا من خلالها القيام بذلك بكفاءة.

العثور على البيانات المخفية في HTML

الخطوة الأولى هي التأكد مما إذا كانت البيانات التي نريدها مخفية بالفعل في صفحة JavaScript في مكان ما.

إليك طريقة بسيطة للتحقق:

  • قم بتحميل الصفحة المستهدفة في المتصفح وحدد موقع معرف البيانات الفريد الذي نريد استخراجه. على سبيل المثال، اسم المنتج أو معرفه.

  • قم بتعطيل JavaScript في المتصفح وأعد تحميل الصفحة. يمكن القيام بذلك في أدوات المطور.

  • تحقق مما إذا كان المعرف الفريد لا يزال موجودًا في كود مصدر HTML الأولي.

إذا اختفت البيانات، فمن المرجح أن يتم عرضها ديناميكيًا بواسطة JavaScript عند تحميل الصفحة.

يتعين علينا الآن البحث في مصدر HTML للعثور على مكان وكيفية إنشاء هذا المحتوى.

استخراج البيانات من العلامات

يعد الداخل أحد أكثر الأماكن شيوعًا لتخزين البيانات المخفية <script> العلامات.

يمكن أن يكون ذلك كائنات JSON أو متغيرات JavaScript أو مجموعات بيانات كاملة أو تعليمات برمجية تعالج الصفحة.

فمثلا:

<html>
<body>

  <div id="product"></div>

  <script>
    // product data as javascript object 
    var data = {
      "product": {
        "name": "Super Product",
        "price": 99.99
      }
    }

    // data rendered on page load
    document.getElementById("product").innerHTML = data.product.name + ": £" + data.product.price;

  </script>

</body>  
</html>

هنا يتم تخزين بيانات المنتج الفعلية في متغير كائن JavaScript يسمى data.

المنتج <div> يكون فارغًا في البداية ويتم ملؤه ديناميكيًا عند تحميل الصفحة.

لذا، لاستخراج هذه البيانات، علينا أولاً العثور على البيانات ذات الصلة <script> علامة في HTML الخام. يمكن القيام بذلك باستخدام أي مكتبة تحليل HTML مثل BeautifulSoup أو Parsel:

# extract scripts from HTML with BeautifulSoup
from bs4 import BeautifulSoup

html = # page HTML 
soup = BeautifulSoup(html, ‘html.parser‘)

scripts = soup.find_all(‘script‘)

بعد ذلك يتعين علينا استخراج البيانات من محتوى البرنامج النصي على وجه التحديد.

الطريقة الأولى: التحميل بتنسيق JSON

إذا كانت البيانات عبارة عن كائن JSON صالح، فيمكننا ببساطة تحميلها مباشرةً باستخدام Python json وحدة:

import json

# find script with data variable 
script = soup.find(‘script‘, text=lambda t: ‘data =‘ in t)

# load json directly
data = json.loads(script.string)

print(data[‘product‘])
# {‘name‘: ‘Super Product‘, ‘price‘: 99.99}

يعمل هذا بشكل رائع إذا تم تحديد علامة البرنامج النصي type="application/json".

الطريقة الثانية: مطابقة Regex

بالنسبة للبيانات الأكثر تعقيدًا، سيتعين علينا تحليل كود JavaScript الخام بأنفسنا. هذا هو المكان الذي تكون فيه التعبيرات العادية مفيدة.

يمكننا مسح الكود ضوئيًا واستخراج الأجزاء التي تطابق النمط، مثل كائن البيانات الخاص بنا.

import re
import json

script = soup.find(‘script‘, text=lambda t: ‘data =‘ in t)

# match the data object by surrounding syntax 
match = re.search(r‘data = ({.+})‘, script.string)

# load matched json 
data = json.loads(match.group(1))

print(data[‘product‘])  
# {‘name‘: ‘Super Product‘, ‘price‘: 99.99}

المفتاح هو صياغة نمط regex بعناية والذي يحدد بشكل فريد مجموعة البيانات التي نريدها من بقية الكود.

الطريقة الثالثة: تحليل جافا سكريبت

بالنسبة للاستخراج المتقدم، قد نرغب في تحليل كود JavaScript الكامل - بما في ذلك المتغيرات والوظائف والكائنات.

وهذا يسمح باستخراج أي بيانات مع الحفاظ على البنية والسياق الأصليين.

يمكننا استخدام المكتبات مثل باي جافا سكريبت و Js2Py لتفسير جافا سكريبت في بايثون.

على سبيل المثال مع PyJavascript:

import javascript

script = soup.find(‘script‘, text=lambda t: ‘data =‘ in t)

# init JavaScript interpreter 
js = javascript.Interpreter()

# run script to define data variable
js.execute(script.string)

# access parsed data object
print(js.context[‘data‘][‘product‘])
# {‘name‘: ‘Super Product‘, ‘price‘: 99.99} 

يتيح لنا ذلك الاستفادة من بيئة JavaScript بأكملها، بما يتجاوز مجموعات البيانات التي نريدها فقط.

استخراج بيانات API من JavaScript

تعمل واجهات برمجة التطبيقات (APIs) على تشغيل معظم السلوك الديناميكي على مواقع الويب الحديثة. تقدم JavaScript طلبات لتحميل البيانات أو إرسال النماذج أو تشغيل التفاعلات.

ومن خلال البحث في رمز الصفحة، يمكننا العثور على نقاط نهاية واجهة برمجة التطبيقات هذه وتقليد طلبات استخراج البيانات.

على سبيل المثال، إليك برنامج نصي بسيط يقوم بتحميل بيانات المنتج من ملف /api/products/123 نقطة النهاية:

async function loadProduct(){

  let response = await fetch(‘/api/products/123‘);

  let product = await response.json();

  // render product data to page
  document.getElementById("product").innerHTML = product.name;

}

loadProduct();

بمجرد تحديد موقع هذا البرنامج النصي في HTML، يمكننا:

  • قم باستخراج عنوان URL لواجهة برمجة التطبيقات من ملف fetch() دعوة

  • تحليل تنسيقات الطلب والاستجابة في AJAX

  • قم بنسخ طلب API مباشرة في Python باستخدام مكتبات مثل الطلبات

يتيح ذلك استخراج البيانات من واجهات برمجة التطبيقات (APIs) التي تعتمد عليها JavaScript دون تنفيذ أي تعليمات برمجية للمتصفح.

البحث عن البيانات في متغيرات جافا سكريبت

يتم أيضًا تخزين بيانات الصفحة مباشرةً في متغيرات JavaScript.

فمثلا:

// javascript data
var products = [
  {name: "Product 1", price: 19.99}, 
  {name: "Product 2", price: 24.99}
];

function renderProducts(){
  // loop through products and render HTML
} 

هنا يتم تخزين قائمة المنتجات الكاملة في متغير يسمى products.

لاستخراج هذا، علينا أولاً العثور على اسم المتغير المطابق لبنية البيانات المستهدفة لدينا. يمكننا استخدام نهج regex مماثل:

import re
import json

# find products variable
script = soup.find(‘script‘, text=lambda t: ‘var products =‘ in t)

# match products json
match = re.search(r‘var products = ({.+});‘, script.string)  
data = json.loads(match.group(1))

print(data)
# [{name: "Product 1", price: 19.99}, {name: "Product 2", price: 24.99}]

إذا كانت بنية البيانات أكثر تعقيدًا، فيمكننا تحليل بيئة JavaScript بأكملها للوصول إلى أي متغيرات داخل النطاق.

كشط المحتوى الذي تم تحميله عبر AJAX

تقوم مواقع الويب في كثير من الأحيان بتحميل المحتوى ديناميكيًا عبر AJAX بعد تحميل الصفحة.

على سبيل المثال، توسيع سلاسل التعليقات أو صفحات التمرير اللانهائية أو علامات التبويب.

هذا المحتوى غير موجود في HTML الأولي ولكن يتم طلبه من الخادم حسب الحاجة.

يمكننا استخراج مقتطفات AJAX هذه من خلال:

  • مراقبة طلبات الشبكة على الصفحة لتحديد عناوين URL الخاصة بـ AJAX.

  • إعادة بناء طلبات AJAX وإرسالها مباشرة من كود Python.

  • تحليل استجابات AJAX التي تحتوي على بيانات HTML/JSON.

على سبيل المثال، خذ بعين الاعتبار هذا البرنامج النصي الذي يقوم بتحميل البيانات المقسمة إلى صفحات عند التمرير:

// initially loaded page data
var results = [ /* initial page of data */]; 

// paginate on scroll
window.addEventListener(‘scroll‘, function() {

  var page = results.length / 20 + 1;

  // request next page
  fetch(‘/data?page=‘ + page)
    .then(res => res.json())
    .then(data => {
      results.push(...data);

      // render new data
    });

});

هنا يمكننا أن نرى أنه يطلب صفحات من /data نقطة النهاية وإلحاق المحتوى بـ results المتغير.

يمكننا تكرار هذه الطلبات واستخراج البيانات مباشرة، وتجنب الاضطرار إلى تحليل HTML المعروض بالكامل.

تنفيذ جافا سكريبت مع المتصفحات مقطوعة الرأس

للحصول على أقصى استفادة من استخراج المحتوى الديناميكي، يمكننا تشغيل متصفح كامل بدون رأس، وتحميل الصفحة والوصول مباشرة إلى بيئة JavaScript.

يتيح ذلك تقييم التعليمات البرمجية وتحميل المحتوى الديناميكي والوصول إلى أي بيانات أو وظائف أو عناصر DOM متاحة للصفحة المباشرة.

فيما يلي مثال مع Playwright في Python:

from playwright.sync_api import sync_playwright

with sync_playwright() as p:

  browser = p.chromium.launch()
  page = browser.new_page()

  page.goto(‘https://targetpage.com‘)

  # evaluate browser context to get data
  data = page.evaluate(‘window.products‘) 

  browser.close()

print(data)

المفتاح يستخدم page.evaluate() لتشغيل كود JavaScript مخصص في سياق الصفحة المحملة.

وهذا يمنحنا الوصول الكامل لاستخراج أي بيانات مخفية.

الجانب السلبي هو الاضطرار إلى تشغيل نسخة متصفح كاملة - وهي أبطأ من طلبات HTTP المباشرة. لذلك يجب استخدام هذه الطريقة باعتدال مع الصفحات المعقدة.

البيانات المبهمة والمشفرة

غالبًا ما تقوم مواقع الويب بالتعتيم على جافا سكريبت الخاصة بها عن عمد لمنع عملية التجريد.

وتشمل بعض الأمثلة:

  • تصغير أسماء المتغيرات والوظائف إلى أحرف لا معنى لها مثل a, b, fn1()

  • تقسيم مجموعات البيانات عبر متغيرات ونصوص برمجية متعددة

  • تشفير/تشفير البيانات بحيث لا يمكن قراءتها بواسطة الإنسان

  • تجميع البيانات ديناميكيًا في وقت التشغيل من أجزاء مجزأة

  • تقنيات حماية التعليمات البرمجية مثل التعبئة، والتشويش، ومكافحة التصحيح، وتنفيذ VM

وهذا يمكن أن يجعل تحليل JavaScript أمرًا صعبًا للغاية. يمكن لتغييرات التعليمات البرمجية الصغيرة أن تكسر كاشطاتنا بسهولة.

هناك عدة طرق للتعامل مع الصفحات المبهمة بشدة:

  • استخدم متصفحات بدون رأس مثل Playwright أو Puppeteer لتحميل التعليمات البرمجية المنفذة بدلاً من تحليل المصدر المبهم مباشرةً.

  • تتبع تنفيذ التعليمات البرمجية لفهم كيفية تجميع البيانات - على سبيل المثال باستخدام أدوات مطور المتصفح أو إنشاء وكيل لحركة مرور المتصفح.

  • تحليل كيفية تفاعل المستخدمين الحقيقيين مع الصفحة لتحديد مصادر البيانات.

  • يتطابق النمط مع هياكل البيانات المعروفة - مثل أسماء المنتجات والأسعار والمعرفات - لتحديد أجزاء التعليمات البرمجية ذات الصلة حتى لو كانت المتغيرات غامضة.

  • بالنسبة للتشفير، حاول تحديد موقع مفاتيح التشفير أو خوارزميات فك التشفير باستخدام الهندسة العكسية.

بمرور الوقت، يمكننا بناء المرونة من خلال تطوير الكاشطات للتكيف مع تغييرات التشويش.

تجريف واجهات برمجة التطبيقات المخفية مع الوكلاء

غالبًا ما تستخدم واجهات برمجة تطبيقات الويب المخفية تقنيات متقدمة لمكافحة التجريد مثل تحديد معدل IP ورمز التحقق والكشف عن الروبوتات لمنع الوصول.

هذا هو المكان الذي يكون فيه الوكلاء مفيدًا جدًا للتجريف. من خلال توجيه الطلبات عبر عناوين IP السكنية، يمكننا تجاوز العديد من وسائل الحماية والوصول إلى واجهات برمجة التطبيقات على نطاق واسع.

بعض النصائح للتجميع باستخدام الوكلاء:

  • استخدم تدوير الوكيل بشكل منتظم لمنع حظر عناوين IP محددة

  • تمكين دوران الوكيل بناءً على المناطق أو مزودي خدمة الإنترنت للتنوع الواسع

  • استخدم وكلاء الاتصال الخلفي الذين يوفرون الآلاف من عناوين IP الفريدة للتنقل عبرها

  • الحد من معدلات الطلب لكل وكيل لتقليد سلوك المستخدم الحقيقي

  • استخدم ترخيص الوكيل لانتحال صفة أجهزة حقيقية، وليس فقط عناوين IP مجهولة

  • مراقبة الكتل الشائعة والتعامل معها مثل رموز التحقق وحظر الصفحات و429s

من خلال إعداد الوكيل الصحيح، يمكننا الوصول عمليًا إلى أي موقع مستهدف أو واجهة برمجة تطبيقات مخفية.

خدمات تجريف البيانات المخفية

هناك أيضًا خدمات استخراج مُدارة مُصممة خصيصًا لاستخراج بيانات JavaScript المقدمة.

وهي توفر أتمتة المتصفح وإدارة الوكيل وقدرات تنفيذ JavaScript.

وتشمل بعض الأمثلة:

كشط النحل - واجهة برمجة تطبيقات المتصفح والوكيل التي يمكنها تقييم JS في الصفحات.

ScraperAPI - واجهة برمجة تطبيقات للمتصفح بدون رأس مع دوران الوكيل التلقائي.

أبي – وقت تشغيل الممثل لأتمتة المتصفح على نطاق واسع.

سكراب اوبس – منشئ أتمتة المتصفح المرئي مع استخراج JS.

سكراب فلاي – واجهة برمجة تطبيقات غير قابلة للحظر مع الملايين من الوكلاء السكنيين المتصلين بالشبكة الخلفية.

تتعامل هذه الخدمات مع جميع تعقيدات العرض الديناميكي للصفحات وتجعل عملية استخراج البيانات المخفية أمرًا سهلاً.

الوجبات السريعة الرئيسية

فيما يلي النقاط الأساسية لاستخراج بيانات موقع الويب المخفية:

  • افحص الصفحات التي لا تحتوي على JavaScript للتأكد من تحميل البيانات ديناميكيًا

  • استخراج وتحليل البرامج النصية والمتغيرات وكائنات JSON من HTML

  • تحليل وتكرار طلبات AJAX للوصول إلى واجهات برمجة التطبيقات المخفية

  • استخدم الوكلاء والمتصفحات مقطوعة الرأس عند الحاجة لمواقع JS الثقيلة

  • مطابقة النمط والهندسة العكسية للتعليمات البرمجية المبهمة

  • قم بتكييف الكاشطات للتعامل مع وسائل الحماية ضد الروبوتات

باستخدام التقنيات الصحيحة، يمكن عمليًا استخراج أي بيانات عامة على موقع الويب. علينا فقط أن نعرف أين ننظر!

الوسوم (تاج):

الانضمام إلى محادثة

لن يتم نشر عنوان بريدك الإلكتروني. الحقول المشار إليها إلزامية *