تجريف الويب يستخرج البيانات من مواقع الويب برمجيًا – وهو مفيد للبحث ومراقبة الأسعار وتجميع البيانات والأتمتة. ينشئ هذا الدليل أدوات استخراج البيانات في لغة Python، بدءًا من الصفحات الثابتة البسيطة وحتى مواقع JavaScript الديناميكية، مع تغطية الممارسات القانونية والأخلاقية التي تبقيك بعيدًا عن المشاكل.
📋 Table of Contents
كشط بمسؤولية أولا
قبل كتابة أي أداة استخراج، افهم القواعد:
- تحقق من ملف robots.txt:
example.com/robots.txtيخبرك بما هو مسموح بالزحف إليه - اقرأ شروط الخدمة: بعض المواقع تحظر صراحة الكشط
- حدود معدل الاحترام: لا تضغط على الخادم — قم بإضافة تأخيرات بين الطلبات
- استخدم واجهات برمجة التطبيقات الرسمية عندما تكون متاحة: تفضل دائمًا واجهة برمجة التطبيقات (API) على الكشط
- لا تتخلص من البيانات الشخصية بدون أساس قانوني (تطبق اللائحة العامة لحماية البيانات والقوانين المماثلة)
- عرف عن نفسك: قم بتعيين وكيل مستخدم مناسب، ولا تخفي الروبوت الخاص بك بشكل ضار
الإعداد
pip install requests beautifulsoup4 lxml
# For JavaScript-heavy sites:
pip install playwright
playwright install chromium
تجريف الصفحات الثابتة مع الطلبات + BeautifulSoup
import requests
from bs4 import BeautifulSoup
import time
def scrape_articles(url):
headers = {
'User-Agent': 'Mozilla/5.0 (compatible; MyResearchBot/1.0)'
}
response = requests.get(url, headers=headers, timeout=10)
response.raise_for_status()
soup = BeautifulSoup(response.text, 'lxml')
articles = []
for article in soup.select('article.post'):
title = article.select_one('h2.title')
link = article.select_one('a')
articles.append({
'title': title.get_text(strip=True) if title else None,
'url': link['href'] if link else None,
})
return articles
data = scrape_articles('https://example.com/blog')
for item in data:
print(item)
اختيار العناصر بدقة
soup = BeautifulSoup(html, 'lxml')
# By tag
soup.find('h1') # first h1
soup.find_all('p') # all paragraphs
# By CSS selector (most flexible)
soup.select('div.card > h2') # h2 inside div.card
soup.select_one('#main .price') # first .price inside #main
# Extract data
element.get_text(strip=True) # text content
element['href'] # attribute value
element.get('data-id', 'default') # attribute with fallback
# Navigate
element.parent # parent element
element.find_next_sibling('div') # next sibling
تجريف المواقع الديناميكية (جافا سكريبت) مع الكاتب المسرحي
تعرض العديد من المواقع الحديثة المحتوى باستخدام JavaScript — ولن تتمكن الطلبات من رؤيته. الكاتب المسرحي يدير متصفحًا حقيقيًا:
from playwright.sync_api import sync_playwright
def scrape_dynamic(url):
with sync_playwright() as p:
browser = p.chromium.launch(headless=True)
page = browser.new_page(user_agent='Mozilla/5.0 (MyBot/1.0)')
page.goto(url, wait_until='networkidle')
# Wait for content to load
page.wait_for_selector('.product-card')
# Extract data from the rendered page
products = page.eval_on_selector_all('.product-card', '''
cards => cards.map(card => ({
name: card.querySelector('.name')?.innerText,
price: card.querySelector('.price')?.innerText,
}))
''')
browser.close()
return products
results = scrape_dynamic('https://example.com/products')
تحديد المعدل والأدب
import time
import random
def polite_scrape(urls):
results = []
for url in urls:
try:
data = scrape_page(url)
results.append(data)
except requests.RequestException as e:
print(f"Failed {url}: {e}")
# Random delay between requests (1-3 seconds) - be gentle
time.sleep(random.uniform(1, 3))
return results
# Respect Retry-After on 429 responses
response = requests.get(url)
if response.status_code == 429:
retry_after = int(response.headers.get('Retry-After', 60))
time.sleep(retry_after)
التعامل مع ترقيم الصفحات
def scrape_all_pages(base_url):
all_data = []
page = 1
while True:
url = f"{base_url}?page={page}"
response = requests.get(url, headers=HEADERS, timeout=10)
soup = BeautifulSoup(response.text, 'lxml')
items = soup.select('.item')
if not items:
break # no more items - stop
all_data.extend(extract_items(items))
# Check for a "next" link, or just increment
if not soup.select_one('a.next-page'):
break
page += 1
time.sleep(random.uniform(1, 2))
return all_data
حفظ البيانات المحذوفة
import csv
import json
# To CSV
with open('data.csv', 'w', newline='') as f:
writer = csv.DictWriter(f, fieldnames=['title', 'url', 'price'])
writer.writeheader()
writer.writerows(data)
# To JSON
with open('data.json', 'w') as f:
json.dump(data, f, indent=2, ensure_ascii=False)
# To a database (SQLite example)
import sqlite3
conn = sqlite3.connect('scraped.db')
conn.executemany(
"INSERT INTO products (name, price) VALUES (?, ?)",
[(d['name'], d['price']) for d in data]
)
conn.commit()
الأسئلة المتداولة
س: هل تجريف الويب قانوني؟
ج: هذا يعتمد. غالبًا ما يكون حذف البيانات المتاحة للجمهور أمرًا قانونيًا، ولكن انتهاك شروط الخدمة، أو حذف البيانات الشخصية دون أساس، أو تجاوز عناصر التحكم في الوصول قد يكون أمرًا غير قانوني. تحقق من ملف robots.txt وToS، وفضل واجهات برمجة التطبيقات الرسمية، واستشر المشورة القانونية بشأن الاستخلاص التجاري.
س: طلبات/BeautifulSoup أو الكاتب المسرحي؟
ج: استخدم طلبات + BeautifulSoup لصفحات HTML الثابتة (أسرع وأخف وزنًا). استخدم Playwright (أو السيلينيوم) للمواقع التي يتم عرضها بواسطة JavaScript حيث يتم تحميل المحتوى ديناميكيًا. تحقق مما إذا كانت البيانات موجودة بتنسيق HTML الأولي أولاً — إذا كان الأمر كذلك، فلن تحتاج إلى متصفح.
س: كيف أتجنب الحظر؟
ج: تعامل بأدب – احترم حدود المعدل، وأضف التأخيرات، وقم بتعيين وكيل مستخدم مناسب، ولا تفرط في تحميل الخوادم. أفضل طريقة لتجنب الكتل هي ألا تكون مسيئًا. يتم حظر التجريف العدواني (وقد يكون غير قانوني).
س: هل يجب أن أستخدم واجهة برمجة التطبيقات (API) بدلاً من الاستخراج؟
ج: دائمًا، إذا كان موجودًا. تعتبر واجهات برمجة التطبيقات أكثر موثوقية وقانونية وتنظيمًا ولا تنقطع عندما يتغير HTML الخاص بالموقع. يعتبر الاستخلاص هو الملاذ الأخير عندما لا توفر واجهة برمجة التطبيقات (API) البيانات التي تحتاجها.
س: كيف أتعامل مع المواقع التي تتطلب تسجيل الدخول؟
ج: يمكن للكاتب المسرحي أتمتة تسجيل الدخول (ملء النماذج، الإرسال)، والحفاظ على الجلسة. لكن التنقيب خلف معلومات تسجيل الدخول غالبًا ما ينتهك شروط الخدمة – كن حذرًا بشكل خاص بشأن الشرعية واستخرج فقط البيانات التي يُسمح لك بالوصول إليها.
الخلاصة
يعد استخراج الويب باستخدام Python أمرًا فعالاً لجمع البيانات، ولكن قم بذلك بطريقة مسؤولة. استخدمطلبات + BeautifulSoup للصفحات الثابتة وPlaywright للمواقع التي يتم عرضها بواسطة JavaScriptوحدد العناصر باستخدام محددات CSS، وتعامل مع ترقيم الصفحات، واحفظها في CSV/JSON/قاعدة البيانات. والأهم:تحقق من ملف robots.txt وشروط الخدمة، واحترم حدود المعدل مع التأخير، وفضل واجهات برمجة التطبيقات الرسمية، ولا تستخرج البيانات الشخصية دون أساس قانوني. إن الاستخراج الأخلاقي والمهذب يبقيك بعيدًا عن المشاكل القانونية والفنية أثناء الحصول على البيانات التي تحتاجها. عند وجود واجهة برمجة التطبيقات (API)، استخدمها دائمًا بدلاً من ذلك — فالاستخراج هو الحل الاحتياطي، وليس الخيار الأول.
🔗 Share this article
✍️ Leave a Comment