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

كيفية تجريف الويب باستخدام HTTPX وPython

تجريف الويب هو عملية استخراج البيانات من مواقع الويب تلقائيًا. إنها تقنية شائعة تُستخدم لجمع كميات كبيرة من البيانات للتحليل والتعلم الآلي والمزيد. يوجد في Python العديد من المكتبات الرائعة التي تجعل عملية تجريف الويب أمرًا سهلاً. أحد الخيارات الشائعة هو HTTPX.

HTTPX هو عميل HTTP قوي وحديث لـ Python. تم إنشاؤه بواسطة المطورين الذين يقفون وراء الطلبات ويستمد الإلهام كثيرًا من الطلبات، مع إضافة وظائف جديدة أيضًا مثل دعم HTTP/2.

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

الشروع في العمل مع HTTPX

للبدء، يمكن تثبيت HTTPX عبر النقطة:

pip install httpx

بدلا من ذلك، يمكن استخدام الشعر:

poetry add httpx

بمجرد التثبيت، يمكن استيراد HTTPX واستخدامه:

import httpx

response = httpx.get(‘https://example.com‘)
print(response.text)

سيؤدي هذا إلى تقديم طلب GET إلى example.com وطباعة HTML للصفحة الرئيسية.

يحتوي HTTPX على واجهة برمجة تطبيقات بسيطة ويدعم جميع أفعال HTTP الشائعة مثل GET وPOST وPUT وDELETE وHEAD وOPTIONS وما إلى ذلك.

تتضمن بعض الميزات الرئيسية ما يلي:

  • دعم HTTP/1.1 وHTTP/2
  • واجهة برمجة التطبيقات (API) غير المتزامنة على نمط aiohttp
  • تجميع الاتصال والحفاظ على الحياة
  • دعم الوكيل
  • تكوين المهلة
  • ثبات ملفات تعريف الارتباط
  • واجهة برمجة تطبيقات بأسلوب الطلبات المألوفة

بعد ذلك، دعونا نلقي نظرة على بعض أنماط الاستخدام الشائعة.

تقديم الطلبات باستخدام HTTPX

لتقديم طلب GET، httpx.get() يمكن استخدام الطريقة:

response = httpx.get(‘https://example.com‘)

وبالمثل، httpx.post(), httpx.put(), httpx.delete()، وما إلى ذلك يمكن استخدامها لأفعال HTTP الأخرى.

يمكن تمرير معلمات مثل الرؤوس وملفات تعريف الارتباط والمهلة وما إلى ذلك كوسيطات للكلمات الرئيسية:

response = httpx.get(
  ‘https://httpbin.org/headers‘,
  headers = {
    ‘User-Agent‘: ‘MyBot 1.0‘
  },
  timeout = 10.0
)

يحتوي الرد على خصائص مثل status_code, headers, text, json()، الخ:

print(response.status_code)
print(response.headers)
print(response.text)
json = response.json()

يمكنك أيضًا دفق الاستجابة بشكل متزايد عن طريق التكرار على كائن الاستجابة.

باستخدام عميل HTTPX

بالنسبة لمعظم مهام الكشط، يوصى باستخدام أداة مستمرة httpx.Client حتة.

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

import httpx

client = httpx.Client()

response = client.get(‘https://example.com‘)
print(response.text)

response = client.get(‘https://httpbin.org/cookies/set?name=foo‘)
print(response.text) 

response = client.get(‘https://httpbin.org/cookies‘)
print(response.json())

نقوم هنا بتقديم طلبات متعددة باستخدام نفس العميل، الذي يتعامل مع ثبات ملفات تعريف الارتباط تلقائيًا.

يمكنك أيضًا تكوين خيارات مثل الترويسات والوكلاء والمصادقة وما إلى ذلك عند إنشاء العميل:

client = httpx.Client(
  headers = {
    ‘User-Agent‘: ‘MyBot 1.0‘,
    ‘Authorization‘: ‘Bearer xxx‘   
  },
  proxies = ‘http://192.168.1.1:8181/‘,
  auth = (‘username‘, ‘password‘)
)

الآن دعونا نلقي نظرة على طلبات التنفيذ بشكل غير متزامن.

الطلبات غير المتزامنة مع HTTPX

لتقديم الطلبات بشكل غير متزامن في بايثون، يوفر HTTPX AsyncClient:

import httpx

async with httpx.AsyncClient() as client:
  response = await client.get(‘https://example.com‘) 

نستخدم async with لتهيئة العميل، await بناء على الطلب، وإغلاق العميل تلقائيا بعد ذلك.

لاستخراج عناوين URL متعددة في وقت واحد، يمكننا استخدامها asyncio.gather():

import httpx
import asyncio

async def get_url(url):
  async with httpx.AsyncClient() as client:
    response = await client.get(url)
    return response.text

urls = [‘https://example.com‘, ‘https://httpbin.org‘, ‘https://python.org‘]

async def main():
  responses = await asyncio.gather(*[get_url(url) for url in urls])
  print(responses)

asyncio.run(main())

asyncio.gather() ينتظر بشكل متزامن العديد من coroutines ويعيد النتائج بترتيب المنتظر.

هناك أيضًا خيارات أخرى مثل asyncio.as_completed() لمعالجتها عند اكتمالها:

tasks = [get_url(url) for url in urls]

async def main():
  for result in asyncio.as_completed(tasks):
    print(await result)

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

بعد ذلك، دعونا نلقي نظرة على استخراج البيانات من استجابات HTML وJSON.

كشط استجابات HTML وJSON

بالنسبة لمسح HTML، يمكننا استخدام محلل مثل Beautiful Soup لاستخراج البيانات:

from bs4 import BeautifulSoup

response = httpx.get(‘https://en.wikipedia.org/wiki/Python_(programming_language)‘)

soup = BeautifulSoup(response.text, ‘html.parser‘)

for link in soup.select(‘.toctext‘):
  print(link.text.strip())

يؤدي هذا إلى طباعة محتويات جدول محتويات صفحة ويكيبيديا.

بالنسبة لاستجابات JSON، يوفر HTTPX ميزة مضمنة .json() الأسلوب:

response = httpx.get(‘https://api.github.com/repos/encode/httpx‘)

json = response.json()
print(json[‘description‘])

json= يمكن أيضًا استخدام المعلمة لتسلسل بيانات JSON في الطلبات.

بالتعاون مع المحلل اللغوي، يمكننا إنشاء أدوات استخراج البيانات لاستخراج البيانات من واجهات برمجة التطبيقات ومواقع الويب.

التعامل مع المشكلات والأخطاء

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

يوفر HTTPX استثناءات وأدوات للتعامل معها بشكل مناسب.

مهلة

للتعامل مع الاستجابات البطيئة، يمكنك تحديد مخصص timeout معامل. الافتراضي هو 5 ثواني.

response = httpx.get(‘https://example.com‘, timeout=10.0) 

إذا تم تجاوز هذا، أ httpx.TimeoutException يحدث:

try:
  response = httpx.get(‘https://example.com‘, timeout=0.001)
except httpx.TimeoutException:
  print(‘Request timed out‘)

قد تكون هناك حاجة إلى مهلات أطول لبعض المواقع أو الصفحات.

أخطاء HTTP

بالنسبة لأخطاء HTTP مثل 400 و500 وما إلى ذلك response.raise_for_status() يمكن استخدام الطريقة:

try:
  response = httpx.get(‘https://httpbin.org/status/500‘)
  response.raise_for_status()
except httpx.HTTPStatusError:
  print(‘HTTP Error occurred‘)  

سيؤدي هذا إلى ظهور استثناء على أي رمز حالة 4xx أو 5xx.

إعادة محاولة الطلبات

لإضافة منطق إعادة المحاولة، مثل الحزم الخارجية tenacity من الممكن استخدامه:

from tenacity import retry, stop_after_attempt

@retry(stop=stop_after_attempt(3))
def make_request():
  response = httpx.get(‘https://example.com‘)
  response.raise_for_status()
  return response.json()

data = make_request()

هنا نعيد المحاولة حتى 3 مرات لأي استثناء. يمكن أيضًا تحديد منطق إعادة المحاولة الأكثر تقدمًا.

حدود الطلبات الموازية

عند تقديم العديد من الطلبات بالتوازي، قد تواجه قيودًا على الاتصال.

limits يمكن استخدام المعلمة لتكوين خيارات مثل الحد الأقصى للاتصالات:

client = httpx.AsyncClient(
  limits = httpx.Limits(max_connections=20)
)

يمكن أن يساعد ضبط هذه المعلمة بناءً على الموقع المستهدف في تجنب الحدود.

ومن خلال التعامل مع هذه المشكلات الشائعة، يمكن بناء كاشطات أكثر مرونة.

تجريف أفضل الممارسات

فيما يلي بعض النصائح لإنشاء أدوات مسح ويب فعالة باستخدام HTTPX:

  • استخدم عميل HTTPX - يوفر العملاء خدمة تجميع الاتصالات واستمرارية ملفات تعريف الارتباط ومزايا أخرى.

  • كشط بأدب – الحد من معدلات الطلب لتجنب إرهاق الخوادم. استخدم التأخير العشوائي والاختناق.

  • التعامل مع الأخطاء - استخدم المحاولة/باستثناء الكتل والتحقق من الحالة وإعادة المحاولة لمعالجة المشكلات.

  • استخدم الإدخال/الإخراج غير المتزامن – كشط الصفحات بشكل متزامن لتحسين السرعة. ولكن الحد من التزامن لتجنب الحظر.

  • عشوائية وكلاء المستخدم – قم بتدوير سلاسل وكيل المستخدم العشوائي لتظهر بشكل أكثر إنسانية.

  • استخدم الوكلاء - قم بتدوير الوكلاء/عناوين IP المختلفة لتوزيع الطلبات.

  • ذاكرة التخزين المؤقت والبيانات المستمرة - احفظ البيانات المسروقة في الملفات/قواعد البيانات لتجنب إعادة تجريفها.

ومن خلال اتباع أفضل الممارسات مثل هذه، يمكن بناء كاشطات أكثر قوة وقابلة للصيانة.

تقنيات القشط المتقدمة

دعونا نلقي نظرة على بعض إمكانيات التجريد الأكثر تقدمًا لـ HTTPX.

كشط صفحات المصادقة

لاستخراج الصفحات التي تمت مصادقتها، يدعم HTTPX أنواع مصادقة متعددة مثل Basic وDigest وBearer auth:

client = httpx.Client(
  auth = (‘username‘, ‘password‘)
)

response = client.get(‘https://api.example.com/users/me‘)

يتم الاحتفاظ ببيانات اعتماد المصادقة عبر الطلبات تلقائيًا.

التعامل مع ملفات تعريف الارتباط

cookies يمكن استخدام المعلمة لإرسال ملفات تعريف الارتباط المخصصة:

client = httpx.Client(
  cookies = {
    ‘sessionId‘: ‘xxxx‘
  }
)

response = client.get(‘https://example.com/dashboard‘) 

ويتم الاحتفاظ بملفات تعريف الارتباط التي يحددها الخادم تلقائيًا في العميل.

الردود المتدفقة

بالنسبة للاستجابات الكبيرة، يمكنك دفقها بشكل تدريجي عن طريق تكرار كائن الاستجابة:

response = client.get(‘https://example.com/bigfile‘)
for chunk in response:
  process(chunk) 

وهذا يتجنب الاضطرار إلى تحميل الاستجابة بأكملها في الذاكرة.

دعم الوكيل

لتوجيه الطلبات من خلال خادم وكيل، proxies يمكن استخدام المعلمة:

proxy = ‘http://192.168.0.1:8888‘ 

client = httpx.Client(proxies = {‘http‘: proxy, ‘https‘: proxy})

يساعد تدوير الوكلاء المختلفين على توزيع الطلبات من عناوين IP مختلفة.

رؤوس مخصصة

يمكنك انتحال رؤوس الطلبات أو ترتيبها بشكل عشوائي مثل وكلاء المستخدم:

client = httpx.Client(headers = {
  ‘User-Agent‘: ‘MyBot 1.0‘ 
})

هذا يحاكي رؤوس المتصفح الحقيقي.

من خلال هذه الميزات الأكثر تقدمًا، يمكن إنشاء كاشطات قوية باستخدام HTTPX وPython.

كاشطات المثال

دعونا الآن نلقي نظرة على بعض الأمثلة على أدوات الكاشط التي تم إنشاؤها باستخدام HTTPX.

ريديت API مكشطة

فيما يلي أداة الكشط الأساسية لواجهة برمجة تطبيقات Reddit:

import httpx

client = httpx.Client()

subreddit = ‘python‘ 
listing = ‘hot‘
limit = 10

response = client.get(f‘https://www.reddit.com/r/{subreddit}/{listing}.json?limit={limit}‘)

data = response.json()[‘data‘]

for post in data[‘children‘]:
   title = post[‘data‘][‘title‘]
   score = post[‘data‘][‘score‘]
   print(f"{title} (Score: {score})")

يؤدي هذا إلى جلب البيانات الموجودة في أهم المشاركات من موقع Python الفرعي. تقوم واجهة برمجة التطبيقات (API) بإرجاع JSON الذي يمكننا تحليله.

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

أخبار المادة مكشطة

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

from bs4 import BeautifulSoup
import httpx

client = httpx.Client()

response = client.get("https://example.com/news")
soup = BeautifulSoup(response.text, ‘html.parser‘)

for article in soup.select(‘.article‘):

  title = article.select_one(‘.article-title‘).text
  content = article.select_one(‘.article-content‘).text

  print(title) 
  print(content)
  print() 

هذا يجد كل شيء .article العناصر، ويستخرج حقلي العنوان والمحتوى، ويطبع المقالات.

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

مكشطة نتائج البحث

وإليك مثال على أداة استخراج نتائج بحث Google:

import httpx

query = "httpx python"
url = f"https://www.google.com/search?q={query}"

client = httpx.Client()
response = client.get(url)

from bs4 import BeautifulSoup
soup = BeautifulSoup(response.text, ‘html.parser‘)

for result in soup.select(‘.tF2Cxc‘):

  title = result.select_one(‘.DKV0Md‘).text
  link = result.select_one(‘.yuRUbf a‘)[‘href‘]

  print(title)
  print(link) 
  print()

يؤدي هذا إلى البحث في Google عن استعلام معين، وتحليل روابط/عناوين النتائج، وطباعتها.

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

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

نبذة عامة

للتلخيص، يوفر HTTPX عميل HTTP قويًا لإنشاء أدوات استخراج بيانات الويب الخاصة بـ Python. فيما يلي بعض النقاط الرئيسية:

  • يحتوي HTTPX على واجهة برمجة تطبيقات بسيطة على نمط الطلبات لتقديم الطلبات.

  • يسمح الدعم غير المتزامن بتقديم الطلبات بشكل متزامن.

  • معالجة قوية للأخطاء من خلال المهلات وإعادة المحاولة والتحقق من الحالة.

  • يمكنك استخلاص صفحات HTML باستخدام Beautiful Soup وJSON APIs بسهولة.

  • يوفر العملاء الدائمون تجمع الاتصالات والجلسات ومعالجة ملفات تعريف الارتباط.

  • تعمل التقنيات المتقدمة مثل الوكلاء والرؤوس والمصادقة على تمكين أدوات الكشط المتطورة.

  • اتبع أفضل الممارسات مثل استخدام التقييد والتأخير العشوائي ووكلاء المستخدم.

يجعل HTTPX من السهل بدء عملية الاستخلاص باستخدام Python. من خلال المعالجة القوية للأخطاء والتزامن غير المتزامن، يمكن تطوير كاشطات قابلة للتطوير.

قم بتجربة HTTPX في مشروع تجريف ويب Python التالي الخاص بك!

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

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

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