Karim shoair commited on
Commit ·
5e95d8a
1
Parent(s): 7a6a272
docs: update the translated readme files with the new content
Browse files- docs/README_AR.md +201 -133
- docs/README_CN.md +201 -133
- docs/README_DE.md +197 -129
- docs/README_ES.md +196 -128
- docs/README_JP.md +208 -140
- docs/README_RU.md +210 -142
docs/README_AR.md
CHANGED
|
@@ -6,8 +6,9 @@
|
|
| 6 |
</picture>
|
| 7 |
</a>
|
| 8 |
<br>
|
| 9 |
-
<small>Web Scraping
|
| 10 |
</h1>
|
|
|
|
| 11 |
<p align="center">
|
| 12 |
<a href="https://github.com/D4Vinci/Scrapling/actions/workflows/tests.yml" alt="Tests">
|
| 13 |
<img alt="Tests" src="https://github.com/D4Vinci/Scrapling/actions/workflows/tests.yml/badge.svg"></a>
|
|
@@ -28,46 +29,47 @@
|
|
| 28 |
</p>
|
| 29 |
|
| 30 |
<p align="center">
|
| 31 |
-
<a href="https://scrapling.readthedocs.io/en/latest/parsing/selection/">
|
| 32 |
-
|
| 33 |
-
</a>
|
| 34 |
-
|
| 35 |
-
<a href="https://scrapling.readthedocs.io/en/latest/
|
| 36 |
-
|
| 37 |
-
</a>
|
| 38 |
-
|
| 39 |
-
<a href="https://scrapling.readthedocs.io/en/latest/
|
| 40 |
-
واجهة سطر الأوامر
|
| 41 |
-
</a>
|
| 42 |
-
·
|
| 43 |
-
<a href="https://scrapling.readthedocs.io/en/latest/ai/mcp-server/">
|
| 44 |
-
وضع MCP
|
| 45 |
-
</a>
|
| 46 |
-
·
|
| 47 |
-
<a href="https://scrapling.readthedocs.io/en/latest/tutorials/migrating_from_beautifulsoup/">
|
| 48 |
-
الانتقال من Beautifulsoup
|
| 49 |
-
</a>
|
| 50 |
</p>
|
| 51 |
|
| 52 |
-
|
| 53 |
|
| 54 |
-
|
| 55 |
|
| 56 |
-
|
| 57 |
|
| 58 |
```python
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
# احصل على
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 68 |
```
|
| 69 |
|
| 70 |
-
|
|
|
|
| 71 |
|
| 72 |
<!-- sponsors -->
|
| 73 |
|
|
@@ -91,138 +93,211 @@ Scrapling ليست مجرد مكتبة أخرى لاستخراج بيانات ا
|
|
| 91 |
|
| 92 |
## الميزات الرئيسية
|
| 93 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 94 |
### جلب متقدم للمواقع مع دعم الجلسات
|
| 95 |
-
- **طلبات HTTP**: طلبات HTTP سريعة وخفية مع فئة `Fetcher`. يمكنها تقليد بصمة TLS للمتصفح والرؤوس واستخدام
|
| 96 |
- **التحميل الديناميكي**: جلب المواقع الديناميكية مع أتمتة كاملة للمتصفح من خلال فئة `DynamicFetcher` التي تدعم Chromium من Playwright و Google Chrome.
|
| 97 |
-
- **تجاوز مكافحة الروبوتات**: قدرات تخفي متقدمة مع `StealthyFetcher` وانتحال
|
| 98 |
- **إدارة الجلسات**: دعم الجلسات المستمرة مع فئات `FetcherSession` و`StealthySession` و`DynamicSession` لإدارة ملفات تعريف الارتباط والحالة عبر الطلبات.
|
|
|
|
|
|
|
| 99 |
- **دعم Async**: دعم async كامل عبر جميع الجوالب وفئات الجلسات async المخصصة.
|
| 100 |
|
| 101 |
### الاستخراج التكيفي والتكامل مع الذكاء الاصطناعي
|
| 102 |
- 🔄 **تتبع العناصر الذكي**: إعادة تحديد موقع العناصر بعد تغييرات الموقع باستخدام خوارزميات التشابه الذكية.
|
| 103 |
- 🎯 **الاختيار المرن الذكي**: محددات CSS، محددات XPath، البحث القائم على الفلاتر، البحث النصي، البحث بالتعبيرات العادية والمزيد.
|
| 104 |
- 🔍 **البحث عن عناصر مشابهة**: تحديد العناصر المشابهة للعناصر الموجودة تلقائياً.
|
| 105 |
-
- 🤖 **خادم MCP للاستخدام مع الذكاء الاصطناعي**: خادم MCP مدمج ل
|
| 106 |
|
| 107 |
-
### بنية عالية الأداء ومختبرة
|
| 108 |
-
- 🚀 **سريع كالبرق**: أداء محسّن يتفوق على معظم مكتبات
|
| 109 |
- 🔋 **فعال في استخدام الذاكرة**: هياكل بيانات محسّنة وتحميل كسول لأقل استخدام للذاكرة.
|
| 110 |
- ⚡ **تسلسل JSON سريع**: أسرع 10 مرات من المكتبة القياسية.
|
| 111 |
-
- 🏗️ **مُختبر
|
| 112 |
|
| 113 |
### تجربة صديقة للمطورين/مستخرجي الويب
|
| 114 |
-
- 🎯 **
|
| 115 |
- 🚀 **استخدمه مباشرة من الطرفية**: اختيارياً، يمكنك استخدام Scrapling لاستخراج عنوان URL دون كتابة سطر واحد من الكود!
|
| 116 |
-
- 🛠️ **واجهة
|
| 117 |
-
- 🧬 **معالجة نصوص محسّنة**: تعبيرات عادية مدمجة وطرق تنظيف وعمليات
|
| 118 |
-
- 📝 **إنشاء محدد تلقائي**: إنشاء محددات CSS/XPath قوية لأي عنصر.
|
| 119 |
-
- 🔌 **واجهة
|
| 120 |
-
- 📘 **تغطية كاملة للأنواع**: تلميحات نوع كاملة لدعم IDE ممتاز وإكمال الكود.
|
| 121 |
- 🔋 **صورة Docker جاهزة**: مع كل إصدار، يتم بناء ودفع صورة Docker تحتوي على جميع المتصفحات تلقائياً.
|
| 122 |
|
| 123 |
## البدء
|
| 124 |
|
|
|
|
|
|
|
| 125 |
### الاستخدام الأساسي
|
|
|
|
| 126 |
```python
|
| 127 |
-
from scrapling.fetchers import Fetcher,
|
| 128 |
-
from scrapling.fetchers import FetcherSession, StealthySession, DynamicSession
|
| 129 |
|
| 130 |
-
# طلبات HTTP مع دعم الجلسات
|
| 131 |
with FetcherSession(impersonate='chrome') as session: # استخدم أحدث إصدار من بصمة TLS لـ Chrome
|
| 132 |
page = session.get('https://quotes.toscrape.com/', stealthy_headers=True)
|
| 133 |
-
quotes = page.css('.quote .text::text')
|
| 134 |
|
| 135 |
# أو استخدم طلبات لمرة واحدة
|
| 136 |
page = Fetcher.get('https://quotes.toscrape.com/')
|
| 137 |
-
quotes = page.css('.quote .text::text')
|
|
|
|
|
|
|
|
|
|
|
|
|
| 138 |
|
| 139 |
-
|
| 140 |
-
with StealthySession(headless=True, solve_cloudflare=True) as session:
|
| 141 |
page = session.fetch('https://nopecha.com/demo/cloudflare', google_search=False)
|
| 142 |
-
data = page.css('#padded_content a')
|
| 143 |
|
| 144 |
# أو استخدم نمط الطلب لمرة واحدة، يفتح المتصفح لهذا الطلب، ثم يغلقه بعد الانتهاء
|
| 145 |
page = StealthyFetcher.fetch('https://nopecha.com/demo/cloudflare')
|
| 146 |
-
data = page.css('#padded_content a')
|
| 147 |
-
|
| 148 |
-
|
| 149 |
-
|
| 150 |
-
|
| 151 |
-
|
| 152 |
-
|
| 153 |
-
|
| 154 |
-
|
| 155 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 156 |
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 157 |
|
| 158 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 159 |
```python
|
| 160 |
-
|
| 161 |
-
|
| 162 |
-
page
|
| 163 |
-
page.css('a', recursive=False) # العناصر المباشرة فقط
|
| 164 |
-
page.css('a', auto_save=True) # حفظ مواضع العناصر تلقائياً
|
| 165 |
-
|
| 166 |
-
# XPath
|
| 167 |
-
page.xpath('//a/text()')
|
| 168 |
-
|
| 169 |
-
# بحث مرن
|
| 170 |
-
page.find_by_text('Python', first_match=True) # البحث بالنص
|
| 171 |
-
page.find_by_regex(r'\d{4}') # البحث بنمط التعبير العادي
|
| 172 |
-
page.find('div', {'class': 'container'}) # البحث بالسمات
|
| 173 |
-
|
| 174 |
-
# التنقل
|
| 175 |
-
element.parent # الحصول على العنصر الوالد
|
| 176 |
-
element.next_sibling # الحصول على الشقيق التالي
|
| 177 |
-
element.children # الحصول على الأطفال
|
| 178 |
-
|
| 179 |
-
# عناصر مشابهة
|
| 180 |
-
similar = page.get_similar(element) # البحث عن عناصر مشابهة
|
| 181 |
-
|
| 182 |
-
# الاستخراج التكيفي
|
| 183 |
-
saved_elements = page.css('.product', auto_save=True)
|
| 184 |
-
# لاحقاً، عندما يتغير الموقع:
|
| 185 |
-
page.css('.product', adaptive=True) # البحث عن العناصر باستخدام المواضع المحفوظة
|
| 186 |
```
|
|
|
|
| 187 |
|
| 188 |
-
###
|
| 189 |
```python
|
| 190 |
-
|
| 191 |
-
|
| 192 |
-
|
| 193 |
-
with FetcherSession() as session:
|
| 194 |
-
|
| 195 |
-
page1 = session.get('https://quotes.toscrape.com/login')
|
| 196 |
-
page2 = session.post('https://quotes.toscrape.com/login', data={'username': 'admin', 'password': 'admin'})
|
| 197 |
-
|
| 198 |
-
# تبديل بصمة المتصفح إذا لزم الأمر
|
| 199 |
page2 = session.get('https://quotes.toscrape.com/', impersonate='firefox135')
|
| 200 |
|
| 201 |
# استخدام جلسة async
|
| 202 |
async with AsyncStealthySession(max_pages=2) as session:
|
| 203 |
tasks = []
|
| 204 |
urls = ['https://example.com/page1', 'https://example.com/page2']
|
| 205 |
-
|
| 206 |
for url in urls:
|
| 207 |
task = session.fetch(url)
|
| 208 |
tasks.append(task)
|
| 209 |
-
|
| 210 |
print(session.get_pool_stats()) # اختياري - حالة مجموعة علامات تبويب المتصفح (مشغول/حر/خطأ)
|
| 211 |
results = await asyncio.gather(*tasks)
|
| 212 |
print(session.get_pool_stats())
|
| 213 |
```
|
| 214 |
|
| 215 |
-
## واجهة سطر الأوامر وال
|
| 216 |
|
| 217 |
-
يتضمن Scrapling
|
| 218 |
|
| 219 |
[](https://asciinema.org/a/736339)
|
| 220 |
|
| 221 |
-
تشغيل
|
| 222 |
```bash
|
| 223 |
scrapling shell
|
| 224 |
```
|
| 225 |
-
استخر
|
| 226 |
```bash
|
| 227 |
scrapling extract get 'https://example.com' content.md
|
| 228 |
scrapling extract get 'https://example.com' content.txt --css-selector '#fromSkipToProducts' --impersonate 'chrome' # جميع العناصر المطابقة لمحدد CSS '#fromSkipToProducts'
|
|
@@ -231,24 +306,24 @@ scrapling extract stealthy-fetch 'https://nopecha.com/demo/cloudflare' captchas.
|
|
| 231 |
```
|
| 232 |
|
| 233 |
> [!NOTE]
|
| 234 |
-
> هناك العديد من الميزات الإضافية، لكننا نريد إبقاء هذه الصفحة موجزة، م
|
| 235 |
|
| 236 |
## معايير الأداء
|
| 237 |
|
| 238 |
-
Scrapling ليس قوياً ف
|
| 239 |
|
| 240 |
### اختبار سرعة استخراج النص (5000 عنصر متداخل)
|
| 241 |
|
| 242 |
-
| # | المكتبة | الوقت (ms) | vs Scrapling |
|
| 243 |
|---|:-----------------:|:----------:|:------------:|
|
| 244 |
-
| 1 | Scrapling |
|
| 245 |
-
| 2 | Parsel/Scrapy | 2.
|
| 246 |
-
| 3 | Raw Lxml | 2.
|
| 247 |
-
| 4 | PyQuery |
|
| 248 |
-
| 5 | Selectolax |
|
| 249 |
-
| 6 |
|
| 250 |
-
| 7 |
|
| 251 |
-
| 8 | BS4 with html5lib |
|
| 252 |
|
| 253 |
|
| 254 |
### أداء تشابه العناصر والبحث النصي
|
|
@@ -257,39 +332,39 @@ Scrapling ليس قوياً فقط - إنه أيضاً سريع بشكل مذه
|
|
| 257 |
|
| 258 |
| المكتبة | الوقت (ms) | vs Scrapling |
|
| 259 |
|-------------|:----------:|:------------:|
|
| 260 |
-
| Scrapling | 2.
|
| 261 |
-
| AutoScraper |
|
| 262 |
|
| 263 |
|
| 264 |
> تمثل جميع المعايير متوسطات أكثر من 100 تشغيل. انظر [benchmarks.py](https://github.com/D4Vinci/Scrapling/blob/main/benchmarks.py) للمنهجية.
|
| 265 |
|
| 266 |
## التثبيت
|
| 267 |
|
| 268 |
-
يتطلب Scrapling Python 3.10 أو أعلى:
|
| 269 |
|
| 270 |
```bash
|
| 271 |
pip install scrapling
|
| 272 |
```
|
| 273 |
|
| 274 |
-
|
| 275 |
|
| 276 |
### التبعيات الاختيارية
|
| 277 |
|
| 278 |
1. إذا كنت ستستخدم أياً من الميزات الإضافية أدناه، أو الجوالب، أو فئاتها، فستحتاج إلى تثبيت تبعيات الجوالب وتبعيات المتصفح الخاصة بها على النحو التالي:
|
| 279 |
```bash
|
| 280 |
pip install "scrapling[fetchers]"
|
| 281 |
-
|
| 282 |
scrapling install
|
| 283 |
```
|
| 284 |
|
| 285 |
-
يقوم هذا بتنزيل جميع المتصفحات، إلى جانب تبعيات النظام وتبعيات معالجة
|
| 286 |
|
| 287 |
2. ميزات إضافية:
|
| 288 |
- تثبيت ميزة خادم MCP:
|
| 289 |
```bash
|
| 290 |
pip install "scrapling[ai]"
|
| 291 |
```
|
| 292 |
-
- تثبيت ميزات
|
| 293 |
```bash
|
| 294 |
pip install "scrapling[shell]"
|
| 295 |
```
|
|
@@ -326,14 +401,7 @@ docker pull ghcr.io/d4vinci/scrapling:latest
|
|
| 326 |
## الشكر والتقدير
|
| 327 |
|
| 328 |
يتضمن هذا المشروع كوداً معدلاً من:
|
| 329 |
-
- Parsel (ترخيص BSD)
|
| 330 |
-
|
| 331 |
-
## الشكر والمراجع
|
| 332 |
-
|
| 333 |
-
- العمل الرائع لـ [Daijro](https://github.com/daijro) على [BrowserForge](https://github.com/daijro/browserforge) و[Camoufox](https://github.com/daijro/camoufox)
|
| 334 |
-
- العمل الرائع لـ [Vinyzu](https://github.com/Vinyzu) على [Botright](https://github.com/Vinyzu/Botright) و[PatchRight](https://github.com/Kaliiiiiiiiii-Vinyzu/patchright)
|
| 335 |
-
- [brotector](https://github.com/kaliiiiiiiiii/brotector) لتقنيات تجاوز اكتشاف المتصفح
|
| 336 |
-
- [fakebrowser](https://github.com/kkoooqq/fakebrowser) و[BotBrowser](https://github.com/botswin/BotBrowser) لأبحاث البصمات
|
| 337 |
|
| 338 |
---
|
| 339 |
-
<div align="center"><small>مصمم ومصنوع بـ ❤️ بواسطة كريم شعير.</small></div><br>
|
|
|
|
| 6 |
</picture>
|
| 7 |
</a>
|
| 8 |
<br>
|
| 9 |
+
<small>Effortless Web Scraping for the Modern Web</small>
|
| 10 |
</h1>
|
| 11 |
+
|
| 12 |
<p align="center">
|
| 13 |
<a href="https://github.com/D4Vinci/Scrapling/actions/workflows/tests.yml" alt="Tests">
|
| 14 |
<img alt="Tests" src="https://github.com/D4Vinci/Scrapling/actions/workflows/tests.yml/badge.svg"></a>
|
|
|
|
| 29 |
</p>
|
| 30 |
|
| 31 |
<p align="center">
|
| 32 |
+
<a href="https://scrapling.readthedocs.io/en/latest/parsing/selection/"><strong>طرق الاختيار</strong></a>
|
| 33 |
+
·
|
| 34 |
+
<a href="https://scrapling.readthedocs.io/en/latest/fetching/choosing/"><strong>اختيار Fetcher</strong></a>
|
| 35 |
+
·
|
| 36 |
+
<a href="https://scrapling.readthedocs.io/en/latest/cli/overview/"><strong>واجهة سطر الأوامر</strong></a>
|
| 37 |
+
·
|
| 38 |
+
<a href="https://scrapling.readthedocs.io/en/latest/ai/mcp-server/"><strong>وضع MCP</strong></a>
|
| 39 |
+
·
|
| 40 |
+
<a href="https://scrapling.readthedocs.io/en/latest/tutorials/migrating_from_beautifulsoup/"><strong>الانتقال من Beautifulsoup</strong></a>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 41 |
</p>
|
| 42 |
|
| 43 |
+
Scrapling هو إطار عمل تكيفي لـ Web Scraping يتعامل مع كل شيء من طلب واحد إلى زحف كامل النطاق.
|
| 44 |
|
| 45 |
+
محلله يتعلم من تغييرات المواقع ويعيد تحديد موقع عناصرك تلقائياً عند تحديث الصفحات. جوالبه تتجاوز أنظمة مكافحة الروبوتات مثل Cloudflare Turnstile مباشرةً. وإطار عمل Spider الخاص به يتيح لك التوسع إلى عمليات زحف متزامنة ومتعددة الجلسات مع إيقاف/استئناف وتدوير تلقائي لـ Proxy - كل ذلك في بضعة أسطر من Python. مكتبة واحدة، بدون تنازلات.
|
| 46 |
|
| 47 |
+
زحف سريع للغاية مع إحصائيات فورية و Streaming. مبني بواسطة مستخرجي الويب لمستخرجي الويب والمستخدمين العاديين، هناك شيء للجميع.
|
| 48 |
|
| 49 |
```python
|
| 50 |
+
from scrapling.fetchers import Fetcher, AsyncFetcher, StealthyFetcher, DynamicFetcher
|
| 51 |
+
StealthyFetcher.adaptive = True
|
| 52 |
+
page = StealthyFetcher.fetch('https://example.com', headless=True, network_idle=True) # احصل على الموقع بشكل خفي!
|
| 53 |
+
products = page.css('.product', auto_save=True) # استخرج بيانات تنجو من تغييرات تصميم الموقع!
|
| 54 |
+
products = page.css('.product', adaptive=True) # لاحقاً، إذا تغيرت بنية الموقع، مرر `adaptive=True` للعثور عليها!
|
| 55 |
+
```
|
| 56 |
+
أو توسع إلى عمليات زحف كاملة
|
| 57 |
+
```python
|
| 58 |
+
from scrapling.spiders import Spider, Response
|
| 59 |
+
|
| 60 |
+
class MySpider(Spider):
|
| 61 |
+
name = "demo"
|
| 62 |
+
start_urls = ["https://example.com/"]
|
| 63 |
+
|
| 64 |
+
async def parse(self, response: Response):
|
| 65 |
+
for item in response.css('.product'):
|
| 66 |
+
yield {"title": item.css('h2::text').get()}
|
| 67 |
+
|
| 68 |
+
MySpider().start()
|
| 69 |
```
|
| 70 |
|
| 71 |
+
|
| 72 |
+
# الرعاة
|
| 73 |
|
| 74 |
<!-- sponsors -->
|
| 75 |
|
|
|
|
| 93 |
|
| 94 |
## الميزات الرئيسية
|
| 95 |
|
| 96 |
+
### Spiders — إطار عمل زحف كامل
|
| 97 |
+
- 🕷️ **واجهة Spider شبيهة بـ Scrapy**: عرّف Spiders مع `start_urls`، و async `parse` callbacks، وكائنات `Request`/`Response`.
|
| 98 |
+
- ⚡ **زحف متزامن**: حدود تزامن قابلة للتكوين، وتحكم بالسرعة حسب النطاق، وتأخيرات التنزيل.
|
| 99 |
+
- 🔄 **دعم الجلسات المتعددة**: واجهة موحدة لطلبات HTTP، ومتصفحات خفية بدون واجهة في Spider واحد — وجّه الطلبات إلى جلسات مختلفة بالمعرّف.
|
| 100 |
+
- 💾 **إيقاف واستئناف**: استمرارية الزحف القائمة على Checkpoint. اضغط Ctrl+C للإيقاف بسلاسة؛ أعد التشغيل للاستئناف من حيث توقفت.
|
| 101 |
+
- 📡 **وضع Streaming**: بث العناصر المستخرجة فور وصولها عبر `async for item in spider.stream()` مع إحصائيات فورية — مثالي لواجهات المستخدم وخطوط الأنابيب وعمليات الزحف الطويلة.
|
| 102 |
+
- 🛡️ **كشف الطلبات المحظورة**: كشف تلقائي وإعادة محاولة للطلبات المحظورة مع منطق قابل للتخصيص.
|
| 103 |
+
- 📦 **تصدير مدمج**: صدّر النتائج عبر الخطافات وخط الأنابيب الخاص بك أو JSON/JSONL المدمج مع `result.items.to_json()` / `result.items.to_jsonl()` على التوالي.
|
| 104 |
+
|
| 105 |
### جلب متقدم للمواقع مع دعم الجلسات
|
| 106 |
+
- **طلبات HTTP**: طلبات HTTP سريعة وخفية مع فئة `Fetcher`. يمكنها تقليد بصمة TLS للمتصفح والرؤوس واستخدام HTTP/3.
|
| 107 |
- **التحميل الديناميكي**: جلب المواقع الديناميكية مع أتمتة كاملة للمتصفح من خلال فئة `DynamicFetcher` التي تدعم Chromium من Playwright و Google Chrome.
|
| 108 |
+
- **تجاوز مكافحة الروبوتات**: قدرات تخفي متقدمة مع `StealthyFetcher` وانتحال fingerprint. يمكنه تجاوز جميع أنواع Turnstile/Interstitial من Cloudflare بسهولة بالأتمتة.
|
| 109 |
- **إدارة الجلسات**: دعم الجلسات المستمرة مع فئات `FetcherSession` و`StealthySession` و`DynamicSession` لإدارة ملفات تعريف الارتباط والحالة عبر الطلبات.
|
| 110 |
+
- **تدوير Proxy**: `ProxyRotator` مدمج مع استراتيجيات round-robin أو مخصصة عبر جميع أنواع الجلسات، بالإضافة إلى تجاوزات Proxy لكل طلب.
|
| 111 |
+
- **حظر النطاقات**: حظر الطلبات إلى نطاقات محددة (ونطاقاتها الفرعية) في الجوالب المعتمدة على المتصفح.
|
| 112 |
- **دعم Async**: دعم async كامل عبر جميع الجوالب وفئات الجلسات async المخصصة.
|
| 113 |
|
| 114 |
### الاستخراج التكيفي والتكامل مع الذكاء الاصطناعي
|
| 115 |
- 🔄 **تتبع العناصر الذكي**: إعادة تحديد موقع العناصر بعد تغييرات الموقع باستخدام خوارزميات التشابه الذكية.
|
| 116 |
- 🎯 **الاختيار المرن الذكي**: محددات CSS، محددات XPath، البحث القائم على الفلاتر، البحث النصي، البحث بالتعبيرات العادية والمزيد.
|
| 117 |
- 🔍 **البحث عن عناصر مشابهة**: تحديد العناصر المشابهة للعناصر الموجودة تلقائياً.
|
| 118 |
+
- 🤖 **خادم MCP للاستخدام مع الذكاء الاصطناعي**: خادم MCP مدمج لـ Web Scraping بمساعدة الذكاء الاصطناعي واستخراج البيانات. يتميز خادم MCP بقدرات قوية مخصصة تستفيد من Scrapling لاستخراج المحتوى المستهدف قبل تمريره إلى الذكاء الاصطناعي (Claude/Cursor/إلخ)، وبالتالي تسريع العمليات وتقليل التكاليف عن طريق تقليل استخدام الرموز. ([فيديو توضيحي](https://www.youtube.com/watch?v=qyFk3ZNwOxE))
|
| 119 |
|
| 120 |
+
### بنية عالية الأداء ومختبرة ميدانياً
|
| 121 |
+
- 🚀 **سريع كالبرق**: أداء محسّن يتفوق على معظم مكتبات Web Scraping في Python.
|
| 122 |
- 🔋 **فعال في استخدام الذاكرة**: هياكل بيانات محسّنة وتحميل كسول لأقل استخدام للذاكرة.
|
| 123 |
- ⚡ **تسلسل JSON سريع**: أسرع 10 مرات من المكتبة القياسية.
|
| 124 |
+
- 🏗️ **مُختبر ميدانياً**: لا يمتلك Scrapling فقط تغطية اختبار بنسبة 92٪ وتغطية كاملة لتلميحات الأنواع، بل تم استخدامه يومياً من قبل مئات مستخرجي الويب خلال العام الماضي.
|
| 125 |
|
| 126 |
### تجربة صديقة للمطورين/مستخرجي الويب
|
| 127 |
+
- 🎯 **Shell تفاعلي لـ Web Scraping**: Shell IPython مدمج اختياري مع تكامل Scrapling، واختصارات، وأدوات جديدة لتسريع تطوير سكريبتات Web Scraping، مثل تحويل طلبات curl إلى طلبات Scrapling وعرض نتائج الطلبات في متصفحك.
|
| 128 |
- 🚀 **استخدمه مباشرة من الطرفية**: اختيارياً، يمكنك استخدام Scrapling لاستخراج عنوان URL دون كتابة سطر واحد من الكود!
|
| 129 |
+
- 🛠️ **واجهة تنقل غنية**: اجتياز DOM متقدم مع طرق التنقل بين العناصر الوالدية والشقيقة والفرعية.
|
| 130 |
+
- 🧬 **معالجة نصوص محسّنة**: تعبيرات عادية مدمجة وطرق تنظيف وعمليات نصية محسّنة.
|
| 131 |
+
- 📝 **إنشاء محددات تلقائي**: إنشاء محددات CSS/XPath قوية لأي عنصر.
|
| 132 |
+
- 🔌 **واجهة مألوفة**: مشابه لـ Scrapy/BeautifulSoup مع نفس العناصر الزائفة المستخدمة في Scrapy/Parsel.
|
| 133 |
+
- 📘 **تغطية كاملة للأنواع**: تلميحات نوع كاملة لدعم IDE ممتاز وإكمال الكود. يتم فحص قاعدة الكود بالكامل تلقائياً بواسطة **PyRight** و**MyPy** مع كل تغيير.
|
| 134 |
- 🔋 **صورة Docker جاهزة**: مع كل إصدار، يتم بناء ودفع صورة Docker تحتوي على جميع المتصفحات تلقائياً.
|
| 135 |
|
| 136 |
## البدء
|
| 137 |
|
| 138 |
+
لنلقِ نظرة سريعة على ما يمكن لـ Scrapling فعله دون التعمق.
|
| 139 |
+
|
| 140 |
### الاستخدام الأساسي
|
| 141 |
+
طلبات HTTP مع دعم الجلسات
|
| 142 |
```python
|
| 143 |
+
from scrapling.fetchers import Fetcher, FetcherSession
|
|
|
|
| 144 |
|
|
|
|
| 145 |
with FetcherSession(impersonate='chrome') as session: # استخدم أحدث إصدار من بصمة TLS لـ Chrome
|
| 146 |
page = session.get('https://quotes.toscrape.com/', stealthy_headers=True)
|
| 147 |
+
quotes = page.css('.quote .text::text').getall()
|
| 148 |
|
| 149 |
# أو استخدم طلبات لمرة واحدة
|
| 150 |
page = Fetcher.get('https://quotes.toscrape.com/')
|
| 151 |
+
quotes = page.css('.quote .text::text').getall()
|
| 152 |
+
```
|
| 153 |
+
وضع التخفي المتقدم
|
| 154 |
+
```python
|
| 155 |
+
from scrapling.fetchers import StealthyFetcher, StealthySession
|
| 156 |
|
| 157 |
+
with StealthySession(headless=True, solve_cloudflare=True) as session: # أبقِ المتصفح مفتوحاً حتى تنتهي
|
|
|
|
| 158 |
page = session.fetch('https://nopecha.com/demo/cloudflare', google_search=False)
|
| 159 |
+
data = page.css('#padded_content a').getall()
|
| 160 |
|
| 161 |
# أو استخدم نمط الطلب لمرة واحدة، يفتح المتصفح لهذا الطلب، ثم يغلقه بعد الانتهاء
|
| 162 |
page = StealthyFetcher.fetch('https://nopecha.com/demo/cloudflare')
|
| 163 |
+
data = page.css('#padded_content a').getall()
|
| 164 |
+
```
|
| 165 |
+
أتمتة المتصفح الكاملة
|
| 166 |
+
```python
|
| 167 |
+
from scrapling.fetchers import DynamicFetcher, DynamicSession
|
| 168 |
+
|
| 169 |
+
with DynamicSession(headless=True, disable_resources=False, network_idle=True) as session: # أبقِ المتصفح مفتوحاً حتى تنتهي
|
| 170 |
+
page = session.fetch('https://quotes.toscrape.com/', load_dom=False)
|
| 171 |
+
data = page.xpath('//span[@class="text"]/text()').getall() # محدد XPath إذا كنت تفضله
|
| 172 |
+
|
| 173 |
+
# أو استخدم نمط الطلب لمرة واحدة، يفتح المتصفح لهذا الطلب، ثم يغلقه بعد الانتهاء
|
| 174 |
+
page = DynamicFetcher.fetch('https://quotes.toscrape.com/')
|
| 175 |
+
data = page.css('.quote .text::text').getall()
|
| 176 |
+
```
|
| 177 |
+
|
| 178 |
+
### Spiders
|
| 179 |
+
ابنِ زواحف كاملة مع طلبات متزامنة وأنواع جلسات متعددة وإيقاف/استئناف:
|
| 180 |
+
```python
|
| 181 |
+
from scrapling.spiders import Spider, Request, Response
|
| 182 |
+
|
| 183 |
+
class QuotesSpider(Spider):
|
| 184 |
+
name = "quotes"
|
| 185 |
+
start_urls = ["https://quotes.toscrape.com/"]
|
| 186 |
+
concurrent_requests = 10
|
| 187 |
+
|
| 188 |
+
async def parse(self, response: Response):
|
| 189 |
+
for quote in response.css('.quote'):
|
| 190 |
+
yield {
|
| 191 |
+
"text": quote.css('.text::text').get(),
|
| 192 |
+
"author": quote.css('.author::text').get(),
|
| 193 |
+
}
|
| 194 |
+
|
| 195 |
+
next_page = response.css('.next a')
|
| 196 |
+
if next_page:
|
| 197 |
+
yield response.follow(next_page[0].attrib['href'])
|
| 198 |
+
|
| 199 |
+
result = QuotesSpider().start()
|
| 200 |
+
print(f"Scraped {len(result.items)} quotes")
|
| 201 |
+
result.items.to_json("quotes.json")
|
| 202 |
+
```
|
| 203 |
+
استخدم أنواع جلسات متعددة في Spider واحد:
|
| 204 |
+
```python
|
| 205 |
+
from scrapling.spiders import Spider, Request, Response
|
| 206 |
+
from scrapling.fetchers import FetcherSession, AsyncStealthySession
|
| 207 |
+
|
| 208 |
+
class MultiSessionSpider(Spider):
|
| 209 |
+
name = "multi"
|
| 210 |
+
start_urls = ["https://example.com/"]
|
| 211 |
+
|
| 212 |
+
def configure_sessions(self, manager):
|
| 213 |
+
manager.add("fast", FetcherSession(impersonate="chrome"))
|
| 214 |
+
manager.add("stealth", AsyncStealthySession(headless=True), lazy=True)
|
| 215 |
+
|
| 216 |
+
async def parse(self, response: Response):
|
| 217 |
+
for link in response.css('a::attr(href)').getall():
|
| 218 |
+
# وجّه الصفحات المحمية عبر جلسة التخفي
|
| 219 |
+
if "protected" in link:
|
| 220 |
+
yield Request(link, sid="stealth")
|
| 221 |
+
else:
|
| 222 |
+
yield Request(link, sid="fast", callback=self.parse) # callback صريح
|
| 223 |
+
```
|
| 224 |
+
أوقف واستأنف عمليات الزحف الطويلة مع Checkpoints بتشغيل Spider هكذا:
|
| 225 |
+
```python
|
| 226 |
+
QuotesSpider(crawldir="./crawl_data").start()
|
| 227 |
```
|
| 228 |
+
اضغط Ctrl+C للإيقاف بسلاسة — يتم حفظ التقدم تلقائياً. لاحقاً، عند تشغيل Spider مرة أخرى، مرر نفس `crawldir`، وسيستأنف من حيث توقف.
|
| 229 |
+
|
| 230 |
+
### التحليل المتقدم والتنقل
|
| 231 |
+
```python
|
| 232 |
+
from scrapling.fetchers import Fetcher
|
| 233 |
|
| 234 |
+
# اختيار عناصر غني وتنقل
|
| 235 |
+
page = Fetcher.get('https://quotes.toscrape.com/')
|
| 236 |
+
|
| 237 |
+
# احصل على الاقتباسات بطرق اختيار متعددة
|
| 238 |
+
quotes = page.css('.quote') # ��حدد CSS
|
| 239 |
+
quotes = page.xpath('//div[@class="quote"]') # XPath
|
| 240 |
+
quotes = page.find_all('div', {'class': 'quote'}) # بأسلوب BeautifulSoup
|
| 241 |
+
# نفس الشيء مثل
|
| 242 |
+
quotes = page.find_all('div', class_='quote')
|
| 243 |
+
quotes = page.find_all(['div'], class_='quote')
|
| 244 |
+
quotes = page.find_all(class_='quote') # وهكذا...
|
| 245 |
+
# البحث عن عنصر بمحتوى النص
|
| 246 |
+
quotes = page.find_by_text('quote', tag='div')
|
| 247 |
+
|
| 248 |
+
# التنقل المتقدم
|
| 249 |
+
quote_text = page.css('.quote')[0].css('.text::text').get()
|
| 250 |
+
quote_text = page.css('.quote').css('.text::text').getall() # محددات متسلسلة
|
| 251 |
+
first_quote = page.css('.quote')[0]
|
| 252 |
+
author = first_quote.next_sibling.css('.author::text')
|
| 253 |
+
parent_container = first_quote.parent
|
| 254 |
+
|
| 255 |
+
# علاقات العناصر والتشابه
|
| 256 |
+
similar_elements = first_quote.find_similar()
|
| 257 |
+
below_elements = first_quote.below_elements()
|
| 258 |
+
```
|
| 259 |
+
يمكنك استخدام المحلل مباشرة إذا كنت لا تريد جلب المواقع كما يلي:
|
| 260 |
```python
|
| 261 |
+
from scrapling.parser import Selector
|
| 262 |
+
|
| 263 |
+
page = Selector("<html>...</html>")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 264 |
```
|
| 265 |
+
وهو يعمل بنفس الطريقة تماماً!
|
| 266 |
|
| 267 |
+
### أمثلة إدارة الجلسات بشكل Async
|
| 268 |
```python
|
| 269 |
+
import asyncio
|
| 270 |
+
from scrapling.fetchers import FetcherSession, AsyncStealthySession, AsyncDynamicSession
|
| 271 |
+
|
| 272 |
+
async with FetcherSession(http3=True) as session: # `FetcherSession` واعٍ بالسياق ويعمل في كلا النمطين المتزامن/async
|
| 273 |
+
page1 = session.get('https://quotes.toscrape.com/')
|
|
|
|
|
|
|
|
|
|
|
|
|
| 274 |
page2 = session.get('https://quotes.toscrape.com/', impersonate='firefox135')
|
| 275 |
|
| 276 |
# استخدام جلسة async
|
| 277 |
async with AsyncStealthySession(max_pages=2) as session:
|
| 278 |
tasks = []
|
| 279 |
urls = ['https://example.com/page1', 'https://example.com/page2']
|
| 280 |
+
|
| 281 |
for url in urls:
|
| 282 |
task = session.fetch(url)
|
| 283 |
tasks.append(task)
|
| 284 |
+
|
| 285 |
print(session.get_pool_stats()) # اختياري - حالة مجموعة علامات تبويب المتصفح (مشغول/حر/خطأ)
|
| 286 |
results = await asyncio.gather(*tasks)
|
| 287 |
print(session.get_pool_stats())
|
| 288 |
```
|
| 289 |
|
| 290 |
+
## واجهة سطر الأوامر والـ Shell التفاعلي
|
| 291 |
|
| 292 |
+
يتضمن Scrapling واجهة سطر أوامر قوية:
|
| 293 |
|
| 294 |
[](https://asciinema.org/a/736339)
|
| 295 |
|
| 296 |
+
تشغيل Shell الـ Web Scraping التفاعلي
|
| 297 |
```bash
|
| 298 |
scrapling shell
|
| 299 |
```
|
| 300 |
+
استخرج الصفحات إلى ملف مباشرة دون برمجة (يستخرج المحتوى داخل وسم `body` افتراضياً). إذا انتهى ملف الإخراج بـ `.txt`، فسيتم استخراج محتوى النص للهدف. إذا انتهى بـ `.md`، فسيكون تمثيل Markdown لمحتوى HTML؛ إذا انتهى بـ `.html`، فسيكون محتوى HTML نفسه.
|
| 301 |
```bash
|
| 302 |
scrapling extract get 'https://example.com' content.md
|
| 303 |
scrapling extract get 'https://example.com' content.txt --css-selector '#fromSkipToProducts' --impersonate 'chrome' # جميع العناصر المطابقة لمحدد CSS '#fromSkipToProducts'
|
|
|
|
| 306 |
```
|
| 307 |
|
| 308 |
> [!NOTE]
|
| 309 |
+
> هناك العديد من الميزات الإضافية، لكننا نريد إبقاء هذه الصفحة موجزة، بما في ذلك خادم MCP والـ Shell التفاعلي لـ Web Scraping. تحقق من الوثائق الكاملة [هنا](https://scrapling.readthedocs.io/en/latest/)
|
| 310 |
|
| 311 |
## معايير الأداء
|
| 312 |
|
| 313 |
+
Scrapling ليس قوياً فحسب — بل هو أيضاً سريع بشكل مذهل. تقارن المعايير التالية محلل Scrapling مع أحدث إصدارات المكتبات الشائعة الأخرى.
|
| 314 |
|
| 315 |
### اختبار سرعة استخراج النص (5000 عنصر متداخل)
|
| 316 |
|
| 317 |
+
| # | المكتبة | الوقت (ms) | vs Scrapling |
|
| 318 |
|---|:-----------------:|:----------:|:------------:|
|
| 319 |
+
| 1 | Scrapling | 2.02 | 1.0x |
|
| 320 |
+
| 2 | Parsel/Scrapy | 2.04 | 1.01 |
|
| 321 |
+
| 3 | Raw Lxml | 2.54 | 1.257 |
|
| 322 |
+
| 4 | PyQuery | 24.17 | ~12x |
|
| 323 |
+
| 5 | Selectolax | 82.63 | ~41x |
|
| 324 |
+
| 6 | MechanicalSoup | 1549.71 | ~767.1x |
|
| 325 |
+
| 7 | BS4 with Lxml | 1584.31 | ~784.3x |
|
| 326 |
+
| 8 | BS4 with html5lib | 3391.91 | ~1679.1x |
|
| 327 |
|
| 328 |
|
| 329 |
### أداء تشابه العناصر والبحث النصي
|
|
|
|
| 332 |
|
| 333 |
| المكتبة | الوقت (ms) | vs Scrapling |
|
| 334 |
|-------------|:----------:|:------------:|
|
| 335 |
+
| Scrapling | 2.39 | 1.0x |
|
| 336 |
+
| AutoScraper | 12.45 | 5.209x |
|
| 337 |
|
| 338 |
|
| 339 |
> تمثل جميع المعايير متوسطات أكثر من 100 تشغيل. انظر [benchmarks.py](https://github.com/D4Vinci/Scrapling/blob/main/benchmarks.py) للمنهجية.
|
| 340 |
|
| 341 |
## التثبيت
|
| 342 |
|
| 343 |
+
يتطلب Scrapling إصدار Python 3.10 أو أعلى:
|
| 344 |
|
| 345 |
```bash
|
| 346 |
pip install scrapling
|
| 347 |
```
|
| 348 |
|
| 349 |
+
يتضمن هذا التثبيت فقط محرك المحلل وتبعياته، بدون أي جوالب أو تبعيات سطر الأوامر.
|
| 350 |
|
| 351 |
### التبعيات الاختيارية
|
| 352 |
|
| 353 |
1. إذا كنت ستستخدم أياً من الميزات الإضافية أدناه، أو الجوالب، أو فئاتها، فستحتاج إلى تثبيت تبعيات الجوالب وتبعيات المتصفح الخاصة بها على النحو التالي:
|
| 354 |
```bash
|
| 355 |
pip install "scrapling[fetchers]"
|
| 356 |
+
|
| 357 |
scrapling install
|
| 358 |
```
|
| 359 |
|
| 360 |
+
يقوم هذا بتنزيل جميع المتصفحات، إلى جانب تبعيات النظام وتبعيات معالجة fingerprint الخاصة بها.
|
| 361 |
|
| 362 |
2. ميزات إضافية:
|
| 363 |
- تثبيت ميزة خادم MCP:
|
| 364 |
```bash
|
| 365 |
pip install "scrapling[ai]"
|
| 366 |
```
|
| 367 |
+
- تثبيت ميزات Shell (Shell الـ Web Scraping وأمر `extract`):
|
| 368 |
```bash
|
| 369 |
pip install "scrapling[shell]"
|
| 370 |
```
|
|
|
|
| 401 |
## الشكر والتقدير
|
| 402 |
|
| 403 |
يتضمن هذا المشروع كوداً معدلاً من:
|
| 404 |
+
- Parsel (ترخيص BSD) — يُستخدم للوحدة الفرعية [translator](https://github.com/D4Vinci/Scrapling/blob/main/scrapling/core/translator.py)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 405 |
|
| 406 |
---
|
| 407 |
+
<div align="center"><small>مصمم ومصنوع بـ ❤️ بواسطة كريم شعير.</small></div><br>
|
docs/README_CN.md
CHANGED
|
@@ -6,8 +6,9 @@
|
|
| 6 |
</picture>
|
| 7 |
</a>
|
| 8 |
<br>
|
| 9 |
-
<small>Web Scraping
|
| 10 |
</h1>
|
|
|
|
| 11 |
<p align="center">
|
| 12 |
<a href="https://github.com/D4Vinci/Scrapling/actions/workflows/tests.yml" alt="Tests">
|
| 13 |
<img alt="Tests" src="https://github.com/D4Vinci/Scrapling/actions/workflows/tests.yml/badge.svg"></a>
|
|
@@ -28,46 +29,47 @@
|
|
| 28 |
</p>
|
| 29 |
|
| 30 |
<p align="center">
|
| 31 |
-
<a href="https://scrapling.readthedocs.io/en/latest/parsing/selection/">
|
| 32 |
-
|
| 33 |
-
</a>
|
| 34 |
-
|
| 35 |
-
<a href="https://scrapling.readthedocs.io/en/latest/
|
| 36 |
-
|
| 37 |
-
</a>
|
| 38 |
-
|
| 39 |
-
<a href="https://scrapling.readthedocs.io/en/latest/
|
| 40 |
-
命令行界面
|
| 41 |
-
</a>
|
| 42 |
-
·
|
| 43 |
-
<a href="https://scrapling.readthedocs.io/en/latest/ai/mcp-server/">
|
| 44 |
-
MCP模式
|
| 45 |
-
</a>
|
| 46 |
-
·
|
| 47 |
-
<a href="https://scrapling.readthedocs.io/en/latest/tutorials/migrating_from_beautifulsoup/">
|
| 48 |
-
从Beautifulsoup迁移
|
| 49 |
-
</a>
|
| 50 |
</p>
|
| 51 |
|
| 52 |
-
|
| 53 |
|
| 54 |
-
|
| 55 |
|
| 56 |
-
|
| 57 |
|
| 58 |
```python
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
# 隐秘地获取网站
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 68 |
```
|
| 69 |
|
| 70 |
-
|
|
|
|
| 71 |
|
| 72 |
<!-- sponsors -->
|
| 73 |
|
|
@@ -91,122 +93,195 @@ Scrapling不仅仅是另一个网页抓取库。它是第一个**自适应**抓
|
|
| 91 |
|
| 92 |
## 主要特性
|
| 93 |
|
| 94 |
-
###
|
| 95 |
-
- **
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 96 |
- **动态加载**:通过`DynamicFetcher`类使用完整的浏览器自动化获取动态网站,支持Playwright的Chromium和Google Chrome。
|
| 97 |
-
- **反机器人绕过**:使用`StealthyFetcher`的高级隐秘功能和
|
| 98 |
-
- **
|
| 99 |
-
- **
|
|
|
|
|
|
|
| 100 |
|
| 101 |
### 自适应抓取和AI集成
|
| 102 |
- 🔄 **智能元素跟踪**:使用智能相似性算法在网站更改后重新定位元素。
|
| 103 |
- 🎯 **智能灵活选择**:CSS选择器、XPath选择器、基于过滤器的搜索、文本搜索、正则表达式搜索等。
|
| 104 |
-
- 🔍 **查找相似元素**:自动定位与找到
|
| 105 |
-
- 🤖 **与AI一起使用的MCP服务器**:内置MCP服务器用于AI辅助
|
| 106 |
|
| 107 |
### 高性能和经过实战测试的架构
|
| 108 |
- 🚀 **闪电般快速**:优化性能超越大多数Python抓取库。
|
| 109 |
- 🔋 **内存高效**:优化的数据结构和延迟加载,最小内存占用。
|
| 110 |
- ⚡ **快速JSON序列化**:比标准库快10倍。
|
| 111 |
-
- 🏗️ **经过实战测试**:Scrapling不仅拥有92%的测试覆盖率和完整的类型提示覆盖率,而且在过去一年中每天被数百名
|
| 112 |
|
| 113 |
-
### 对开发者/
|
| 114 |
-
- 🎯 **交互式
|
| 115 |
- 🚀 **直接从终端使用**:可选地,您可以使用Scrapling抓取URL而无需编写任何代码!
|
| 116 |
- 🛠️ **丰富的导航API**:使用父级、兄弟级和子级导航方法进行高级DOM遍历。
|
| 117 |
- 🧬 **增强的文本处理**:内置正则表达式、清理方法和优化的字符串操作。
|
| 118 |
- 📝 **自动选择器生成**:为任何元素生成强大的CSS/XPath选择器。
|
| 119 |
- 🔌 **熟悉的API**:类似于Scrapy/BeautifulSoup,使用与Scrapy/Parsel相同的伪元素。
|
| 120 |
-
- 📘 **完整的类型覆盖**:完整的类型提示,出色的IDE支持和代码补全。
|
| 121 |
- 🔋 **现成的Docker镜像**:每次发布时,包含所有浏览器的Docker镜像会自动构建和推送。
|
| 122 |
|
| 123 |
## 入门
|
| 124 |
|
|
|
|
|
|
|
| 125 |
### 基本用法
|
|
|
|
| 126 |
```python
|
| 127 |
-
from scrapling.fetchers import Fetcher,
|
| 128 |
-
from scrapling.fetchers import FetcherSession, StealthySession, DynamicSession
|
| 129 |
|
| 130 |
-
#
|
| 131 |
-
with FetcherSession(impersonate='chrome') as session: # 使用Chrome的最新版本TLS指纹
|
| 132 |
page = session.get('https://quotes.toscrape.com/', stealthy_headers=True)
|
| 133 |
-
quotes = page.css('.quote .text::text')
|
| 134 |
|
| 135 |
# 或使用一次性请求
|
| 136 |
page = Fetcher.get('https://quotes.toscrape.com/')
|
| 137 |
-
quotes = page.css('.quote .text::text')
|
|
|
|
|
|
|
|
|
|
|
|
|
| 138 |
|
| 139 |
-
#
|
| 140 |
-
with StealthySession(headless=True, solve_cloudflare=True) as session:
|
| 141 |
page = session.fetch('https://nopecha.com/demo/cloudflare', google_search=False)
|
| 142 |
-
data = page.css('#padded_content a')
|
| 143 |
|
| 144 |
# 或使用一次性请求样式,为此请求打开浏览器,完成后关闭
|
| 145 |
page = StealthyFetcher.fetch('https://nopecha.com/demo/cloudflare')
|
| 146 |
-
data = page.css('#padded_content a')
|
| 147 |
-
|
| 148 |
-
|
| 149 |
-
|
| 150 |
-
|
| 151 |
-
|
| 152 |
-
|
| 153 |
-
|
| 154 |
-
|
| 155 |
-
|
|
|
|
|
|
|
|
|
|
| 156 |
```
|
| 157 |
|
| 158 |
-
###
|
|
|
|
| 159 |
```python
|
| 160 |
-
|
| 161 |
-
|
| 162 |
-
|
| 163 |
-
|
| 164 |
-
|
| 165 |
-
|
| 166 |
-
|
| 167 |
-
|
| 168 |
-
|
| 169 |
-
|
| 170 |
-
|
| 171 |
-
|
| 172 |
-
|
| 173 |
-
|
| 174 |
-
|
| 175 |
-
|
| 176 |
-
|
| 177 |
-
|
| 178 |
-
|
| 179 |
-
|
| 180 |
-
|
| 181 |
-
|
| 182 |
-
# 自适应抓取
|
| 183 |
-
saved_elements = page.css('.product', auto_save=True)
|
| 184 |
-
# 之后,当网站更改时:
|
| 185 |
-
page.css('.product', adaptive=True) # 使用保存的位置查找元素
|
| 186 |
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 187 |
|
| 188 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 189 |
```python
|
| 190 |
-
from scrapling.
|
| 191 |
-
|
| 192 |
-
|
| 193 |
-
|
| 194 |
-
|
| 195 |
-
|
| 196 |
-
|
| 197 |
-
|
| 198 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 199 |
page2 = session.get('https://quotes.toscrape.com/', impersonate='firefox135')
|
| 200 |
|
| 201 |
-
#
|
| 202 |
async with AsyncStealthySession(max_pages=2) as session:
|
| 203 |
tasks = []
|
| 204 |
urls = ['https://example.com/page1', 'https://example.com/page2']
|
| 205 |
-
|
| 206 |
for url in urls:
|
| 207 |
task = session.fetch(url)
|
| 208 |
tasks.append(task)
|
| 209 |
-
|
| 210 |
print(session.get_pool_stats()) # 可选 - 浏览器标签池的状态(忙/空闲/错误)
|
| 211 |
results = await asyncio.gather(*tasks)
|
| 212 |
print(session.get_pool_stats())
|
|
@@ -214,11 +289,11 @@ async with AsyncStealthySession(max_pages=2) as session:
|
|
| 214 |
|
| 215 |
## CLI和交互式Shell
|
| 216 |
|
| 217 |
-
Scrapling
|
| 218 |
|
| 219 |
[](https://asciinema.org/a/736339)
|
| 220 |
|
| 221 |
-
启动交互式
|
| 222 |
```bash
|
| 223 |
scrapling shell
|
| 224 |
```
|
|
@@ -231,24 +306,24 @@ scrapling extract stealthy-fetch 'https://nopecha.com/demo/cloudflare' captchas.
|
|
| 231 |
```
|
| 232 |
|
| 233 |
> [!NOTE]
|
| 234 |
-
> 还有许多其他功能,但我们希望保持此页面简洁,
|
| 235 |
|
| 236 |
## 性能基准
|
| 237 |
|
| 238 |
-
Scrapling不仅功能强大——它还速度极快
|
| 239 |
|
| 240 |
### 文本提取速度测试(5000个嵌套元素)
|
| 241 |
|
| 242 |
-
| # | 库 | 时间(ms) | vs Scrapling |
|
| 243 |
-
|---|:-----------------:|:-------:|:------------:|
|
| 244 |
-
| 1 | Scrapling |
|
| 245 |
-
| 2 | Parsel/Scrapy |
|
| 246 |
-
| 3 | Raw Lxml | 2.
|
| 247 |
-
| 4 | PyQuery |
|
| 248 |
-
| 5 | Selectolax |
|
| 249 |
-
| 6 |
|
| 250 |
-
| 7 |
|
| 251 |
-
| 8 | BS4 with html5lib |
|
| 252 |
|
| 253 |
|
| 254 |
### 元素相似性和文本搜索性能
|
|
@@ -256,9 +331,9 @@ Scrapling不仅功能强大——它还速度极快,自0.3版本以来的更
|
|
| 256 |
Scrapling的自适应元素查找功能明显优于替代方案:
|
| 257 |
|
| 258 |
| 库 | 时间(ms) | vs Scrapling |
|
| 259 |
-
|-------------|:------:|:------------:|
|
| 260 |
-
| Scrapling |
|
| 261 |
-
| AutoScraper |
|
| 262 |
|
| 263 |
|
| 264 |
> 所有基准测试代表100+次运行的平均值。请参阅[benchmarks.py](https://github.com/D4Vinci/Scrapling/blob/main/benchmarks.py)了解方法。
|
|
@@ -271,25 +346,25 @@ Scrapling需要Python 3.10或更高版本:
|
|
| 271 |
pip install scrapling
|
| 272 |
```
|
| 273 |
|
| 274 |
-
|
| 275 |
|
| 276 |
### 可选依赖项
|
| 277 |
|
| 278 |
-
1. 如果您要使用以下任何额外功能、
|
| 279 |
```bash
|
| 280 |
pip install "scrapling[fetchers]"
|
| 281 |
-
|
| 282 |
scrapling install
|
| 283 |
```
|
| 284 |
|
| 285 |
-
这会下载所有浏览器,以及它们的系统依赖项和
|
| 286 |
|
| 287 |
2. 额外功能:
|
| 288 |
- 安装MCP服务器功能:
|
| 289 |
```bash
|
| 290 |
pip install "scrapling[ai]"
|
| 291 |
```
|
| 292 |
-
- 安装
|
| 293 |
```bash
|
| 294 |
pip install "scrapling[shell]"
|
| 295 |
```
|
|
@@ -328,12 +403,5 @@ docker pull ghcr.io/d4vinci/scrapling:latest
|
|
| 328 |
此项目包含改编自以下内容的代码:
|
| 329 |
- Parsel(BSD许可证)——用于[translator](https://github.com/D4Vinci/Scrapling/blob/main/scrapling/core/translator.py)子模块
|
| 330 |
|
| 331 |
-
## 感谢和参考
|
| 332 |
-
|
| 333 |
-
- [Daijro](https://github.com/daijro)在[BrowserForge](https://github.com/daijro/browserforge)和[Camoufox](https://github.com/daijro/camoufox)上的出色工作
|
| 334 |
-
- [Vinyzu](https://github.com/Vinyzu)在[Botright](https://github.com/Vinyzu/Botright)和[PatchRight](https://github.com/Kaliiiiiiiiii-Vinyzu/patchright)上的出色工作
|
| 335 |
-
- [brotector](https://github.com/kaliiiiiiiiii/brotector)提供的浏览器检测绕过技术
|
| 336 |
-
- [fakebrowser](https://github.com/kkoooqq/fakebrowser)和[BotBrowser](https://github.com/botswin/BotBrowser)提供的指纹识别研究
|
| 337 |
-
|
| 338 |
---
|
| 339 |
-
<div align="center"><small>由Karim Shoair用❤️设计和制作。</small></div><br>
|
|
|
|
| 6 |
</picture>
|
| 7 |
</a>
|
| 8 |
<br>
|
| 9 |
+
<small>Effortless Web Scraping for the Modern Web</small>
|
| 10 |
</h1>
|
| 11 |
+
|
| 12 |
<p align="center">
|
| 13 |
<a href="https://github.com/D4Vinci/Scrapling/actions/workflows/tests.yml" alt="Tests">
|
| 14 |
<img alt="Tests" src="https://github.com/D4Vinci/Scrapling/actions/workflows/tests.yml/badge.svg"></a>
|
|
|
|
| 29 |
</p>
|
| 30 |
|
| 31 |
<p align="center">
|
| 32 |
+
<a href="https://scrapling.readthedocs.io/en/latest/parsing/selection/"><strong>选择方法</strong></a>
|
| 33 |
+
·
|
| 34 |
+
<a href="https://scrapling.readthedocs.io/en/latest/fetching/choosing/"><strong>选择Fetcher</strong></a>
|
| 35 |
+
·
|
| 36 |
+
<a href="https://scrapling.readthedocs.io/en/latest/cli/overview/"><strong>CLI</strong></a>
|
| 37 |
+
·
|
| 38 |
+
<a href="https://scrapling.readthedocs.io/en/latest/ai/mcp-server/"><strong>MCP模式</strong></a>
|
| 39 |
+
·
|
| 40 |
+
<a href="https://scrapling.readthedocs.io/en/latest/tutorials/migrating_from_beautifulsoup/"><strong>从Beautifulsoup迁移</strong></a>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 41 |
</p>
|
| 42 |
|
| 43 |
+
Scrapling是一个自适应Web Scraping框架,能处理从单个请求到大规模爬取的一切需求。
|
| 44 |
|
| 45 |
+
它的解析器能够从网站变化中学习,并在页面更新时自动重新定位您的元素。它的Fetcher能够开箱即用地绕过Cloudflare Turnstile等反机器人系统。它的Spider框架让您可以扩展到并发、多Session爬取,支持暂停/恢复和自动Proxy轮换——只需几行Python代码。一个库,零妥协。
|
| 46 |
|
| 47 |
+
极速爬取,实时统计和Streaming。由Web Scraper为Web Scraper和普通用户而构建,每个人都能找到适合自己的功能。
|
| 48 |
|
| 49 |
```python
|
| 50 |
+
from scrapling.fetchers import Fetcher, AsyncFetcher, StealthyFetcher, DynamicFetcher
|
| 51 |
+
StealthyFetcher.adaptive = True
|
| 52 |
+
page = StealthyFetcher.fetch('https://example.com', headless=True, network_idle=True) # 隐秘地获取网站!
|
| 53 |
+
products = page.css('.product', auto_save=True) # 抓取在网站设计变更后仍能存活的数据!
|
| 54 |
+
products = page.css('.product', adaptive=True) # 之后,如果网站结构改变,传递 `adaptive=True` 来找到它们!
|
| 55 |
+
```
|
| 56 |
+
或扩展为完整爬取
|
| 57 |
+
```python
|
| 58 |
+
from scrapling.spiders import Spider, Response
|
| 59 |
+
|
| 60 |
+
class MySpider(Spider):
|
| 61 |
+
name = "demo"
|
| 62 |
+
start_urls = ["https://example.com/"]
|
| 63 |
+
|
| 64 |
+
async def parse(self, response: Response):
|
| 65 |
+
for item in response.css('.product'):
|
| 66 |
+
yield {"title": item.css('h2::text').get()}
|
| 67 |
+
|
| 68 |
+
MySpider().start()
|
| 69 |
```
|
| 70 |
|
| 71 |
+
|
| 72 |
+
# 赞助商
|
| 73 |
|
| 74 |
<!-- sponsors -->
|
| 75 |
|
|
|
|
| 93 |
|
| 94 |
## 主要特性
|
| 95 |
|
| 96 |
+
### Spider — 完整的爬取框架
|
| 97 |
+
- 🕷️ **类Scrapy的Spider API**:使用`start_urls`、async `parse` callback和`Request`/`Response`对象定义Spider。
|
| 98 |
+
- ⚡ **并发爬取**:可配置的并发限制、按域名节流和下载延迟。
|
| 99 |
+
- 🔄 **多Session支持**:统一接口,支持HTTP请求和隐秘无头浏览器在同一个Spider中使用——通过ID将请求路由到不同的Session。
|
| 100 |
+
- 💾 **暂停与恢复**:基于Checkpoint的爬取持久化。按Ctrl+C优雅关闭;重启后从上次停止的地方继续。
|
| 101 |
+
- 📡 **Streaming模式**:通过`async for item in spider.stream()`以实时统计Streaming抓取的数据——非常适合UI、管道和长时间运行的爬取。
|
| 102 |
+
- 🛡️ **被阻止请求检测**:自动检测并重试被阻止的请求,支持自定义逻辑。
|
| 103 |
+
- 📦 **内置导出**:通过钩子和您自己的管道导出结果,或使用内置的JSON/JSONL,分别通过`result.items.to_json()`/`result.items.to_jsonl()`。
|
| 104 |
+
|
| 105 |
+
### 支持Session的高级网站获取
|
| 106 |
+
- **HTTP请求**:使用`Fetcher`类进行快速和隐秘的HTTP请求。可以模拟浏览器的TLS fingerprint、标头并使用HTTP/3。
|
| 107 |
- **动态加载**:通过`DynamicFetcher`类使用完整的浏览器自动化获取动态网站,支持Playwright的Chromium和Google Chrome。
|
| 108 |
+
- **反机器人绕过**:使用`StealthyFetcher`的高级隐秘功能和fingerprint伪装。可以轻松自动绕过所有类型的Cloudflare Turnstile/Interstitial。
|
| 109 |
+
- **Session管理**:使用`FetcherSession`、`StealthySession`和`DynamicSession`类实现持久化Session支持,用于跨请求的cookie和状态管理。
|
| 110 |
+
- **Proxy轮换**:内置`ProxyRotator`,支持轮询或自定义策略,适用于所有Session类型,并支持按请求覆盖Proxy。
|
| 111 |
+
- **域名屏蔽**:在基于浏览器的Fetcher中屏蔽对特定域名(及其子域名)的请求。
|
| 112 |
+
- **Async支持**:所有Fetcher和专用async Session类的完整async支持。
|
| 113 |
|
| 114 |
### 自适应抓取和AI集成
|
| 115 |
- 🔄 **智能元素跟踪**:使用智能相似性算法在网站更改后重新定位元素。
|
| 116 |
- 🎯 **智能灵活选择**:CSS选择器、XPath选择器、基于过滤器的搜索、文本搜索、正则表达式搜索等。
|
| 117 |
+
- 🔍 **查找相似元素**:自动定位与已找到元素相似的元素。
|
| 118 |
+
- 🤖 **与AI一起使用的MCP服务器**:内置MCP服务器用于AI辅助Web Scraping和数据提取。MCP服务器具有强大的自定义功能,利用Scrapling在将内容传递给AI(Claude/Cursor等)之前提取目标内容,从而加快操作并通过最小化token使用来降低成本。([演示视频](https://www.youtube.com/watch?v=qyFk3ZNwOxE))
|
| 119 |
|
| 120 |
### 高性能和经过实战测试的架构
|
| 121 |
- 🚀 **闪电般快速**:优化性能超越大多数Python抓取库。
|
| 122 |
- 🔋 **内存高效**:优化的数据结构和延迟加载,最小内存占用。
|
| 123 |
- ⚡ **快速JSON序列化**:比标准库快10倍。
|
| 124 |
+
- 🏗️ **经过实战测试**:Scrapling不仅拥有92%的测试覆盖率和完整的类型提示覆盖率,而且在过去一年中每天被数百名Web Scraper使用。
|
| 125 |
|
| 126 |
+
### 对开发者/Web Scraper友好的体验
|
| 127 |
+
- 🎯 **交互式Web Scraping Shell**:可选的内置IPython Shell,具有Scrapling集成、快捷方式和新工具,可加快Web Scraping脚本开发,例如将curl请求转换为Scrapling请求并在浏览器中查看请求结果。
|
| 128 |
- 🚀 **直接从终端使用**:可选地,您可以使用Scrapling抓取URL而无需编写任何代码!
|
| 129 |
- 🛠️ **丰富的导航API**:使用父级、兄弟级和子级导航方法进行高级DOM遍历。
|
| 130 |
- 🧬 **增强的文本处理**:内置正则表达式、清理方法和优化的字符串操作。
|
| 131 |
- 📝 **自动选择器生成**:为任何元素生成强大的CSS/XPath选择器。
|
| 132 |
- 🔌 **熟悉的API**:类似于Scrapy/BeautifulSoup,使用与Scrapy/Parsel相同的伪元素。
|
| 133 |
+
- 📘 **完整的类型覆盖**:完整的类型提示,出色的IDE支持和代码补全。整个代码库在每次更改时都会自动使用**PyRight**和**MyPy**扫描。
|
| 134 |
- 🔋 **现成的Docker镜像**:每次发布时,包含所有浏览器的Docker镜像会自动构建和推送。
|
| 135 |
|
| 136 |
## 入门
|
| 137 |
|
| 138 |
+
让我们快速展示Scrapling的功能,无需深入了解。
|
| 139 |
+
|
| 140 |
### 基本用法
|
| 141 |
+
支持Session的HTTP请求
|
| 142 |
```python
|
| 143 |
+
from scrapling.fetchers import Fetcher, FetcherSession
|
|
|
|
| 144 |
|
| 145 |
+
with FetcherSession(impersonate='chrome') as session: # 使用Chrome的最新版本TLS fingerprint
|
|
|
|
| 146 |
page = session.get('https://quotes.toscrape.com/', stealthy_headers=True)
|
| 147 |
+
quotes = page.css('.quote .text::text').getall()
|
| 148 |
|
| 149 |
# 或使用一次性请求
|
| 150 |
page = Fetcher.get('https://quotes.toscrape.com/')
|
| 151 |
+
quotes = page.css('.quote .text::text').getall()
|
| 152 |
+
```
|
| 153 |
+
高级隐秘模式
|
| 154 |
+
```python
|
| 155 |
+
from scrapling.fetchers import StealthyFetcher, StealthySession
|
| 156 |
|
| 157 |
+
with StealthySession(headless=True, solve_cloudflare=True) as session: # 保持浏览器打开直到完成
|
|
|
|
| 158 |
page = session.fetch('https://nopecha.com/demo/cloudflare', google_search=False)
|
| 159 |
+
data = page.css('#padded_content a').getall()
|
| 160 |
|
| 161 |
# 或使用一次性请求样式,为此请求打开浏览器,完成后关闭
|
| 162 |
page = StealthyFetcher.fetch('https://nopecha.com/demo/cloudflare')
|
| 163 |
+
data = page.css('#padded_content a').getall()
|
| 164 |
+
```
|
| 165 |
+
完整的浏览器自动化
|
| 166 |
+
```python
|
| 167 |
+
from scrapling.fetchers import DynamicFetcher, DynamicSession
|
| 168 |
+
|
| 169 |
+
with DynamicSession(headless=True, disable_resources=False, network_idle=True) as session: # 保持浏览器打开直到完成
|
| 170 |
+
page = session.fetch('https://quotes.toscrape.com/', load_dom=False)
|
| 171 |
+
data = page.xpath('//span[@class="text"]/text()').getall() # 如果您偏好XPath选择器
|
| 172 |
+
|
| 173 |
+
# 或使用一次性请求样式,为此请求打开浏览器,完成后关闭
|
| 174 |
+
page = DynamicFetcher.fetch('https://quotes.toscrape.com/')
|
| 175 |
+
data = page.css('.quote .text::text').getall()
|
| 176 |
```
|
| 177 |
|
| 178 |
+
### Spider
|
| 179 |
+
构建具有并发请求、多种Session类型和暂停/恢复功能的完整爬虫:
|
| 180 |
```python
|
| 181 |
+
from scrapling.spiders import Spider, Request, Response
|
| 182 |
+
|
| 183 |
+
class QuotesSpider(Spider):
|
| 184 |
+
name = "quotes"
|
| 185 |
+
start_urls = ["https://quotes.toscrape.com/"]
|
| 186 |
+
concurrent_requests = 10
|
| 187 |
+
|
| 188 |
+
async def parse(self, response: Response):
|
| 189 |
+
for quote in response.css('.quote'):
|
| 190 |
+
yield {
|
| 191 |
+
"text": quote.css('.text::text').get(),
|
| 192 |
+
"author": quote.css('.author::text').get(),
|
| 193 |
+
}
|
| 194 |
+
|
| 195 |
+
next_page = response.css('.next a')
|
| 196 |
+
if next_page:
|
| 197 |
+
yield response.follow(next_page[0].attrib['href'])
|
| 198 |
+
|
| 199 |
+
result = QuotesSpider().start()
|
| 200 |
+
print(f"抓取了 {len(result.items)} 条引用")
|
| 201 |
+
result.items.to_json("quotes.json")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 202 |
```
|
| 203 |
+
在单个Spider中使用多种Session类型:
|
| 204 |
+
```python
|
| 205 |
+
from scrapling.spiders import Spider, Request, Response
|
| 206 |
+
from scrapling.fetchers import FetcherSession, AsyncStealthySession
|
| 207 |
+
|
| 208 |
+
class MultiSessionSpider(Spider):
|
| 209 |
+
name = "multi"
|
| 210 |
+
start_urls = ["https://example.com/"]
|
| 211 |
+
|
| 212 |
+
def configure_sessions(self, manager):
|
| 213 |
+
manager.add("fast", FetcherSession(impersonate="chrome"))
|
| 214 |
+
manager.add("stealth", AsyncStealthySession(headless=True), lazy=True)
|
| 215 |
+
|
| 216 |
+
async def parse(self, response: Response):
|
| 217 |
+
for link in response.css('a::attr(href)').getall():
|
| 218 |
+
# 将受保护的页面路由到隐秘Session
|
| 219 |
+
if "protected" in link:
|
| 220 |
+
yield Request(link, sid="stealth")
|
| 221 |
+
else:
|
| 222 |
+
yield Request(link, sid="fast", callback=self.parse) # 显式callback
|
| 223 |
+
```
|
| 224 |
+
通过如下方式运行Spider来暂停和恢复长时间爬取,使用Checkpoint:
|
| 225 |
+
```python
|
| 226 |
+
QuotesSpider(crawldir="./crawl_data").start()
|
| 227 |
+
```
|
| 228 |
+
按Ctrl+C优雅暂停——进度会自动保存。之后,当您再次启动Spider时,传递相同的`crawldir`,它将从上次停止的地方继续。
|
| 229 |
+
|
| 230 |
+
### 高级解析与导航
|
| 231 |
+
```python
|
| 232 |
+
from scrapling.fetchers import Fetcher
|
| 233 |
+
|
| 234 |
+
# 丰富的元素选择和导航
|
| 235 |
+
page = Fetcher.get('https://quotes.toscrape.com/')
|
| 236 |
|
| 237 |
+
# 使用多种选择方法获取引用
|
| 238 |
+
quotes = page.css('.quote') # CSS选择器
|
| 239 |
+
quotes = page.xpath('//div[@class="quote"]') # XPath
|
| 240 |
+
quotes = page.find_all('div', {'class': 'quote'}) # BeautifulSoup风格
|
| 241 |
+
# 等同于
|
| 242 |
+
quotes = page.find_all('div', class_='quote')
|
| 243 |
+
quotes = page.find_all(['div'], class_='quote')
|
| 244 |
+
quotes = page.find_all(class_='quote') # 等等...
|
| 245 |
+
# 按文本内容查找元素
|
| 246 |
+
quotes = page.find_by_text('quote', tag='div')
|
| 247 |
+
|
| 248 |
+
# 高级导航
|
| 249 |
+
quote_text = page.css('.quote')[0].css('.text::text').get()
|
| 250 |
+
quote_text = page.css('.quote').css('.text::text').getall() # 链式选择器
|
| 251 |
+
first_quote = page.css('.quote')[0]
|
| 252 |
+
author = first_quote.next_sibling.css('.author::text')
|
| 253 |
+
parent_container = first_quote.parent
|
| 254 |
+
|
| 255 |
+
# 元素关系和相似性
|
| 256 |
+
similar_elements = first_quote.find_similar()
|
| 257 |
+
below_elements = first_quote.below_elements()
|
| 258 |
+
```
|
| 259 |
+
如果您不想获取网站,可以直接使用解析器,如下所示:
|
| 260 |
```python
|
| 261 |
+
from scrapling.parser import Selector
|
| 262 |
+
|
| 263 |
+
page = Selector("<html>...</html>")
|
| 264 |
+
```
|
| 265 |
+
用法完全相同!
|
| 266 |
+
|
| 267 |
+
### Async Session管理示例
|
| 268 |
+
```python
|
| 269 |
+
import asyncio
|
| 270 |
+
from scrapling.fetchers import FetcherSession, AsyncStealthySession, AsyncDynamicSession
|
| 271 |
+
|
| 272 |
+
async with FetcherSession(http3=True) as session: # `FetcherSession`是上下文感知的,可以在sync/async模式下工作
|
| 273 |
+
page1 = session.get('https://quotes.toscrape.com/')
|
| 274 |
page2 = session.get('https://quotes.toscrape.com/', impersonate='firefox135')
|
| 275 |
|
| 276 |
+
# Async Session用法
|
| 277 |
async with AsyncStealthySession(max_pages=2) as session:
|
| 278 |
tasks = []
|
| 279 |
urls = ['https://example.com/page1', 'https://example.com/page2']
|
| 280 |
+
|
| 281 |
for url in urls:
|
| 282 |
task = session.fetch(url)
|
| 283 |
tasks.append(task)
|
| 284 |
+
|
| 285 |
print(session.get_pool_stats()) # 可选 - 浏览器标签池的状态(忙/空闲/错误)
|
| 286 |
results = await asyncio.gather(*tasks)
|
| 287 |
print(session.get_pool_stats())
|
|
|
|
| 289 |
|
| 290 |
## CLI和交互式Shell
|
| 291 |
|
| 292 |
+
Scrapling包含强大的命令行界面:
|
| 293 |
|
| 294 |
[](https://asciinema.org/a/736339)
|
| 295 |
|
| 296 |
+
启动交互式Web Scraping Shell
|
| 297 |
```bash
|
| 298 |
scrapling shell
|
| 299 |
```
|
|
|
|
| 306 |
```
|
| 307 |
|
| 308 |
> [!NOTE]
|
| 309 |
+
> 还有许多其他功能,但我们希望保持此页面简洁,包括MCP服务器和交互式Web Scraping Shell。查看完整文档[这里](https://scrapling.readthedocs.io/en/latest/)
|
| 310 |
|
| 311 |
## 性能基准
|
| 312 |
|
| 313 |
+
Scrapling不仅功能强大——它还速度极快。以下基准测试将Scrapling的解析器与其他流行库的最新版本进行了比较。
|
| 314 |
|
| 315 |
### 文本提取速度测试(5000个嵌套元素)
|
| 316 |
|
| 317 |
+
| # | 库 | 时间(ms) | vs Scrapling |
|
| 318 |
+
|---|:-----------------:|:---------:|:------------:|
|
| 319 |
+
| 1 | Scrapling | 2.02 | 1.0x |
|
| 320 |
+
| 2 | Parsel/Scrapy | 2.04 | 1.01 |
|
| 321 |
+
| 3 | Raw Lxml | 2.54 | 1.257 |
|
| 322 |
+
| 4 | PyQuery | 24.17 | ~12x |
|
| 323 |
+
| 5 | Selectolax | 82.63 | ~41x |
|
| 324 |
+
| 6 | MechanicalSoup | 1549.71 | ~767.1x |
|
| 325 |
+
| 7 | BS4 with Lxml | 1584.31 | ~784.3x |
|
| 326 |
+
| 8 | BS4 with html5lib | 3391.91 | ~1679.1x |
|
| 327 |
|
| 328 |
|
| 329 |
### 元素相似性和文本搜索性能
|
|
|
|
| 331 |
Scrapling的自适应元素查找功能明显优于替代方案:
|
| 332 |
|
| 333 |
| 库 | 时间(ms) | vs Scrapling |
|
| 334 |
+
|-------------|:---------:|:------------:|
|
| 335 |
+
| Scrapling | 2.39 | 1.0x |
|
| 336 |
+
| AutoScraper | 12.45 | 5.209x |
|
| 337 |
|
| 338 |
|
| 339 |
> 所有基准测试代表100+次运行的平均值。请参阅[benchmarks.py](https://github.com/D4Vinci/Scrapling/blob/main/benchmarks.py)了解方法。
|
|
|
|
| 346 |
pip install scrapling
|
| 347 |
```
|
| 348 |
|
| 349 |
+
此安装仅包括解析器引擎及其依赖项,没有任何Fetcher或命令行依赖项。
|
| 350 |
|
| 351 |
### 可选依赖项
|
| 352 |
|
| 353 |
+
1. 如果您要使用以下任何额外功能、Fetcher或它们的类,您将需要安装Fetcher的依赖项和它们的浏览器依赖项,如下所示:
|
| 354 |
```bash
|
| 355 |
pip install "scrapling[fetchers]"
|
| 356 |
+
|
| 357 |
scrapling install
|
| 358 |
```
|
| 359 |
|
| 360 |
+
这会下载所有浏览器,以及它们的系统依赖项和fingerprint操作依赖项。
|
| 361 |
|
| 362 |
2. 额外功能:
|
| 363 |
- 安装MCP服务器功能:
|
| 364 |
```bash
|
| 365 |
pip install "scrapling[ai]"
|
| 366 |
```
|
| 367 |
+
- 安装Shell功能(Web Scraping Shell和`extract`命令):
|
| 368 |
```bash
|
| 369 |
pip install "scrapling[shell]"
|
| 370 |
```
|
|
|
|
| 403 |
此项目包含改编自以下内容的代码:
|
| 404 |
- Parsel(BSD许可证)——用于[translator](https://github.com/D4Vinci/Scrapling/blob/main/scrapling/core/translator.py)子模块
|
| 405 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 406 |
---
|
| 407 |
+
<div align="center"><small>由Karim Shoair用❤️设计和制作。</small></div><br>
|
docs/README_DE.md
CHANGED
|
@@ -6,8 +6,9 @@
|
|
| 6 |
</picture>
|
| 7 |
</a>
|
| 8 |
<br>
|
| 9 |
-
<small>Web Scraping
|
| 10 |
</h1>
|
|
|
|
| 11 |
<p align="center">
|
| 12 |
<a href="https://github.com/D4Vinci/Scrapling/actions/workflows/tests.yml" alt="Tests">
|
| 13 |
<img alt="Tests" src="https://github.com/D4Vinci/Scrapling/actions/workflows/tests.yml/badge.svg"></a>
|
|
@@ -28,46 +29,47 @@
|
|
| 28 |
</p>
|
| 29 |
|
| 30 |
<p align="center">
|
| 31 |
-
<a href="https://scrapling.readthedocs.io/en/latest/parsing/selection/">
|
| 32 |
-
|
| 33 |
-
</a>
|
| 34 |
-
|
| 35 |
-
<a href="https://scrapling.readthedocs.io/en/latest/
|
| 36 |
-
|
| 37 |
-
</a>
|
| 38 |
-
|
| 39 |
-
<a href="https://scrapling.readthedocs.io/en/latest/
|
| 40 |
-
CLI
|
| 41 |
-
</a>
|
| 42 |
-
·
|
| 43 |
-
<a href="https://scrapling.readthedocs.io/en/latest/ai/mcp-server/">
|
| 44 |
-
MCP-Modus
|
| 45 |
-
</a>
|
| 46 |
-
·
|
| 47 |
-
<a href="https://scrapling.readthedocs.io/en/latest/tutorials/migrating_from_beautifulsoup/">
|
| 48 |
-
Migration von Beautifulsoup
|
| 49 |
-
</a>
|
| 50 |
</p>
|
| 51 |
|
| 52 |
-
|
| 53 |
|
| 54 |
-
|
| 55 |
|
| 56 |
-
|
| 57 |
|
| 58 |
```python
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
200
|
| 65 |
-
>> products = page.css('.product', auto_save=True) # Scrapen Sie Daten, die Website-Designänderungen überleben!
|
| 66 |
-
>> # Später, wenn sich die Website-Struktur ändert, übergeben Sie `adaptive=True`
|
| 67 |
-
>> products = page.css('.product', adaptive=True) # und Scrapling findet sie trotzdem!
|
| 68 |
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 69 |
|
| 70 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 71 |
|
| 72 |
<!-- sponsors -->
|
| 73 |
|
|
@@ -91,12 +93,23 @@ Für das moderne Web entwickelt, bietet Scrapling **seine eigene schnelle Parsin
|
|
| 91 |
|
| 92 |
## Hauptmerkmale
|
| 93 |
|
| 94 |
-
###
|
| 95 |
-
- **
|
| 96 |
-
- **
|
| 97 |
-
- **
|
| 98 |
-
- **
|
| 99 |
-
- **
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 100 |
|
| 101 |
### Adaptives Scraping & KI-Integration
|
| 102 |
- 🔄 **Intelligente Element-Verfolgung**: Elemente nach Website-Änderungen mit intelligenten Ähnlichkeitsalgorithmen neu lokalisieren.
|
|
@@ -110,103 +123,165 @@ Für das moderne Web entwickelt, bietet Scrapling **seine eigene schnelle Parsin
|
|
| 110 |
- ⚡ **Schnelle JSON-Serialisierung**: 10x schneller als die Standardbibliothek.
|
| 111 |
- 🏗️ **Praxiserprobt**: Scrapling hat nicht nur eine Testabdeckung von 92% und eine vollständige Type-Hints-Abdeckung, sondern wird seit dem letzten Jahr täglich von Hunderten von Web Scrapern verwendet.
|
| 112 |
|
| 113 |
-
### Entwickler/Web-Scraper-freundliche Erfahrung
|
| 114 |
- 🎯 **Interaktive Web-Scraping-Shell**: Optionale integrierte IPython-Shell mit Scrapling-Integration, Shortcuts und neuen Tools zur Beschleunigung der Web-Scraping-Skriptentwicklung, wie das Konvertieren von Curl-Anfragen in Scrapling-Anfragen und das Anzeigen von Anfrageergebnissen in Ihrem Browser.
|
| 115 |
- 🚀 **Direkt vom Terminal aus verwenden**: Optional können Sie Scrapling verwenden, um eine URL zu scrapen, ohne eine einzige Codezeile zu schreiben!
|
| 116 |
- 🛠️ **Umfangreiche Navigations-API**: Erweiterte DOM-Traversierung mit Eltern-, Geschwister- und Kind-Navigationsmethoden.
|
| 117 |
- 🧬 **Verbesserte Textverarbeitung**: Integrierte Regex, Bereinigungsmethoden und optimierte String-Operationen.
|
| 118 |
- 📝 **Automatische Selektorgenerierung**: Robuste CSS/XPath-Selektoren für jedes Element generieren.
|
| 119 |
- 🔌 **Vertraute API**: Ähnlich wie Scrapy/BeautifulSoup mit denselben Pseudo-Elementen, die in Scrapy/Parsel verwendet werden.
|
| 120 |
-
- 📘 **Vollständige Typabdeckung**: Vollständige Type Hints für hervorragende IDE-Unterstützung und Code-Vervollständigung.
|
| 121 |
- 🔋 **Fertiges Docker-Image**: Mit jeder Veröffentlichung wird automatisch ein Docker-Image erstellt und gepusht, das alle Browser enthält.
|
| 122 |
|
| 123 |
## Erste Schritte
|
| 124 |
|
|
|
|
|
|
|
| 125 |
### Grundlegende Verwendung
|
|
|
|
| 126 |
```python
|
| 127 |
-
from scrapling.fetchers import Fetcher,
|
| 128 |
-
from scrapling.fetchers import FetcherSession, StealthySession, DynamicSession
|
| 129 |
|
| 130 |
-
#
|
| 131 |
-
with FetcherSession(impersonate='chrome') as session: # Verwenden Sie die neueste Version von Chromes TLS-Fingerabdruck
|
| 132 |
page = session.get('https://quotes.toscrape.com/', stealthy_headers=True)
|
| 133 |
-
quotes = page.css('.quote .text::text')
|
| 134 |
|
| 135 |
-
# Oder
|
| 136 |
page = Fetcher.get('https://quotes.toscrape.com/')
|
| 137 |
-
quotes = page.css('.quote .text::text')
|
|
|
|
|
|
|
|
|
|
|
|
|
| 138 |
|
| 139 |
-
|
| 140 |
-
with StealthySession(headless=True, solve_cloudflare=True) as session:
|
| 141 |
page = session.fetch('https://nopecha.com/demo/cloudflare', google_search=False)
|
| 142 |
-
data = page.css('#padded_content a')
|
| 143 |
|
| 144 |
-
# Oder
|
| 145 |
page = StealthyFetcher.fetch('https://nopecha.com/demo/cloudflare')
|
| 146 |
-
data = page.css('#padded_content a')
|
| 147 |
-
|
| 148 |
-
|
| 149 |
-
|
| 150 |
-
|
| 151 |
-
|
| 152 |
-
|
| 153 |
-
|
| 154 |
-
|
| 155 |
-
|
|
|
|
|
|
|
|
|
|
| 156 |
```
|
| 157 |
|
| 158 |
-
###
|
|
|
|
| 159 |
```python
|
| 160 |
-
|
| 161 |
-
|
| 162 |
-
|
| 163 |
-
|
| 164 |
-
|
| 165 |
-
|
| 166 |
-
|
| 167 |
-
|
| 168 |
-
|
| 169 |
-
|
| 170 |
-
|
| 171 |
-
|
| 172 |
-
|
| 173 |
-
|
| 174 |
-
|
| 175 |
-
|
| 176 |
-
|
| 177 |
-
|
| 178 |
-
|
| 179 |
-
|
| 180 |
-
|
| 181 |
-
|
| 182 |
-
# Adaptives Scraping
|
| 183 |
-
saved_elements = page.css('.product', auto_save=True)
|
| 184 |
-
# Später, wenn sich die Website ändert:
|
| 185 |
-
page.css('.product', adaptive=True) # Elemente mithilfe gespeicherter Positionen finden
|
| 186 |
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 187 |
|
| 188 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 189 |
```python
|
| 190 |
-
from scrapling.
|
| 191 |
-
|
| 192 |
-
|
| 193 |
-
|
| 194 |
-
|
| 195 |
-
|
| 196 |
-
|
| 197 |
-
|
| 198 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 199 |
page2 = session.get('https://quotes.toscrape.com/', impersonate='firefox135')
|
| 200 |
|
| 201 |
-
# Async-
|
| 202 |
async with AsyncStealthySession(max_pages=2) as session:
|
| 203 |
tasks = []
|
| 204 |
urls = ['https://example.com/page1', 'https://example.com/page2']
|
| 205 |
-
|
| 206 |
for url in urls:
|
| 207 |
task = session.fetch(url)
|
| 208 |
tasks.append(task)
|
| 209 |
-
|
| 210 |
print(session.get_pool_stats()) # Optional - Der Status des Browser-Tab-Pools (beschäftigt/frei/Fehler)
|
| 211 |
results = await asyncio.gather(*tasks)
|
| 212 |
print(session.get_pool_stats())
|
|
@@ -214,7 +289,7 @@ async with AsyncStealthySession(max_pages=2) as session:
|
|
| 214 |
|
| 215 |
## CLI & Interaktive Shell
|
| 216 |
|
| 217 |
-
Scrapling
|
| 218 |
|
| 219 |
[](https://asciinema.org/a/736339)
|
| 220 |
|
|
@@ -222,7 +297,7 @@ Interaktive Web-Scraping-Shell starten
|
|
| 222 |
```bash
|
| 223 |
scrapling shell
|
| 224 |
```
|
| 225 |
-
Seiten direkt ohne Programmierung in eine Datei extrahieren (
|
| 226 |
```bash
|
| 227 |
scrapling extract get 'https://example.com' content.md
|
| 228 |
scrapling extract get 'https://example.com' content.txt --css-selector '#fromSkipToProducts' --impersonate 'chrome' # Alle Elemente, die dem CSS-Selektor '#fromSkipToProducts' entsprechen
|
|
@@ -231,24 +306,24 @@ scrapling extract stealthy-fetch 'https://nopecha.com/demo/cloudflare' captchas.
|
|
| 231 |
```
|
| 232 |
|
| 233 |
> [!NOTE]
|
| 234 |
-
> Es gibt viele zusätzliche Funktionen, aber wir möchten diese Seite prägnant halten,
|
| 235 |
|
| 236 |
## Leistungsbenchmarks
|
| 237 |
|
| 238 |
-
Scrapling ist nicht nur leistungsstark
|
| 239 |
|
| 240 |
### Textextraktions-Geschwindigkeitstest (5000 verschachtelte Elemente)
|
| 241 |
|
| 242 |
-
| # | Bibliothek | Zeit (ms) | vs Scrapling |
|
| 243 |
|---|:-----------------:|:---------:|:------------:|
|
| 244 |
-
| 1 | Scrapling |
|
| 245 |
-
| 2 | Parsel/Scrapy | 2.
|
| 246 |
-
| 3 | Raw Lxml |
|
| 247 |
-
| 4 | PyQuery |
|
| 248 |
-
| 5 | Selectolax |
|
| 249 |
-
| 6 |
|
| 250 |
-
| 7 |
|
| 251 |
-
| 8 | BS4 with html5lib |
|
| 252 |
|
| 253 |
|
| 254 |
### Element-Ähnlichkeit & Textsuche-Leistung
|
|
@@ -257,8 +332,8 @@ Scraplings adaptive Element-Finding-Fähigkeiten übertreffen Alternativen deutl
|
|
| 257 |
|
| 258 |
| Bibliothek | Zeit (ms) | vs Scrapling |
|
| 259 |
|-------------|:---------:|:------------:|
|
| 260 |
-
| Scrapling | 2.
|
| 261 |
-
| AutoScraper |
|
| 262 |
|
| 263 |
|
| 264 |
> Alle Benchmarks stellen Durchschnittswerte von über 100 Durchläufen dar. Siehe [benchmarks.py](https://github.com/D4Vinci/Scrapling/blob/main/benchmarks.py) für die Methodik.
|
|
@@ -271,18 +346,18 @@ Scrapling erfordert Python 3.10 oder höher:
|
|
| 271 |
pip install scrapling
|
| 272 |
```
|
| 273 |
|
| 274 |
-
|
| 275 |
|
| 276 |
### Optionale Abhängigkeiten
|
| 277 |
|
| 278 |
1. Wenn Sie eine der folgenden zusätzlichen Funktionen, die Fetcher oder ihre Klassen verwenden möchten, müssen Sie die Abhängigkeiten der Fetcher und ihre Browser-Abhängigkeiten wie folgt installieren:
|
| 279 |
```bash
|
| 280 |
pip install "scrapling[fetchers]"
|
| 281 |
-
|
| 282 |
scrapling install
|
| 283 |
```
|
| 284 |
|
| 285 |
-
Dies lädt alle Browser zusammen mit ihren Systemabhängigkeiten und
|
| 286 |
|
| 287 |
2. Zusätzliche Funktionen:
|
| 288 |
- MCP-Server-Funktion installieren:
|
|
@@ -326,14 +401,7 @@ Diese Arbeit ist unter der BSD-3-Clause-Lizenz lizenziert.
|
|
| 326 |
## Danksagungen
|
| 327 |
|
| 328 |
Dieses Projekt enthält angepassten Code von:
|
| 329 |
-
- Parsel (BSD-Lizenz)
|
| 330 |
-
|
| 331 |
-
## Dank und Referenzen
|
| 332 |
-
|
| 333 |
-
- [Daijros](https://github.com/daijro) brillante Arbeit an [BrowserForge](https://github.com/daijro/browserforge) und [Camoufox](https://github.com/daijro/camoufox)
|
| 334 |
-
- [Vinyzus](https://github.com/Vinyzu) brillante Arbeit an [Botright](https://github.com/Vinyzu/Botright) und [PatchRight](https://github.com/Kaliiiiiiiiii-Vinyzu/patchright)
|
| 335 |
-
- [brotector](https://github.com/kaliiiiiiiiii/brotector) für Browser-Erkennungs-Umgehungstechniken
|
| 336 |
-
- [fakebrowser](https://github.com/kkoooqq/fakebrowser) und [BotBrowser](https://github.com/botswin/BotBrowser) für Fingerprinting-Forschung
|
| 337 |
|
| 338 |
---
|
| 339 |
-
<div align="center"><small>Entworfen und hergestellt mit ❤️ von Karim Shoair.</small></div><br>
|
|
|
|
| 6 |
</picture>
|
| 7 |
</a>
|
| 8 |
<br>
|
| 9 |
+
<small>Effortless Web Scraping for the Modern Web</small>
|
| 10 |
</h1>
|
| 11 |
+
|
| 12 |
<p align="center">
|
| 13 |
<a href="https://github.com/D4Vinci/Scrapling/actions/workflows/tests.yml" alt="Tests">
|
| 14 |
<img alt="Tests" src="https://github.com/D4Vinci/Scrapling/actions/workflows/tests.yml/badge.svg"></a>
|
|
|
|
| 29 |
</p>
|
| 30 |
|
| 31 |
<p align="center">
|
| 32 |
+
<a href="https://scrapling.readthedocs.io/en/latest/parsing/selection/"><strong>Auswahlmethoden</strong></a>
|
| 33 |
+
·
|
| 34 |
+
<a href="https://scrapling.readthedocs.io/en/latest/fetching/choosing/"><strong>Einen Fetcher wählen</strong></a>
|
| 35 |
+
·
|
| 36 |
+
<a href="https://scrapling.readthedocs.io/en/latest/cli/overview/"><strong>CLI</strong></a>
|
| 37 |
+
·
|
| 38 |
+
<a href="https://scrapling.readthedocs.io/en/latest/ai/mcp-server/"><strong>MCP-Modus</strong></a>
|
| 39 |
+
·
|
| 40 |
+
<a href="https://scrapling.readthedocs.io/en/latest/tutorials/migrating_from_beautifulsoup/"><strong>Migration von Beautifulsoup</strong></a>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 41 |
</p>
|
| 42 |
|
| 43 |
+
Scrapling ist ein adaptives Web-Scraping-Framework, das alles abdeckt -- von einer einzelnen Anfrage bis hin zu einem umfassenden Crawl.
|
| 44 |
|
| 45 |
+
Sein Parser lernt aus Website-Änderungen und lokalisiert Ihre Elemente automatisch neu, wenn sich Seiten aktualisieren. Seine Fetcher umgehen Anti-Bot-Systeme wie Cloudflare Turnstile direkt ab Werk. Und sein Spider-Framework ermöglicht es Ihnen, auf parallele Multi-Session-Crawls mit Pause & Resume und automatischer Proxy-Rotation hochzuskalieren -- alles in wenigen Zeilen Python. Eine Bibliothek, keine Kompromisse.
|
| 46 |
|
| 47 |
+
Blitzschnelle Crawls mit Echtzeit-Statistiken und Streaming. Von Web Scrapern für Web Scraper und normale Benutzer entwickelt, ist für jeden etwas dabei.
|
| 48 |
|
| 49 |
```python
|
| 50 |
+
from scrapling.fetchers import Fetcher, AsyncFetcher, StealthyFetcher, DynamicFetcher
|
| 51 |
+
StealthyFetcher.adaptive = True
|
| 52 |
+
page = StealthyFetcher.fetch('https://example.com', headless=True, network_idle=True) # Website unbemerkt abrufen!
|
| 53 |
+
products = page.css('.product', auto_save=True) # Daten scrapen, die Website-Designänderungen überleben!
|
| 54 |
+
products = page.css('.product', adaptive=True) # Später, wenn sich die Website-Struktur ändert, `adaptive=True` übergeben, um sie zu finden!
|
|
|
|
|
|
|
|
|
|
|
|
|
| 55 |
```
|
| 56 |
+
Oder auf vollständige Crawls hochskalieren
|
| 57 |
+
```python
|
| 58 |
+
from scrapling.spiders import Spider, Response
|
| 59 |
+
|
| 60 |
+
class MySpider(Spider):
|
| 61 |
+
name = "demo"
|
| 62 |
+
start_urls = ["https://example.com/"]
|
| 63 |
|
| 64 |
+
async def parse(self, response: Response):
|
| 65 |
+
for item in response.css('.product'):
|
| 66 |
+
yield {"title": item.css('h2::text').get()}
|
| 67 |
+
|
| 68 |
+
MySpider().start()
|
| 69 |
+
```
|
| 70 |
+
|
| 71 |
+
|
| 72 |
+
# Sponsoren
|
| 73 |
|
| 74 |
<!-- sponsors -->
|
| 75 |
|
|
|
|
| 93 |
|
| 94 |
## Hauptmerkmale
|
| 95 |
|
| 96 |
+
### Spiders -- Ein vollständiges Crawling-Framework
|
| 97 |
+
- 🕷️ **Scrapy-ähnliche Spider-API**: Definieren Sie Spiders mit `start_urls`, async `parse` Callbacks und `Request`/`Response`-Objekten.
|
| 98 |
+
- ⚡ **Paralleles Crawling**: Konfigurierbare Parallelitätslimits, domainbezogenes Throttling und Download-Verzögerungen.
|
| 99 |
+
- 🔄 **Multi-Session-Unterstützung**: Einheitliche Schnittstelle für HTTP-Anfragen und heimliche Headless-Browser in einem einzigen Spider -- leiten Sie Anfragen per ID an verschiedene Sessions weiter.
|
| 100 |
+
- 💾 **Pause & Resume**: Checkpoint-basierte Crawl-Persistenz. Drücken Sie Strg+C für ein kontrolliertes Herunterfahren; starten Sie neu, um dort fortzufahren, wo Sie aufgehört haben.
|
| 101 |
+
- 📡 **Streaming-Modus**: Gescrapte Elemente in Echtzeit streamen über `async for item in spider.stream()` mit Echtzeit-Statistiken -- ideal für UI, Pipelines und lang laufende Crawls.
|
| 102 |
+
- 🛡️ **Erkennung blockierter Anfragen**: Automatische Erkennung und Wiederholung blockierter Anfragen mit anpassbarer Logik.
|
| 103 |
+
- 📦 **Integrierter Export**: Ergebnisse über Hooks und Ihre eigene Pipeline oder den integrierten JSON/JSONL-Export mit `result.items.to_json()` / `result.items.to_jsonl()` exportieren.
|
| 104 |
+
|
| 105 |
+
### Erweitertes Website-Abrufen mit Session-Unterstützung
|
| 106 |
+
- **HTTP-Anfragen**: Schnelle und heimliche HTTP-Anfragen mit der `Fetcher`-Klasse. Kann Browser-TLS-Fingerprints und Header imitieren und HTTP/3 verwenden.
|
| 107 |
+
- **Dynamisches Laden**: Dynamische Websites mit vollständiger Browser-Automatisierung über die `DynamicFetcher`-Klasse abrufen, die Playwrights Chromium und Google Chrome unterstützt.
|
| 108 |
+
- **Anti-Bot-Umgehung**: Erweiterte Stealth-Fähigkeiten mit `StealthyFetcher` und Fingerprint-Spoofing. Kann alle Arten von Cloudflares Turnstile/Interstitial einfach mit Automatisierung umgehen.
|
| 109 |
+
- **Session-Verwaltung**: Persistente Session-Unterstützung mit den Klassen `FetcherSession`, `StealthySession` und `DynamicSession` für Cookie- und Zustandsverwaltung über Anfragen hinweg.
|
| 110 |
+
- **Proxy-Rotation**: Integrierter `ProxyRotator` mit Round-Robin- oder benutzerdefinierten Strategien über alle Session-Typen hinweg, plus Proxy-Überschreibungen pro Anfrage.
|
| 111 |
+
- **Domain-Blockierung**: Anfragen an bestimmte Domains (und deren Subdomains) in browserbasierten Fetchern blockieren.
|
| 112 |
+
- **Async-Unterstützung**: Vollständige async-Unterstützung über alle Fetcher und dedizierte async Session-Klassen hinweg.
|
| 113 |
|
| 114 |
### Adaptives Scraping & KI-Integration
|
| 115 |
- 🔄 **Intelligente Element-Verfolgung**: Elemente nach Website-Änderungen mit intelligenten Ähnlichkeitsalgorithmen neu lokalisieren.
|
|
|
|
| 123 |
- ⚡ **Schnelle JSON-Serialisierung**: 10x schneller als die Standardbibliothek.
|
| 124 |
- 🏗️ **Praxiserprobt**: Scrapling hat nicht nur eine Testabdeckung von 92% und eine vollständige Type-Hints-Abdeckung, sondern wird seit dem letzten Jahr täglich von Hunderten von Web Scrapern verwendet.
|
| 125 |
|
| 126 |
+
### Entwickler-/Web-Scraper-freundliche Erfahrung
|
| 127 |
- 🎯 **Interaktive Web-Scraping-Shell**: Optionale integrierte IPython-Shell mit Scrapling-Integration, Shortcuts und neuen Tools zur Beschleunigung der Web-Scraping-Skriptentwicklung, wie das Konvertieren von Curl-Anfragen in Scrapling-Anfragen und das Anzeigen von Anfrageergebnissen in Ihrem Browser.
|
| 128 |
- 🚀 **Direkt vom Terminal aus verwenden**: Optional können Sie Scrapling verwenden, um eine URL zu scrapen, ohne eine einzige Codezeile zu schreiben!
|
| 129 |
- 🛠️ **Umfangreiche Navigations-API**: Erweiterte DOM-Traversierung mit Eltern-, Geschwister- und Kind-Navigationsmethoden.
|
| 130 |
- 🧬 **Verbesserte Textverarbeitung**: Integrierte Regex, Bereinigungsmethoden und optimierte String-Operationen.
|
| 131 |
- 📝 **Automatische Selektorgenerierung**: Robuste CSS/XPath-Selektoren für jedes Element generieren.
|
| 132 |
- 🔌 **Vertraute API**: Ähnlich wie Scrapy/BeautifulSoup mit denselben Pseudo-Elementen, die in Scrapy/Parsel verwendet werden.
|
| 133 |
+
- 📘 **Vollständige Typabdeckung**: Vollständige Type Hints für hervorragende IDE-Unterstützung und Code-Vervollständigung. Die gesamte Codebasis wird bei jeder Änderung automatisch mit **PyRight** und **MyPy** gescannt.
|
| 134 |
- 🔋 **Fertiges Docker-Image**: Mit jeder Veröffentlichung wird automatisch ein Docker-Image erstellt und gepusht, das alle Browser enthält.
|
| 135 |
|
| 136 |
## Erste Schritte
|
| 137 |
|
| 138 |
+
Hier ein kurzer Überblick über das, was Scrapling kann, ohne zu sehr ins Detail zu gehen.
|
| 139 |
+
|
| 140 |
### Grundlegende Verwendung
|
| 141 |
+
HTTP-Anfragen mit Session-Unterstützung
|
| 142 |
```python
|
| 143 |
+
from scrapling.fetchers import Fetcher, FetcherSession
|
|
|
|
| 144 |
|
| 145 |
+
with FetcherSession(impersonate='chrome') as session: # Neueste Version von Chromes TLS-Fingerprint verwenden
|
|
|
|
| 146 |
page = session.get('https://quotes.toscrape.com/', stealthy_headers=True)
|
| 147 |
+
quotes = page.css('.quote .text::text').getall()
|
| 148 |
|
| 149 |
+
# Oder einmalige Anfragen verwenden
|
| 150 |
page = Fetcher.get('https://quotes.toscrape.com/')
|
| 151 |
+
quotes = page.css('.quote .text::text').getall()
|
| 152 |
+
```
|
| 153 |
+
Erweiterter Stealth-Modus
|
| 154 |
+
```python
|
| 155 |
+
from scrapling.fetchers import StealthyFetcher, StealthySession
|
| 156 |
|
| 157 |
+
with StealthySession(headless=True, solve_cloudflare=True) as session: # Browser offen halten, bis Sie fertig sind
|
|
|
|
| 158 |
page = session.fetch('https://nopecha.com/demo/cloudflare', google_search=False)
|
| 159 |
+
data = page.css('#padded_content a').getall()
|
| 160 |
|
| 161 |
+
# Oder einmaligen Anfragenstil verwenden: öffnet den Browser für diese Anfrage und schließt ihn nach Abschluss
|
| 162 |
page = StealthyFetcher.fetch('https://nopecha.com/demo/cloudflare')
|
| 163 |
+
data = page.css('#padded_content a').getall()
|
| 164 |
+
```
|
| 165 |
+
Vollständige Browser-Automatisierung
|
| 166 |
+
```python
|
| 167 |
+
from scrapling.fetchers import DynamicFetcher, DynamicSession
|
| 168 |
+
|
| 169 |
+
with DynamicSession(headless=True, disable_resources=False, network_idle=True) as session: # Browser offen halten, bis Sie fertig sind
|
| 170 |
+
page = session.fetch('https://quotes.toscrape.com/', load_dom=False)
|
| 171 |
+
data = page.xpath('//span[@class="text"]/text()').getall() # XPath-Selektor, falls bevorzugt
|
| 172 |
+
|
| 173 |
+
# Oder einmaligen Anfragenstil verwenden: öffnet den Browser für diese Anfrage und schließt ihn nach Abschluss
|
| 174 |
+
page = DynamicFetcher.fetch('https://quotes.toscrape.com/')
|
| 175 |
+
data = page.css('.quote .text::text').getall()
|
| 176 |
```
|
| 177 |
|
| 178 |
+
### Spiders
|
| 179 |
+
Vollständige Crawler mit parallelen Anfragen, mehreren Session-Typen und Pause & Resume erstellen:
|
| 180 |
```python
|
| 181 |
+
from scrapling.spiders import Spider, Request, Response
|
| 182 |
+
|
| 183 |
+
class QuotesSpider(Spider):
|
| 184 |
+
name = "quotes"
|
| 185 |
+
start_urls = ["https://quotes.toscrape.com/"]
|
| 186 |
+
concurrent_requests = 10
|
| 187 |
+
|
| 188 |
+
async def parse(self, response: Response):
|
| 189 |
+
for quote in response.css('.quote'):
|
| 190 |
+
yield {
|
| 191 |
+
"text": quote.css('.text::text').get(),
|
| 192 |
+
"author": quote.css('.author::text').get(),
|
| 193 |
+
}
|
| 194 |
+
|
| 195 |
+
next_page = response.css('.next a')
|
| 196 |
+
if next_page:
|
| 197 |
+
yield response.follow(next_page[0].attrib['href'])
|
| 198 |
+
|
| 199 |
+
result = QuotesSpider().start()
|
| 200 |
+
print(f"{len(result.items)} Zitate gescrapt")
|
| 201 |
+
result.items.to_json("quotes.json")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 202 |
```
|
| 203 |
+
Mehrere Session-Typen in einem einzigen Spider verwenden:
|
| 204 |
+
```python
|
| 205 |
+
from scrapling.spiders import Spider, Request, Response
|
| 206 |
+
from scrapling.fetchers import FetcherSession, AsyncStealthySession
|
| 207 |
+
|
| 208 |
+
class MultiSessionSpider(Spider):
|
| 209 |
+
name = "multi"
|
| 210 |
+
start_urls = ["https://example.com/"]
|
| 211 |
+
|
| 212 |
+
def configure_sessions(self, manager):
|
| 213 |
+
manager.add("fast", FetcherSession(impersonate="chrome"))
|
| 214 |
+
manager.add("stealth", AsyncStealthySession(headless=True), lazy=True)
|
| 215 |
+
|
| 216 |
+
async def parse(self, response: Response):
|
| 217 |
+
for link in response.css('a::attr(href)').getall():
|
| 218 |
+
# Geschützte Seiten über die Stealth-Session leiten
|
| 219 |
+
if "protected" in link:
|
| 220 |
+
yield Request(link, sid="stealth")
|
| 221 |
+
else:
|
| 222 |
+
yield Request(link, sid="fast", callback=self.parse) # Expliziter Callback
|
| 223 |
+
```
|
| 224 |
+
Lange Crawls mit Checkpoints pausieren und fortsetzen, indem Sie den Spider so starten:
|
| 225 |
+
```python
|
| 226 |
+
QuotesSpider(crawldir="./crawl_data").start()
|
| 227 |
+
```
|
| 228 |
+
Drücken Sie Strg+C, um kontrolliert zu pausieren -- der Fortschritt wird automatisch gespeichert. Wenn Sie den Spider später erneut starten, übergeben Sie dasselbe `crawldir`, und er setzt dort fort, wo er aufgehört hat.
|
| 229 |
+
|
| 230 |
+
### Erweitertes Parsing & Navigation
|
| 231 |
+
```python
|
| 232 |
+
from scrapling.fetchers import Fetcher
|
| 233 |
+
|
| 234 |
+
# Umfangreiche Elementauswahl und Navigation
|
| 235 |
+
page = Fetcher.get('https://quotes.toscrape.com/')
|
| 236 |
|
| 237 |
+
# Zitate mit verschiedenen Auswahlmethoden abrufen
|
| 238 |
+
quotes = page.css('.quote') # CSS-Selektor
|
| 239 |
+
quotes = page.xpath('//div[@class="quote"]') # XPath
|
| 240 |
+
quotes = page.find_all('div', {'class': 'quote'}) # BeautifulSoup-Stil
|
| 241 |
+
# Gleich wie
|
| 242 |
+
quotes = page.find_all('div', class_='quote')
|
| 243 |
+
quotes = page.find_all(['div'], class_='quote')
|
| 244 |
+
quotes = page.find_all(class_='quote') # und so weiter...
|
| 245 |
+
# Element nach Textinhalt finden
|
| 246 |
+
quotes = page.find_by_text('quote', tag='div')
|
| 247 |
+
|
| 248 |
+
# Erweiterte Navigation
|
| 249 |
+
quote_text = page.css('.quote')[0].css('.text::text').get()
|
| 250 |
+
quote_text = page.css('.quote').css('.text::text').getall() # Verkettete Selektoren
|
| 251 |
+
first_quote = page.css('.quote')[0]
|
| 252 |
+
author = first_quote.next_sibling.css('.author::text')
|
| 253 |
+
parent_container = first_quote.parent
|
| 254 |
+
|
| 255 |
+
# Elementbeziehungen und Ähnlichkeit
|
| 256 |
+
similar_elements = first_quote.find_similar()
|
| 257 |
+
below_elements = first_quote.below_elements()
|
| 258 |
+
```
|
| 259 |
+
Sie können den Parser direkt verwenden, wenn Sie keine Websites abrufen möchten, wie unten gezeigt:
|
| 260 |
```python
|
| 261 |
+
from scrapling.parser import Selector
|
| 262 |
+
|
| 263 |
+
page = Selector("<html>...</html>")
|
| 264 |
+
```
|
| 265 |
+
Und es funktioniert genau auf die gleiche Weise!
|
| 266 |
+
|
| 267 |
+
### Beispiele für async Session-Verwaltung
|
| 268 |
+
```python
|
| 269 |
+
import asyncio
|
| 270 |
+
from scrapling.fetchers import FetcherSession, AsyncStealthySession, AsyncDynamicSession
|
| 271 |
+
|
| 272 |
+
async with FetcherSession(http3=True) as session: # `FetcherSession` ist kontextbewusst und kann sowohl in sync- als auch in async-Mustern arbeiten
|
| 273 |
+
page1 = session.get('https://quotes.toscrape.com/')
|
| 274 |
page2 = session.get('https://quotes.toscrape.com/', impersonate='firefox135')
|
| 275 |
|
| 276 |
+
# Async-Session-Verwendung
|
| 277 |
async with AsyncStealthySession(max_pages=2) as session:
|
| 278 |
tasks = []
|
| 279 |
urls = ['https://example.com/page1', 'https://example.com/page2']
|
| 280 |
+
|
| 281 |
for url in urls:
|
| 282 |
task = session.fetch(url)
|
| 283 |
tasks.append(task)
|
| 284 |
+
|
| 285 |
print(session.get_pool_stats()) # Optional - Der Status des Browser-Tab-Pools (beschäftigt/frei/Fehler)
|
| 286 |
results = await asyncio.gather(*tasks)
|
| 287 |
print(session.get_pool_stats())
|
|
|
|
| 289 |
|
| 290 |
## CLI & Interaktive Shell
|
| 291 |
|
| 292 |
+
Scrapling enthält eine leistungsstarke Befehlszeilenschnittstelle:
|
| 293 |
|
| 294 |
[](https://asciinema.org/a/736339)
|
| 295 |
|
|
|
|
| 297 |
```bash
|
| 298 |
scrapling shell
|
| 299 |
```
|
| 300 |
+
Seiten direkt ohne Programmierung in eine Datei extrahieren (extrahiert standardmäßig den Inhalt im `body`-Tag). Wenn die Ausgabedatei mit `.txt` endet, wird der Textinhalt des Ziels extrahiert. Wenn sie mit `.md` endet, ist es eine Markdown-Darstellung des HTML-Inhalts; wenn sie mit `.html` endet, ist es der HTML-Inhalt selbst.
|
| 301 |
```bash
|
| 302 |
scrapling extract get 'https://example.com' content.md
|
| 303 |
scrapling extract get 'https://example.com' content.txt --css-selector '#fromSkipToProducts' --impersonate 'chrome' # Alle Elemente, die dem CSS-Selektor '#fromSkipToProducts' entsprechen
|
|
|
|
| 306 |
```
|
| 307 |
|
| 308 |
> [!NOTE]
|
| 309 |
+
> Es gibt viele zusätzliche Funktionen, aber wir möchten diese Seite prägnant halten, einschließlich des MCP-Servers und der interaktiven Web-Scraping-Shell. Schauen Sie sich die vollständige Dokumentation [hier](https://scrapling.readthedocs.io/en/latest/) an
|
| 310 |
|
| 311 |
## Leistungsbenchmarks
|
| 312 |
|
| 313 |
+
Scrapling ist nicht nur leistungsstark -- es ist auch blitzschnell. Die folgenden Benchmarks vergleichen Scraplings Parser mit den neuesten Versionen anderer beliebter Bibliotheken.
|
| 314 |
|
| 315 |
### Textextraktions-Geschwindigkeitstest (5000 verschachtelte Elemente)
|
| 316 |
|
| 317 |
+
| # | Bibliothek | Zeit (ms) | vs Scrapling |
|
| 318 |
|---|:-----------------:|:---------:|:------------:|
|
| 319 |
+
| 1 | Scrapling | 2.02 | 1.0x |
|
| 320 |
+
| 2 | Parsel/Scrapy | 2.04 | 1.01 |
|
| 321 |
+
| 3 | Raw Lxml | 2.54 | 1.257 |
|
| 322 |
+
| 4 | PyQuery | 24.17 | ~12x |
|
| 323 |
+
| 5 | Selectolax | 82.63 | ~41x |
|
| 324 |
+
| 6 | MechanicalSoup | 1549.71 | ~767.1x |
|
| 325 |
+
| 7 | BS4 with Lxml | 1584.31 | ~784.3x |
|
| 326 |
+
| 8 | BS4 with html5lib | 3391.91 | ~1679.1x |
|
| 327 |
|
| 328 |
|
| 329 |
### Element-Ähnlichkeit & Textsuche-Leistung
|
|
|
|
| 332 |
|
| 333 |
| Bibliothek | Zeit (ms) | vs Scrapling |
|
| 334 |
|-------------|:---------:|:------------:|
|
| 335 |
+
| Scrapling | 2.39 | 1.0x |
|
| 336 |
+
| AutoScraper | 12.45 | 5.209x |
|
| 337 |
|
| 338 |
|
| 339 |
> Alle Benchmarks stellen Durchschnittswerte von über 100 Durchläufen dar. Siehe [benchmarks.py](https://github.com/D4Vinci/Scrapling/blob/main/benchmarks.py) für die Methodik.
|
|
|
|
| 346 |
pip install scrapling
|
| 347 |
```
|
| 348 |
|
| 349 |
+
Diese Installation enthält nur die Parser-Engine und ihre Abhängigkeiten, ohne Fetcher oder Kommandozeilenabhängigkeiten.
|
| 350 |
|
| 351 |
### Optionale Abhängigkeiten
|
| 352 |
|
| 353 |
1. Wenn Sie eine der folgenden zusätzlichen Funktionen, die Fetcher oder ihre Klassen verwenden möchten, müssen Sie die Abhängigkeiten der Fetcher und ihre Browser-Abhängigkeiten wie folgt installieren:
|
| 354 |
```bash
|
| 355 |
pip install "scrapling[fetchers]"
|
| 356 |
+
|
| 357 |
scrapling install
|
| 358 |
```
|
| 359 |
|
| 360 |
+
Dies lädt alle Browser zusammen mit ihren Systemabhängigkeiten und Fingerprint-Manipulationsabhängigkeiten herunter.
|
| 361 |
|
| 362 |
2. Zusätzliche Funktionen:
|
| 363 |
- MCP-Server-Funktion installieren:
|
|
|
|
| 401 |
## Danksagungen
|
| 402 |
|
| 403 |
Dieses Projekt enthält angepassten Code von:
|
| 404 |
+
- Parsel (BSD-Lizenz) -- Verwendet für das [translator](https://github.com/D4Vinci/Scrapling/blob/main/scrapling/core/translator.py)-Submodul
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 405 |
|
| 406 |
---
|
| 407 |
+
<div align="center"><small>Entworfen und hergestellt mit ❤️ von Karim Shoair.</small></div><br>
|
docs/README_ES.md
CHANGED
|
@@ -6,8 +6,9 @@
|
|
| 6 |
</picture>
|
| 7 |
</a>
|
| 8 |
<br>
|
| 9 |
-
<small>Web Scraping
|
| 10 |
</h1>
|
|
|
|
| 11 |
<p align="center">
|
| 12 |
<a href="https://github.com/D4Vinci/Scrapling/actions/workflows/tests.yml" alt="Tests">
|
| 13 |
<img alt="Tests" src="https://github.com/D4Vinci/Scrapling/actions/workflows/tests.yml/badge.svg"></a>
|
|
@@ -28,46 +29,47 @@
|
|
| 28 |
</p>
|
| 29 |
|
| 30 |
<p align="center">
|
| 31 |
-
<a href="https://scrapling.readthedocs.io/en/latest/parsing/selection/">
|
| 32 |
-
|
| 33 |
-
</a>
|
| 34 |
-
|
| 35 |
-
<a href="https://scrapling.readthedocs.io/en/latest/
|
| 36 |
-
|
| 37 |
-
</a>
|
| 38 |
-
|
| 39 |
-
<a href="https://scrapling.readthedocs.io/en/latest/
|
| 40 |
-
CLI
|
| 41 |
-
</a>
|
| 42 |
-
·
|
| 43 |
-
<a href="https://scrapling.readthedocs.io/en/latest/ai/mcp-server/">
|
| 44 |
-
Modo MCP
|
| 45 |
-
</a>
|
| 46 |
-
·
|
| 47 |
-
<a href="https://scrapling.readthedocs.io/en/latest/tutorials/migrating_from_beautifulsoup/">
|
| 48 |
-
Migrar desde Beautifulsoup
|
| 49 |
-
</a>
|
| 50 |
</p>
|
| 51 |
|
| 52 |
-
|
| 53 |
|
| 54 |
-
|
| 55 |
|
| 56 |
-
|
| 57 |
|
| 58 |
```python
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
# ¡Obtén el
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 68 |
```
|
| 69 |
|
| 70 |
-
|
|
|
|
| 71 |
|
| 72 |
<!-- sponsors -->
|
| 73 |
|
|
@@ -91,24 +93,35 @@ Construido para la Web moderna, Scrapling presenta **su propio motor de análisi
|
|
| 91 |
|
| 92 |
## Características Principales
|
| 93 |
|
| 94 |
-
###
|
| 95 |
-
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 96 |
- **Carga Dinámica**: Obtén sitios web dinámicos con automatización completa del navegador a través de la clase `DynamicFetcher` compatible con Chromium de Playwright y Google Chrome.
|
| 97 |
-
- **Evasión Anti-bot**: Capacidades de sigilo avanzadas con `StealthyFetcher` y falsificación de
|
| 98 |
-
- **Gestión de
|
|
|
|
|
|
|
| 99 |
- **Soporte Async**: Soporte async completo en todos los fetchers y clases de sesión async dedicadas.
|
| 100 |
|
| 101 |
### Scraping Adaptativo e Integración con IA
|
| 102 |
- 🔄 **Seguimiento Inteligente de Elementos**: Relocaliza elementos después de cambios en el sitio web usando algoritmos inteligentes de similitud.
|
| 103 |
- 🎯 **Selección Flexible Inteligente**: Selectores CSS, selectores XPath, búsqueda basada en filtros, búsqueda de texto, búsqueda regex y más.
|
| 104 |
- 🔍 **Encontrar Elementos Similares**: Localiza automáticamente elementos similares a los elementos encontrados.
|
| 105 |
-
- 🤖 **Servidor MCP para usar con IA**: Servidor MCP integrado para Web Scraping asistido por IA y extracción de datos. El servidor MCP presenta capacidades
|
| 106 |
|
| 107 |
### Arquitectura de Alto Rendimiento y Probada en Batalla
|
| 108 |
-
- 🚀 **Ultrarrápido**: Rendimiento optimizado que supera a la mayoría de las bibliotecas de
|
| 109 |
- 🔋 **Eficiente en Memoria**: Estructuras de datos optimizadas y carga diferida para una huella de memoria mínima.
|
| 110 |
- ⚡ **Serialización JSON Rápida**: 10 veces más rápido que la biblioteca estándar.
|
| 111 |
-
- 🏗️ **Probado en batalla**: Scrapling no solo tiene una cobertura de
|
| 112 |
|
| 113 |
### Experiencia Amigable para Desarrolladores/Web Scrapers
|
| 114 |
- 🎯 **Shell Interactivo de Web Scraping**: Shell IPython integrado opcional con integración de Scrapling, atajos y nuevas herramientas para acelerar el desarrollo de scripts de Web Scraping, como convertir solicitudes curl a solicitudes Scrapling y ver resultados de solicitudes en tu navegador.
|
|
@@ -117,96 +130,158 @@ Construido para la Web moderna, Scrapling presenta **su propio motor de análisi
|
|
| 117 |
- 🧬 **Procesamiento de Texto Mejorado**: Métodos integrados de regex, limpieza y operaciones de cadena optimizadas.
|
| 118 |
- 📝 **Generación Automática de Selectores**: Genera selectores CSS/XPath robustos para cualquier elemento.
|
| 119 |
- 🔌 **API Familiar**: Similar a Scrapy/BeautifulSoup con los mismos pseudo-elementos usados en Scrapy/Parsel.
|
| 120 |
-
- 📘 **Cobertura Completa de Tipos**: Type hints completos para excelente soporte de IDE y autocompletado de código.
|
| 121 |
- 🔋 **Imagen Docker Lista**: Con cada lanzamiento, se construye y publica automáticamente una imagen Docker que contiene todos los navegadores.
|
| 122 |
|
| 123 |
-
##
|
|
|
|
|
|
|
| 124 |
|
| 125 |
### Uso Básico
|
|
|
|
| 126 |
```python
|
| 127 |
-
from scrapling.fetchers import Fetcher,
|
| 128 |
-
from scrapling.fetchers import FetcherSession, StealthySession, DynamicSession
|
| 129 |
|
| 130 |
-
#
|
| 131 |
-
with FetcherSession(impersonate='chrome') as session: # Usa la última versión de la huella TLS de Chrome
|
| 132 |
page = session.get('https://quotes.toscrape.com/', stealthy_headers=True)
|
| 133 |
-
quotes = page.css('.quote .text::text')
|
| 134 |
|
| 135 |
# O usa solicitudes de una sola vez
|
| 136 |
page = Fetcher.get('https://quotes.toscrape.com/')
|
| 137 |
-
quotes = page.css('.quote .text::text')
|
|
|
|
|
|
|
|
|
|
|
|
|
| 138 |
|
| 139 |
-
|
| 140 |
-
with StealthySession(headless=True, solve_cloudflare=True) as session:
|
| 141 |
page = session.fetch('https://nopecha.com/demo/cloudflare', google_search=False)
|
| 142 |
-
data = page.css('#padded_content a')
|
| 143 |
|
| 144 |
# O usa el estilo de solicitud de una sola vez, abre el navegador para esta solicitud, luego lo cierra después de terminar
|
| 145 |
page = StealthyFetcher.fetch('https://nopecha.com/demo/cloudflare')
|
| 146 |
-
data = page.css('#padded_content a')
|
| 147 |
-
|
| 148 |
-
|
| 149 |
-
|
| 150 |
-
|
| 151 |
-
|
| 152 |
-
|
| 153 |
-
|
| 154 |
-
|
| 155 |
-
|
|
|
|
|
|
|
|
|
|
| 156 |
```
|
| 157 |
|
| 158 |
-
###
|
|
|
|
| 159 |
```python
|
| 160 |
-
|
| 161 |
-
|
| 162 |
-
|
| 163 |
-
|
| 164 |
-
|
| 165 |
-
|
| 166 |
-
|
| 167 |
-
|
| 168 |
-
|
| 169 |
-
|
| 170 |
-
|
| 171 |
-
|
| 172 |
-
|
| 173 |
-
|
| 174 |
-
|
| 175 |
-
|
| 176 |
-
|
| 177 |
-
|
| 178 |
-
|
| 179 |
-
|
| 180 |
-
|
| 181 |
-
|
| 182 |
-
# Scraping adaptativo
|
| 183 |
-
saved_elements = page.css('.product', auto_save=True)
|
| 184 |
-
# Más tarde, cuando el sitio web cambia:
|
| 185 |
-
page.css('.product', adaptive=True) # Encuentra elementos usando posiciones guardadas
|
| 186 |
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 187 |
|
| 188 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 189 |
```python
|
| 190 |
-
from scrapling.
|
| 191 |
-
|
| 192 |
-
|
| 193 |
-
|
| 194 |
-
|
| 195 |
-
|
| 196 |
-
|
| 197 |
-
|
| 198 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 199 |
page2 = session.get('https://quotes.toscrape.com/', impersonate='firefox135')
|
| 200 |
|
| 201 |
# Uso de sesión async
|
| 202 |
async with AsyncStealthySession(max_pages=2) as session:
|
| 203 |
tasks = []
|
| 204 |
urls = ['https://example.com/page1', 'https://example.com/page2']
|
| 205 |
-
|
| 206 |
for url in urls:
|
| 207 |
task = session.fetch(url)
|
| 208 |
tasks.append(task)
|
| 209 |
-
|
| 210 |
print(session.get_pool_stats()) # Opcional - El estado del pool de pestañas del navegador (ocupado/libre/error)
|
| 211 |
results = await asyncio.gather(*tasks)
|
| 212 |
print(session.get_pool_stats())
|
|
@@ -214,11 +289,11 @@ async with AsyncStealthySession(max_pages=2) as session:
|
|
| 214 |
|
| 215 |
## CLI y Shell Interactivo
|
| 216 |
|
| 217 |
-
Scrapling
|
| 218 |
|
| 219 |
[](https://asciinema.org/a/736339)
|
| 220 |
|
| 221 |
-
Lanzar
|
| 222 |
```bash
|
| 223 |
scrapling shell
|
| 224 |
```
|
|
@@ -231,24 +306,24 @@ scrapling extract stealthy-fetch 'https://nopecha.com/demo/cloudflare' captchas.
|
|
| 231 |
```
|
| 232 |
|
| 233 |
> [!NOTE]
|
| 234 |
-
> Hay muchas características adicionales, pero queremos mantener esta página concisa,
|
| 235 |
|
| 236 |
## Benchmarks de Rendimiento
|
| 237 |
|
| 238 |
-
Scrapling no solo es
|
| 239 |
|
| 240 |
### Prueba de Velocidad de Extracción de Texto (5000 elementos anidados)
|
| 241 |
|
| 242 |
-
| # | Biblioteca | Tiempo (ms) | vs Scrapling |
|
| 243 |
|---|:-----------------:|:-----------:|:------------:|
|
| 244 |
-
| 1 | Scrapling |
|
| 245 |
-
| 2 | Parsel/Scrapy | 2.
|
| 246 |
-
| 3 | Raw Lxml |
|
| 247 |
-
| 4 | PyQuery |
|
| 248 |
-
| 5 | Selectolax |
|
| 249 |
-
| 6 |
|
| 250 |
-
| 7 |
|
| 251 |
-
| 8 | BS4 with html5lib |
|
| 252 |
|
| 253 |
|
| 254 |
### Rendimiento de Similitud de Elementos y Búsqueda de Texto
|
|
@@ -257,8 +332,8 @@ Las capacidades de búsqueda adaptativa de elementos de Scrapling superan signif
|
|
| 257 |
|
| 258 |
| Biblioteca | Tiempo (ms) | vs Scrapling |
|
| 259 |
|-------------|:-----------:|:------------:|
|
| 260 |
-
| Scrapling | 2.
|
| 261 |
-
| AutoScraper |
|
| 262 |
|
| 263 |
|
| 264 |
> Todos los benchmarks representan promedios de más de 100 ejecuciones. Ver [benchmarks.py](https://github.com/D4Vinci/Scrapling/blob/main/benchmarks.py) para la metodología.
|
|
@@ -271,29 +346,29 @@ Scrapling requiere Python 3.10 o superior:
|
|
| 271 |
pip install scrapling
|
| 272 |
```
|
| 273 |
|
| 274 |
-
|
| 275 |
|
| 276 |
### Dependencias Opcionales
|
| 277 |
|
| 278 |
1. Si vas a usar alguna de las características adicionales a continuación, los fetchers, o sus clases, necesitarás instalar las dependencias de los fetchers y sus dependencias del navegador de la siguiente manera:
|
| 279 |
```bash
|
| 280 |
pip install "scrapling[fetchers]"
|
| 281 |
-
|
| 282 |
scrapling install
|
| 283 |
```
|
| 284 |
|
| 285 |
-
Esto descarga todos los navegadores, junto con sus dependencias del sistema y dependencias de manipulación de
|
| 286 |
|
| 287 |
2. Características adicionales:
|
| 288 |
- Instalar la característica del servidor MCP:
|
| 289 |
```bash
|
| 290 |
pip install "scrapling[ai]"
|
| 291 |
```
|
| 292 |
-
- Instalar características del
|
| 293 |
```bash
|
| 294 |
pip install "scrapling[shell]"
|
| 295 |
```
|
| 296 |
-
- Instalar todo:
|
| 297 |
```bash
|
| 298 |
pip install "scrapling[all]"
|
| 299 |
```
|
|
@@ -328,12 +403,5 @@ Este trabajo está licenciado bajo la Licencia BSD-3-Clause.
|
|
| 328 |
Este proyecto incluye código adaptado de:
|
| 329 |
- Parsel (Licencia BSD)—Usado para el submódulo [translator](https://github.com/D4Vinci/Scrapling/blob/main/scrapling/core/translator.py)
|
| 330 |
|
| 331 |
-
## Agradecimientos y Referencias
|
| 332 |
-
|
| 333 |
-
- El brillante trabajo de [Daijro](https://github.com/daijro) en [BrowserForge](https://github.com/daijro/browserforge) y [Camoufox](https://github.com/daijro/camoufox)
|
| 334 |
-
- El brillante trabajo de [Vinyzu](https://github.com/Vinyzu) en [Botright](https://github.com/Vinyzu/Botright) y [PatchRight](https://github.com/Kaliiiiiiiiii-Vinyzu/patchright)
|
| 335 |
-
- [brotector](https://github.com/kaliiiiiiiiii/brotector) por técnicas de evasión de detección de navegador
|
| 336 |
-
- [fakebrowser](https://github.com/kkoooqq/fakebrowser) y [BotBrowser](https://github.com/botswin/BotBrowser) por investigación de huellas digitales
|
| 337 |
-
|
| 338 |
---
|
| 339 |
-
<div align="center"><small>Diseñado y elaborado con ❤️ por Karim Shoair.</small></div><br>
|
|
|
|
| 6 |
</picture>
|
| 7 |
</a>
|
| 8 |
<br>
|
| 9 |
+
<small>Effortless Web Scraping for the Modern Web</small>
|
| 10 |
</h1>
|
| 11 |
+
|
| 12 |
<p align="center">
|
| 13 |
<a href="https://github.com/D4Vinci/Scrapling/actions/workflows/tests.yml" alt="Tests">
|
| 14 |
<img alt="Tests" src="https://github.com/D4Vinci/Scrapling/actions/workflows/tests.yml/badge.svg"></a>
|
|
|
|
| 29 |
</p>
|
| 30 |
|
| 31 |
<p align="center">
|
| 32 |
+
<a href="https://scrapling.readthedocs.io/en/latest/parsing/selection/"><strong>Metodos de seleccion</strong></a>
|
| 33 |
+
·
|
| 34 |
+
<a href="https://scrapling.readthedocs.io/en/latest/fetching/choosing/"><strong>Elegir un fetcher</strong></a>
|
| 35 |
+
·
|
| 36 |
+
<a href="https://scrapling.readthedocs.io/en/latest/cli/overview/"><strong>CLI</strong></a>
|
| 37 |
+
·
|
| 38 |
+
<a href="https://scrapling.readthedocs.io/en/latest/ai/mcp-server/"><strong>Modo MCP</strong></a>
|
| 39 |
+
·
|
| 40 |
+
<a href="https://scrapling.readthedocs.io/en/latest/tutorials/migrating_from_beautifulsoup/"><strong>Migrar desde Beautifulsoup</strong></a>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 41 |
</p>
|
| 42 |
|
| 43 |
+
Scrapling es un framework de Web Scraping adaptativo que se encarga de todo, desde una sola solicitud hasta un rastreo a gran escala.
|
| 44 |
|
| 45 |
+
Su parser aprende de los cambios de los sitios web y relocaliza automáticamente tus elementos cuando las páginas se actualizan. Sus fetchers evaden sistemas anti-bot como Cloudflare Turnstile de forma nativa. Y su framework Spider te permite escalar a rastreos concurrentes con múltiples sesiones, con Pause & Resume y rotación automática de Proxy, todo en unas pocas líneas de Python. Una biblioteca, cero compromisos.
|
| 46 |
|
| 47 |
+
Rastreos ultrarrápidos con estadísticas en tiempo real y Streaming. Construido por Web Scrapers para Web Scrapers y usuarios regulares, hay algo para todos.
|
| 48 |
|
| 49 |
```python
|
| 50 |
+
from scrapling.fetchers import Fetcher, AsyncFetcher, StealthyFetcher, DynamicFetcher
|
| 51 |
+
StealthyFetcher.adaptive = True
|
| 52 |
+
page = StealthyFetcher.fetch('https://example.com', headless=True, network_idle=True) # ¡Obtén el sitio web bajo el radar!
|
| 53 |
+
products = page.css('.product', auto_save=True) # ¡Extrae datos que sobreviven a cambios de diseño del sitio web!
|
| 54 |
+
products = page.css('.product', adaptive=True) # Más tarde, si la estructura del sitio web cambia, ¡pasa `adaptive=True` para encontrarlos!
|
| 55 |
+
```
|
| 56 |
+
O escala a rastreos completos
|
| 57 |
+
```python
|
| 58 |
+
from scrapling.spiders import Spider, Response
|
| 59 |
+
|
| 60 |
+
class MySpider(Spider):
|
| 61 |
+
name = "demo"
|
| 62 |
+
start_urls = ["https://example.com/"]
|
| 63 |
+
|
| 64 |
+
async def parse(self, response: Response):
|
| 65 |
+
for item in response.css('.product'):
|
| 66 |
+
yield {"title": item.css('h2::text').get()}
|
| 67 |
+
|
| 68 |
+
MySpider().start()
|
| 69 |
```
|
| 70 |
|
| 71 |
+
|
| 72 |
+
# Patrocinadores
|
| 73 |
|
| 74 |
<!-- sponsors -->
|
| 75 |
|
|
|
|
| 93 |
|
| 94 |
## Características Principales
|
| 95 |
|
| 96 |
+
### Spiders — Un Framework Completo de Rastreo
|
| 97 |
+
- 🕷️ **API de Spider al estilo Scrapy**: Define spiders con `start_urls`, callbacks async `parse`, y objetos `Request`/`Response`.
|
| 98 |
+
- ⚡ **Rastreo Concurrente**: Límites de concurrencia configurables, limitación por dominio y retrasos de descarga.
|
| 99 |
+
- 🔄 **Soporte Multi-Session**: Interfaz unificada para solicitudes HTTP y navegadores headless sigilosos en un solo Spider — enruta solicitudes a diferentes sesiones por ID.
|
| 100 |
+
- 💾 **Pause & Resume**: Persistencia de rastreo basada en Checkpoint. Presiona Ctrl+C para un cierre ordenado; reinicia para continuar desde donde lo dejaste.
|
| 101 |
+
- 📡 **Modo Streaming**: Transmite elementos extraídos a medida que llegan con `async for item in spider.stream()` con estadísticas en tiempo real — ideal para UI, pipelines y rastreos de larga duración.
|
| 102 |
+
- 🛡️ **Detección de Solicitudes Bloqueadas**: Detección automática y reintento de solicitudes bloqueadas con lógica personalizable.
|
| 103 |
+
- 📦 **Exportación Integrada**: Exporta resultados a través de hooks y tu propio pipeline o el JSON/JSONL integrado con `result.items.to_json()` / `result.items.to_jsonl()` respectivamente.
|
| 104 |
+
|
| 105 |
+
### Obtención Avanzada de Sitios Web con Soporte de Session
|
| 106 |
+
- **Solicitudes HTTP**: Solicitudes HTTP rápidas y sigilosas con la clase `Fetcher`. Puede imitar el fingerprint TLS de los navegadores, encabezados y usar HTTP/3.
|
| 107 |
- **Carga Dinámica**: Obtén sitios web dinámicos con automatización completa del navegador a través de la clase `DynamicFetcher` compatible con Chromium de Playwright y Google Chrome.
|
| 108 |
+
- **Evasión Anti-bot**: Capacidades de sigilo avanzadas con `StealthyFetcher` y falsificación de fingerprint. Puede evadir fácilmente todos los tipos de Turnstile/Interstitial de Cloudflare con automatización.
|
| 109 |
+
- **Gestión de Session**: Soporte de sesión persistente con las clases `FetcherSession`, `StealthySession` y `DynamicSession` para la gestión de cookies y estado entre solicitudes.
|
| 110 |
+
- **Rotación de Proxy**: `ProxyRotator` integrado con estrategias round-robin o personalizadas en todos los tipos de sesión, además de sobrescrituras de Proxy por solicitud.
|
| 111 |
+
- **Bloqueo de Dominios**: Bloquea solicitudes a dominios específicos (y sus subdominios) en fetchers basados en navegador.
|
| 112 |
- **Soporte Async**: Soporte async completo en todos los fetchers y clases de sesión async dedicadas.
|
| 113 |
|
| 114 |
### Scraping Adaptativo e Integración con IA
|
| 115 |
- 🔄 **Seguimiento Inteligente de Elementos**: Relocaliza elementos después de cambios en el sitio web usando algoritmos inteligentes de similitud.
|
| 116 |
- 🎯 **Selección Flexible Inteligente**: Selectores CSS, selectores XPath, búsqueda basada en filtros, búsqueda de texto, búsqueda regex y más.
|
| 117 |
- 🔍 **Encontrar Elementos Similares**: Localiza automáticamente elementos similares a los elementos encontrados.
|
| 118 |
+
- 🤖 **Servidor MCP para usar con IA**: Servidor MCP integrado para Web Scraping asistido por IA y extracción de datos. El servidor MCP presenta capacidades potentes y personalizadas que aprovechan Scrapling para extraer contenido específico antes de pasarlo a la IA (Claude/Cursor/etc), acelerando así las operaciones y reduciendo costos al minimizar el uso de tokens. ([video demo](https://www.youtube.com/watch?v=qyFk3ZNwOxE))
|
| 119 |
|
| 120 |
### Arquitectura de Alto Rendimiento y Probada en Batalla
|
| 121 |
+
- 🚀 **Ultrarrápido**: Rendimiento optimizado que supera a la mayoría de las bibliotecas de Web Scraping de Python.
|
| 122 |
- 🔋 **Eficiente en Memoria**: Estructuras de datos optimizadas y carga diferida para una huella de memoria mínima.
|
| 123 |
- ⚡ **Serialización JSON Rápida**: 10 veces más rápido que la biblioteca estándar.
|
| 124 |
+
- 🏗️ **Probado en batalla**: Scrapling no solo tiene una cobertura de pruebas del 92% y cobertura completa de type hints, sino que ha sido utilizado diariamente por cientos de Web Scrapers durante el último año.
|
| 125 |
|
| 126 |
### Experiencia Amigable para Desarrolladores/Web Scrapers
|
| 127 |
- 🎯 **Shell Interactivo de Web Scraping**: Shell IPython integrado opcional con integración de Scrapling, atajos y nuevas herramientas para acelerar el desarrollo de scripts de Web Scraping, como convertir solicitudes curl a solicitudes Scrapling y ver resultados de solicitudes en tu navegador.
|
|
|
|
| 130 |
- 🧬 **Procesamiento de Texto Mejorado**: Métodos integrados de regex, limpieza y operaciones de cadena optimizadas.
|
| 131 |
- 📝 **Generación Automática de Selectores**: Genera selectores CSS/XPath robustos para cualquier elemento.
|
| 132 |
- 🔌 **API Familiar**: Similar a Scrapy/BeautifulSoup con los mismos pseudo-elementos usados en Scrapy/Parsel.
|
| 133 |
+
- 📘 **Cobertura Completa de Tipos**: Type hints completos para excelente soporte de IDE y autocompletado de código. Todo el código fuente se escanea automáticamente con **PyRight** y **MyPy** en cada cambio.
|
| 134 |
- 🔋 **Imagen Docker Lista**: Con cada lanzamiento, se construye y publica automáticamente una imagen Docker que contiene todos los navegadores.
|
| 135 |
|
| 136 |
+
## Primeros Pasos
|
| 137 |
+
|
| 138 |
+
Aquí tienes un vistazo rápido de lo que Scrapling puede hacer sin entrar en profundidad.
|
| 139 |
|
| 140 |
### Uso Básico
|
| 141 |
+
Solicitudes HTTP con soporte de sesión
|
| 142 |
```python
|
| 143 |
+
from scrapling.fetchers import Fetcher, FetcherSession
|
|
|
|
| 144 |
|
| 145 |
+
with FetcherSession(impersonate='chrome') as session: # Usa la última versión del fingerprint TLS de Chrome
|
|
|
|
| 146 |
page = session.get('https://quotes.toscrape.com/', stealthy_headers=True)
|
| 147 |
+
quotes = page.css('.quote .text::text').getall()
|
| 148 |
|
| 149 |
# O usa solicitudes de una sola vez
|
| 150 |
page = Fetcher.get('https://quotes.toscrape.com/')
|
| 151 |
+
quotes = page.css('.quote .text::text').getall()
|
| 152 |
+
```
|
| 153 |
+
Modo sigiloso avanzado
|
| 154 |
+
```python
|
| 155 |
+
from scrapling.fetchers import StealthyFetcher, StealthySession
|
| 156 |
|
| 157 |
+
with StealthySession(headless=True, solve_cloudflare=True) as session: # Mantén el navegador abierto hasta que termines
|
|
|
|
| 158 |
page = session.fetch('https://nopecha.com/demo/cloudflare', google_search=False)
|
| 159 |
+
data = page.css('#padded_content a').getall()
|
| 160 |
|
| 161 |
# O usa el estilo de solicitud de una sola vez, abre el navegador para esta solicitud, luego lo cierra después de terminar
|
| 162 |
page = StealthyFetcher.fetch('https://nopecha.com/demo/cloudflare')
|
| 163 |
+
data = page.css('#padded_content a').getall()
|
| 164 |
+
```
|
| 165 |
+
Automatización completa del navegador
|
| 166 |
+
```python
|
| 167 |
+
from scrapling.fetchers import DynamicFetcher, DynamicSession
|
| 168 |
+
|
| 169 |
+
with DynamicSession(headless=True, disable_resources=False, network_idle=True) as session: # Mantén el navegador abierto hasta que termines
|
| 170 |
+
page = session.fetch('https://quotes.toscrape.com/', load_dom=False)
|
| 171 |
+
data = page.xpath('//span[@class="text"]/text()').getall() # Selector XPath si lo prefieres
|
| 172 |
+
|
| 173 |
+
# O usa el estilo de solicitud de una sola vez, abre el navegador para esta solicitud, luego lo cierra después de terminar
|
| 174 |
+
page = DynamicFetcher.fetch('https://quotes.toscrape.com/')
|
| 175 |
+
data = page.css('.quote .text::text').getall()
|
| 176 |
```
|
| 177 |
|
| 178 |
+
### Spiders
|
| 179 |
+
Construye rastreadores completos con solicitudes concurrentes, múltiples tipos de sesión y Pause & Resume:
|
| 180 |
```python
|
| 181 |
+
from scrapling.spiders import Spider, Request, Response
|
| 182 |
+
|
| 183 |
+
class QuotesSpider(Spider):
|
| 184 |
+
name = "quotes"
|
| 185 |
+
start_urls = ["https://quotes.toscrape.com/"]
|
| 186 |
+
concurrent_requests = 10
|
| 187 |
+
|
| 188 |
+
async def parse(self, response: Response):
|
| 189 |
+
for quote in response.css('.quote'):
|
| 190 |
+
yield {
|
| 191 |
+
"text": quote.css('.text::text').get(),
|
| 192 |
+
"author": quote.css('.author::text').get(),
|
| 193 |
+
}
|
| 194 |
+
|
| 195 |
+
next_page = response.css('.next a')
|
| 196 |
+
if next_page:
|
| 197 |
+
yield response.follow(next_page[0].attrib['href'])
|
| 198 |
+
|
| 199 |
+
result = QuotesSpider().start()
|
| 200 |
+
print(f"Se extrajeron {len(result.items)} citas")
|
| 201 |
+
result.items.to_json("quotes.json")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 202 |
```
|
| 203 |
+
Usa múltiples tipos de sesión en un solo Spider:
|
| 204 |
+
```python
|
| 205 |
+
from scrapling.spiders import Spider, Request, Response
|
| 206 |
+
from scrapling.fetchers import FetcherSession, AsyncStealthySession
|
| 207 |
+
|
| 208 |
+
class MultiSessionSpider(Spider):
|
| 209 |
+
name = "multi"
|
| 210 |
+
start_urls = ["https://example.com/"]
|
| 211 |
+
|
| 212 |
+
def configure_sessions(self, manager):
|
| 213 |
+
manager.add("fast", FetcherSession(impersonate="chrome"))
|
| 214 |
+
manager.add("stealth", AsyncStealthySession(headless=True), lazy=True)
|
| 215 |
+
|
| 216 |
+
async def parse(self, response: Response):
|
| 217 |
+
for link in response.css('a::attr(href)').getall():
|
| 218 |
+
# Enruta las páginas protegidas a través de la sesión sigilosa
|
| 219 |
+
if "protected" in link:
|
| 220 |
+
yield Request(link, sid="stealth")
|
| 221 |
+
else:
|
| 222 |
+
yield Request(link, sid="fast", callback=self.parse) # callback explícito
|
| 223 |
+
```
|
| 224 |
+
Pausa y reanuda rastreos largos con checkpoints ejecutando el Spider así:
|
| 225 |
+
```python
|
| 226 |
+
QuotesSpider(crawldir="./crawl_data").start()
|
| 227 |
+
```
|
| 228 |
+
Presiona Ctrl+C para pausar de forma ordenada — el progreso se guarda automáticamente. Después, cuando inicies el Spider de nuevo, pasa el mismo `crawldir`, y continuará desde donde se detuvo.
|
| 229 |
+
|
| 230 |
+
### Análisis Avanzado y Navegación
|
| 231 |
+
```python
|
| 232 |
+
from scrapling.fetchers import Fetcher
|
| 233 |
+
|
| 234 |
+
# Selección rica de elementos y navegación
|
| 235 |
+
page = Fetcher.get('https://quotes.toscrape.com/')
|
| 236 |
|
| 237 |
+
# Obtén citas con múltiples métodos de selección
|
| 238 |
+
quotes = page.css('.quote') # Selector CSS
|
| 239 |
+
quotes = page.xpath('//div[@class="quote"]') # XPath
|
| 240 |
+
quotes = page.find_all('div', {'class': 'quote'}) # Estilo BeautifulSoup
|
| 241 |
+
# Igual que
|
| 242 |
+
quotes = page.find_all('div', class_='quote')
|
| 243 |
+
quotes = page.find_all(['div'], class_='quote')
|
| 244 |
+
quotes = page.find_all(class_='quote') # y así sucesivamente...
|
| 245 |
+
# Encuentra elementos por contenido de texto
|
| 246 |
+
quotes = page.find_by_text('quote', tag='div')
|
| 247 |
+
|
| 248 |
+
# Navegación avanzada
|
| 249 |
+
quote_text = page.css('.quote')[0].css('.text::text').get()
|
| 250 |
+
quote_text = page.css('.quote').css('.text::text').getall() # Selectores encadenados
|
| 251 |
+
first_quote = page.css('.quote')[0]
|
| 252 |
+
author = first_quote.next_sibling.css('.author::text')
|
| 253 |
+
parent_container = first_quote.parent
|
| 254 |
+
|
| 255 |
+
# Relaciones y similitud de elementos
|
| 256 |
+
similar_elements = first_quote.find_similar()
|
| 257 |
+
below_elements = first_quote.below_elements()
|
| 258 |
+
```
|
| 259 |
+
Puedes usar el parser directamente si no necesitas obtener sitios web, como se muestra a continuación:
|
| 260 |
```python
|
| 261 |
+
from scrapling.parser import Selector
|
| 262 |
+
|
| 263 |
+
page = Selector("<html>...</html>")
|
| 264 |
+
```
|
| 265 |
+
¡Y funciona exactamente de la misma manera!
|
| 266 |
+
|
| 267 |
+
### Ejemplos de Gestión de Session Async
|
| 268 |
+
```python
|
| 269 |
+
import asyncio
|
| 270 |
+
from scrapling.fetchers import FetcherSession, AsyncStealthySession, AsyncDynamicSession
|
| 271 |
+
|
| 272 |
+
async with FetcherSession(http3=True) as session: # `FetcherSession` es consciente del contexto y puede funcionar tanto en patrones sync/async
|
| 273 |
+
page1 = session.get('https://quotes.toscrape.com/')
|
| 274 |
page2 = session.get('https://quotes.toscrape.com/', impersonate='firefox135')
|
| 275 |
|
| 276 |
# Uso de sesión async
|
| 277 |
async with AsyncStealthySession(max_pages=2) as session:
|
| 278 |
tasks = []
|
| 279 |
urls = ['https://example.com/page1', 'https://example.com/page2']
|
| 280 |
+
|
| 281 |
for url in urls:
|
| 282 |
task = session.fetch(url)
|
| 283 |
tasks.append(task)
|
| 284 |
+
|
| 285 |
print(session.get_pool_stats()) # Opcional - El estado del pool de pestañas del navegador (ocupado/libre/error)
|
| 286 |
results = await asyncio.gather(*tasks)
|
| 287 |
print(session.get_pool_stats())
|
|
|
|
| 289 |
|
| 290 |
## CLI y Shell Interactivo
|
| 291 |
|
| 292 |
+
Scrapling incluye una poderosa interfaz de línea de comandos:
|
| 293 |
|
| 294 |
[](https://asciinema.org/a/736339)
|
| 295 |
|
| 296 |
+
Lanzar el Shell interactivo de Web Scraping
|
| 297 |
```bash
|
| 298 |
scrapling shell
|
| 299 |
```
|
|
|
|
| 306 |
```
|
| 307 |
|
| 308 |
> [!NOTE]
|
| 309 |
+
> Hay muchas características adicionales, pero queremos mantener esta página concisa, incluyendo el servidor MCP y el Shell Interactivo de Web Scraping. Consulta la documentación completa [aquí](https://scrapling.readthedocs.io/en/latest/)
|
| 310 |
|
| 311 |
## Benchmarks de Rendimiento
|
| 312 |
|
| 313 |
+
Scrapling no solo es potente, también es ultrarrápido. Los siguientes benchmarks comparan el parser de Scrapling con las últimas versiones de otras bibliotecas populares.
|
| 314 |
|
| 315 |
### Prueba de Velocidad de Extracción de Texto (5000 elementos anidados)
|
| 316 |
|
| 317 |
+
| # | Biblioteca | Tiempo (ms) | vs Scrapling |
|
| 318 |
|---|:-----------------:|:-----------:|:------------:|
|
| 319 |
+
| 1 | Scrapling | 2.02 | 1.0x |
|
| 320 |
+
| 2 | Parsel/Scrapy | 2.04 | 1.01 |
|
| 321 |
+
| 3 | Raw Lxml | 2.54 | 1.257 |
|
| 322 |
+
| 4 | PyQuery | 24.17 | ~12x |
|
| 323 |
+
| 5 | Selectolax | 82.63 | ~41x |
|
| 324 |
+
| 6 | MechanicalSoup | 1549.71 | ~767.1x |
|
| 325 |
+
| 7 | BS4 with Lxml | 1584.31 | ~784.3x |
|
| 326 |
+
| 8 | BS4 with html5lib | 3391.91 | ~1679.1x |
|
| 327 |
|
| 328 |
|
| 329 |
### Rendimiento de Similitud de Elementos y Búsqueda de Texto
|
|
|
|
| 332 |
|
| 333 |
| Biblioteca | Tiempo (ms) | vs Scrapling |
|
| 334 |
|-------------|:-----------:|:------------:|
|
| 335 |
+
| Scrapling | 2.39 | 1.0x |
|
| 336 |
+
| AutoScraper | 12.45 | 5.209x |
|
| 337 |
|
| 338 |
|
| 339 |
> Todos los benchmarks representan promedios de más de 100 ejecuciones. Ver [benchmarks.py](https://github.com/D4Vinci/Scrapling/blob/main/benchmarks.py) para la metodología.
|
|
|
|
| 346 |
pip install scrapling
|
| 347 |
```
|
| 348 |
|
| 349 |
+
Esta instalación solo incluye el motor de análisis y sus dependencias, sin ningún fetcher ni dependencias de línea de comandos.
|
| 350 |
|
| 351 |
### Dependencias Opcionales
|
| 352 |
|
| 353 |
1. Si vas a usar alguna de las características adicionales a continuación, los fetchers, o sus clases, necesitarás instalar las dependencias de los fetchers y sus dependencias del navegador de la siguiente manera:
|
| 354 |
```bash
|
| 355 |
pip install "scrapling[fetchers]"
|
| 356 |
+
|
| 357 |
scrapling install
|
| 358 |
```
|
| 359 |
|
| 360 |
+
Esto descarga todos los navegadores, junto con sus dependencias del sistema y dependencias de manipulación de fingerprint.
|
| 361 |
|
| 362 |
2. Características adicionales:
|
| 363 |
- Instalar la característica del servidor MCP:
|
| 364 |
```bash
|
| 365 |
pip install "scrapling[ai]"
|
| 366 |
```
|
| 367 |
+
- Instalar características del Shell (Shell de Web Scraping y el comando `extract`):
|
| 368 |
```bash
|
| 369 |
pip install "scrapling[shell]"
|
| 370 |
```
|
| 371 |
+
- Instalar todo:
|
| 372 |
```bash
|
| 373 |
pip install "scrapling[all]"
|
| 374 |
```
|
|
|
|
| 403 |
Este proyecto incluye código adaptado de:
|
| 404 |
- Parsel (Licencia BSD)—Usado para el submódulo [translator](https://github.com/D4Vinci/Scrapling/blob/main/scrapling/core/translator.py)
|
| 405 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 406 |
---
|
| 407 |
+
<div align="center"><small>Diseñado y elaborado con ❤️ por Karim Shoair.</small></div><br>
|
docs/README_JP.md
CHANGED
|
@@ -6,8 +6,9 @@
|
|
| 6 |
</picture>
|
| 7 |
</a>
|
| 8 |
<br>
|
| 9 |
-
<small>Web Scraping
|
| 10 |
</h1>
|
|
|
|
| 11 |
<p align="center">
|
| 12 |
<a href="https://github.com/D4Vinci/Scrapling/actions/workflows/tests.yml" alt="Tests">
|
| 13 |
<img alt="Tests" src="https://github.com/D4Vinci/Scrapling/actions/workflows/tests.yml/badge.svg"></a>
|
|
@@ -28,46 +29,47 @@
|
|
| 28 |
</p>
|
| 29 |
|
| 30 |
<p align="center">
|
| 31 |
-
<a href="https://scrapling.readthedocs.io/en/latest/parsing/selection/">
|
| 32 |
-
|
| 33 |
-
</a>
|
| 34 |
-
|
| 35 |
-
<a href="https://scrapling.readthedocs.io/en/latest/
|
| 36 |
-
|
| 37 |
-
</a>
|
| 38 |
-
|
| 39 |
-
<a href="https://scrapling.readthedocs.io/en/latest/
|
| 40 |
-
CLI
|
| 41 |
-
</a>
|
| 42 |
-
·
|
| 43 |
-
<a href="https://scrapling.readthedocs.io/en/latest/ai/mcp-server/">
|
| 44 |
-
MCPモード
|
| 45 |
-
</a>
|
| 46 |
-
·
|
| 47 |
-
<a href="https://scrapling.readthedocs.io/en/latest/tutorials/migrating_from_beautifulsoup/">
|
| 48 |
-
Beautifulsoupからの移行
|
| 49 |
-
</a>
|
| 50 |
</p>
|
| 51 |
|
| 52 |
-
|
| 53 |
|
| 54 |
-
|
| 55 |
|
| 56 |
-
|
| 57 |
|
| 58 |
```python
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
# レーダーの下でウェブサイト
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
200
|
| 65 |
-
>> products = page.css('.product', auto_save=True) # ウェブサイトのデザイン変更に耐えるデータをスクレイプ!
|
| 66 |
-
>> # 後でウェブサイトの構造が変わったら、`adaptive=True`を渡す
|
| 67 |
-
>> products = page.css('.product', adaptive=True) # そしてScraplingはまだそれらを見つけます!
|
| 68 |
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 69 |
|
| 70 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 71 |
|
| 72 |
<!-- sponsors -->
|
| 73 |
|
|
@@ -91,138 +93,211 @@ Scraplingは単なるウェブスクレイピングライブラリではあり
|
|
| 91 |
|
| 92 |
## 主な機能
|
| 93 |
|
| 94 |
-
###
|
| 95 |
-
- **
|
| 96 |
-
- **
|
| 97 |
-
- **
|
| 98 |
-
- **
|
| 99 |
-
- **
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 100 |
|
| 101 |
### 適応型スクレイピングとAI統合
|
| 102 |
- 🔄 **スマート要素追跡**:インテリジェントな類似性アルゴリズムを使用してウェブサイトの変更後に要素を再配置。
|
| 103 |
- 🎯 **スマート柔軟選択**:CSSセレクタ、XPathセレクタ、フィルタベース検索、テキスト検索、正規表現検索など。
|
| 104 |
-
- 🔍 **類似要素
|
| 105 |
-
- 🤖 **AIと使用するMCPサーバー**:AI支援
|
| 106 |
|
| 107 |
### 高性能で実戦テスト済みのアーキテクチャ
|
| 108 |
-
- 🚀 **高速**:ほとんどのPythonスクレイピングライブラリを上回る最適化されたパフォーマンス。
|
| 109 |
- 🔋 **メモリ効率**:最小のメモリフットプリントのための最適化されたデータ構造と遅延読み込み。
|
| 110 |
- ⚡ **高速JSONシリアル化**:標準ライブラリの10倍の速度。
|
| 111 |
-
- 🏗️ **実戦テスト済み**:Scraplingは92%のテストカバレッジと完全な型ヒントカバレッジを備えているだけでなく、過去1年間に数百人の
|
| 112 |
|
| 113 |
-
### 開発者/
|
| 114 |
-
- 🎯 **インタラクティブ
|
| 115 |
- 🚀 **ターミナルから直接使用**:オプションで、コードを一行も書かずにScraplingを使用してURLをスクレイプできます!
|
| 116 |
- 🛠️ **豊富なナビゲーションAPI**:親、兄弟、子のナビゲーションメソッドによる高度なDOMトラバーサル。
|
| 117 |
- 🧬 **強化されたテキスト処理**:組み込みの正規表現、クリーニングメソッド、最適化された文字列操作。
|
| 118 |
- 📝 **自動セレクタ生成**:任意の要素に対して堅牢なCSS/XPathセレクタを生成。
|
| 119 |
-
- 🔌 **馴染みのあるAPI**:Scrapy/Parselで使用されている同じ疑似要素を持つScrapy/BeautifulSoupに似
|
| 120 |
-
- 📘 **完全な型カバレッジ**:優れたIDEサポートとコード補完のための完全な型ヒント。
|
| 121 |
- 🔋 **すぐに使えるDockerイメージ**:各リリースで、すべてのブラウザを含むDockerイメージが自動的にビルドおよびプッシュされます。
|
| 122 |
|
| 123 |
## はじめに
|
| 124 |
|
|
|
|
|
|
|
| 125 |
### 基本的な使い方
|
|
|
|
| 126 |
```python
|
| 127 |
-
from scrapling.fetchers import Fetcher,
|
| 128 |
-
from scrapling.fetchers import FetcherSession, StealthySession, DynamicSession
|
| 129 |
|
| 130 |
-
#
|
| 131 |
-
with FetcherSession(impersonate='chrome') as session: # ChromeのTLSフィンガープリントの最新バージョンを使用
|
| 132 |
page = session.get('https://quotes.toscrape.com/', stealthy_headers=True)
|
| 133 |
-
quotes = page.css('.quote .text::text')
|
| 134 |
|
| 135 |
# または一回限りのリクエストを使用
|
| 136 |
page = Fetcher.get('https://quotes.toscrape.com/')
|
| 137 |
-
quotes = page.css('.quote .text::text')
|
|
|
|
|
|
|
|
|
|
|
|
|
| 138 |
|
| 139 |
-
#
|
| 140 |
-
with StealthySession(headless=True, solve_cloudflare=True) as session:
|
| 141 |
page = session.fetch('https://nopecha.com/demo/cloudflare', google_search=False)
|
| 142 |
-
data = page.css('#padded_content a')
|
| 143 |
|
| 144 |
-
# または一回限りのリクエストスタイル
|
| 145 |
page = StealthyFetcher.fetch('https://nopecha.com/demo/cloudflare')
|
| 146 |
-
data = page.css('#padded_content a')
|
| 147 |
-
|
| 148 |
-
|
| 149 |
-
|
| 150 |
-
|
| 151 |
-
|
| 152 |
-
|
| 153 |
-
|
| 154 |
-
|
| 155 |
-
|
|
|
|
|
|
|
|
|
|
| 156 |
```
|
| 157 |
|
| 158 |
-
###
|
|
|
|
| 159 |
```python
|
| 160 |
-
|
| 161 |
-
|
| 162 |
-
|
| 163 |
-
|
| 164 |
-
|
| 165 |
-
|
| 166 |
-
|
| 167 |
-
|
| 168 |
-
|
| 169 |
-
|
| 170 |
-
|
| 171 |
-
|
| 172 |
-
|
| 173 |
-
|
| 174 |
-
|
| 175 |
-
|
| 176 |
-
|
| 177 |
-
|
| 178 |
-
|
| 179 |
-
|
| 180 |
-
|
| 181 |
-
|
| 182 |
-
# 適応型スクレイピング
|
| 183 |
-
saved_elements = page.css('.product', auto_save=True)
|
| 184 |
-
# 後でウェブサイトが変更されたとき:
|
| 185 |
-
page.css('.product', adaptive=True) # 保存された位置を使用して要素を見つける
|
| 186 |
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 187 |
|
| 188 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 189 |
```python
|
| 190 |
-
from scrapling.
|
| 191 |
-
|
| 192 |
-
|
| 193 |
-
|
| 194 |
-
|
| 195 |
-
|
| 196 |
-
|
| 197 |
-
|
| 198 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 199 |
page2 = session.get('https://quotes.toscrape.com/', impersonate='firefox135')
|
| 200 |
|
| 201 |
-
# 非同期
|
| 202 |
async with AsyncStealthySession(max_pages=2) as session:
|
| 203 |
tasks = []
|
| 204 |
urls = ['https://example.com/page1', 'https://example.com/page2']
|
| 205 |
-
|
| 206 |
for url in urls:
|
| 207 |
task = session.fetch(url)
|
| 208 |
tasks.append(task)
|
| 209 |
-
|
| 210 |
print(session.get_pool_stats()) # オプション - ブラウザタブプールのステータス(ビジー/フリー/エラー)
|
| 211 |
results = await asyncio.gather(*tasks)
|
| 212 |
print(session.get_pool_stats())
|
| 213 |
```
|
| 214 |
|
| 215 |
-
## CLIとインタラクティブ
|
| 216 |
|
| 217 |
-
Scrapling
|
| 218 |
|
| 219 |
[](https://asciinema.org/a/736339)
|
| 220 |
|
| 221 |
-
インタラクティブ
|
| 222 |
```bash
|
| 223 |
scrapling shell
|
| 224 |
```
|
| 225 |
-
プログラミングせずに直接ページをファイルに抽出(デフォルトで`body`タグ内のコンテンツを抽出)。出力ファイルが`.txt`で終わる場合、ターゲットのテキストコンテンツが抽出されます。`.md`で終わる場合、HTMLコンテンツのMarkdown表現になります
|
| 226 |
```bash
|
| 227 |
scrapling extract get 'https://example.com' content.md
|
| 228 |
scrapling extract get 'https://example.com' content.txt --css-selector '#fromSkipToProducts' --impersonate 'chrome' # CSSセレクタ'#fromSkipToProducts'に一致するすべての要素
|
|
@@ -231,34 +306,34 @@ scrapling extract stealthy-fetch 'https://nopecha.com/demo/cloudflare' captchas.
|
|
| 231 |
```
|
| 232 |
|
| 233 |
> [!NOTE]
|
| 234 |
-
> MCPサーバーやインタラク
|
| 235 |
|
| 236 |
## パフォーマンスベンチマーク
|
| 237 |
|
| 238 |
-
Scraplingは強力であるだけでなく、
|
| 239 |
|
| 240 |
### テキスト抽出速度テスト(5000個のネストされた要素)
|
| 241 |
|
| 242 |
-
| # |
|
| 243 |
-
|---|:-----------------:|:-------:|:------------:|
|
| 244 |
-
| 1 | Scrapling |
|
| 245 |
-
| 2 | Parsel/Scrapy |
|
| 246 |
-
| 3 | Raw Lxml | 2.
|
| 247 |
-
| 4 | PyQuery |
|
| 248 |
-
| 5 | Selectolax |
|
| 249 |
-
| 6 |
|
| 250 |
-
| 7 |
|
| 251 |
-
| 8 | BS4 with html5lib |
|
| 252 |
|
| 253 |
|
| 254 |
### 要素類似性とテキスト検索のパフォーマンス
|
| 255 |
|
| 256 |
Scraplingの適応型要素検索機能は代替手段を大幅に上回ります:
|
| 257 |
|
| 258 |
-
| ライブラリ
|
| 259 |
-
|-------------|:------:|:------------:|
|
| 260 |
-
| Scrapling |
|
| 261 |
-
| AutoScraper |
|
| 262 |
|
| 263 |
|
| 264 |
> すべてのベンチマークは100回以上の実行の平均を表します。方法論については[benchmarks.py](https://github.com/D4Vinci/Scrapling/blob/main/benchmarks.py)を参照してください。
|
|
@@ -271,25 +346,25 @@ ScraplingにはPython 3.10以上が必要です:
|
|
| 271 |
pip install scrapling
|
| 272 |
```
|
| 273 |
|
| 274 |
-
|
| 275 |
|
| 276 |
### オプションの依存関係
|
| 277 |
|
| 278 |
-
1. 以下の追加機能、
|
| 279 |
```bash
|
| 280 |
pip install "scrapling[fetchers]"
|
| 281 |
-
|
| 282 |
scrapling install
|
| 283 |
```
|
| 284 |
|
| 285 |
-
これにより、すべてのブラウザ、およびそれらのシステム依存関係と
|
| 286 |
|
| 287 |
2. 追加機能:
|
| 288 |
- MCPサーバー機能をインストール:
|
| 289 |
```bash
|
| 290 |
pip install "scrapling[ai]"
|
| 291 |
```
|
| 292 |
-
-
|
| 293 |
```bash
|
| 294 |
pip install "scrapling[shell]"
|
| 295 |
```
|
|
@@ -328,12 +403,5 @@ docker pull ghcr.io/d4vinci/scrapling:latest
|
|
| 328 |
このプロジェクトには次から適応されたコードが含まれています:
|
| 329 |
- Parsel(BSDライセンス)— [translator](https://github.com/D4Vinci/Scrapling/blob/main/scrapling/core/translator.py)サブモジュールに使用
|
| 330 |
|
| 331 |
-
## 感謝と参考文献
|
| 332 |
-
|
| 333 |
-
- [Daijro](https://github.com/daijro)の[BrowserForge](https://github.com/daijro/browserforge)と[Camoufox](https://github.com/daijro/camoufox)における素晴らしい仕事
|
| 334 |
-
- [Vinyzu](https://github.com/Vinyzu)の[Botright](https://github.com/Vinyzu/Botright)と[PatchRight](https://github.com/Kaliiiiiiiiii-Vinyzu/patchright)における素晴らしい仕事
|
| 335 |
-
- ブラウザ検出回避技術を提供する[brotector](https://github.com/kaliiiiiiiiii/brotector)
|
| 336 |
-
- フィンガープリント研究を提供する[fakebrowser](https://github.com/kkoooqq/fakebrowser)と[BotBrowser](https://github.com/botswin/BotBrowser)
|
| 337 |
-
|
| 338 |
---
|
| 339 |
-
<div align="center"><small>Karim Shoairによって❤️でデザインおよび作成されました。</small></div><br>
|
|
|
|
| 6 |
</picture>
|
| 7 |
</a>
|
| 8 |
<br>
|
| 9 |
+
<small>Effortless Web Scraping for the Modern Web</small>
|
| 10 |
</h1>
|
| 11 |
+
|
| 12 |
<p align="center">
|
| 13 |
<a href="https://github.com/D4Vinci/Scrapling/actions/workflows/tests.yml" alt="Tests">
|
| 14 |
<img alt="Tests" src="https://github.com/D4Vinci/Scrapling/actions/workflows/tests.yml/badge.svg"></a>
|
|
|
|
| 29 |
</p>
|
| 30 |
|
| 31 |
<p align="center">
|
| 32 |
+
<a href="https://scrapling.readthedocs.io/en/latest/parsing/selection/"><strong>選択メソッド</strong></a>
|
| 33 |
+
·
|
| 34 |
+
<a href="https://scrapling.readthedocs.io/en/latest/fetching/choosing/"><strong>Fetcherの選び方</strong></a>
|
| 35 |
+
·
|
| 36 |
+
<a href="https://scrapling.readthedocs.io/en/latest/cli/overview/"><strong>CLI</strong></a>
|
| 37 |
+
·
|
| 38 |
+
<a href="https://scrapling.readthedocs.io/en/latest/ai/mcp-server/"><strong>MCPモード</strong></a>
|
| 39 |
+
·
|
| 40 |
+
<a href="https://scrapling.readthedocs.io/en/latest/tutorials/migrating_from_beautifulsoup/"><strong>Beautifulsoupからの移行</strong></a>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 41 |
</p>
|
| 42 |
|
| 43 |
+
Scraplingは、単一のリクエストから本格的なクロールまですべてを処理する適応型Web Scrapingフレームワークです。
|
| 44 |
|
| 45 |
+
そのパーサーはウェブサイトの変更から学習し、ページが更新されたときに要素を自動的に再配置します。Fetcherはすぐに使えるCloudflare Turnstileなどのアンチボットシステムを回避します。そしてSpiderフレームワークにより、Pause & Resumeや自動Proxy回転機能を備えた並行マルチSessionクロールへとスケールアップできます — すべてわずか数行のPythonで。1つのライブラリ、妥協なし。
|
| 46 |
|
| 47 |
+
リアルタイム統計とStreamingによる超高速クロール。Web Scraperによって、Web Scraperと一般ユーザーのために構築され、誰にでも何かがあります。
|
| 48 |
|
| 49 |
```python
|
| 50 |
+
from scrapling.fetchers import Fetcher, AsyncFetcher, StealthyFetcher, DynamicFetcher
|
| 51 |
+
StealthyFetcher.adaptive = True
|
| 52 |
+
page = StealthyFetcher.fetch('https://example.com', headless=True, network_idle=True) # レーダーの下でウェブサイトを取得!
|
| 53 |
+
products = page.css('.product', auto_save=True) # ウェブサイトのデザイン変更に耐えるデータをスクレイプ!
|
| 54 |
+
products = page.css('.product', adaptive=True) # 後でウェブサイトの構造が変わったら、`adaptive=True`を渡して見つける!
|
|
|
|
|
|
|
|
|
|
|
|
|
| 55 |
```
|
| 56 |
+
または本格的なクロールへスケールアップ
|
| 57 |
+
```python
|
| 58 |
+
from scrapling.spiders import Spider, Response
|
| 59 |
+
|
| 60 |
+
class MySpider(Spider):
|
| 61 |
+
name = "demo"
|
| 62 |
+
start_urls = ["https://example.com/"]
|
| 63 |
|
| 64 |
+
async def parse(self, response: Response):
|
| 65 |
+
for item in response.css('.product'):
|
| 66 |
+
yield {"title": item.css('h2::text').get()}
|
| 67 |
+
|
| 68 |
+
MySpider().start()
|
| 69 |
+
```
|
| 70 |
+
|
| 71 |
+
|
| 72 |
+
# スポンサー
|
| 73 |
|
| 74 |
<!-- sponsors -->
|
| 75 |
|
|
|
|
| 93 |
|
| 94 |
## 主な機能
|
| 95 |
|
| 96 |
+
### Spider — 本格的なクロールフレームワーク
|
| 97 |
+
- 🕷️ **Scrapy風のSpider API**:`start_urls`、async `parse` callback、`Request`/`Response`オブジェクトでSpiderを定義。
|
| 98 |
+
- ⚡ **並行クロール**:設定可能な並行数制限、ドメインごとのスロットリング、ダウンロード遅延。
|
| 99 |
+
- 🔄 **マルチSessionサポート**:HTTPリクエストとステルスヘッドレスブラウザの統一インターフェース — IDによって異なるSessionにリクエストをルーティング。
|
| 100 |
+
- 💾 **Pause & Resume**:Checkpointベースのクロール永続化。Ctrl+Cで正常にシャットダウン;再起動すると中断したところから再開。
|
| 101 |
+
- 📡 **Streamingモード**:`async for item in spider.stream()`でリアルタイム統計とともにスクレイプされたアイテムをStreamingで受信 — UI、パイプライン、長時間実行クロールに最適。
|
| 102 |
+
- 🛡️ **ブロックされたリクエストの検出**:カスタマイズ可能なロジックによるブロックされたリクエストの自動検出とリトライ。
|
| 103 |
+
- 📦 **組み込みエクスポート**:フックや独自のパイプライン、または組み込みのJSON/JSONLで結果をエクスポート。それぞれ`result.items.to_json()` / `result.items.to_jsonl()`を使用。
|
| 104 |
+
|
| 105 |
+
### Sessionサポート付き高度なウェブサイト取得
|
| 106 |
+
- **HTTPリクエスト**:`Fetcher`クラスで高速かつステルスなHTTPリクエスト。ブラウザのTLS fingerprint、ヘッダーを模倣し、HTTP/3を使用可能。
|
| 107 |
+
- **動的読み込み**:PlaywrightのChromiumとGoogle Chromeをサポートする`DynamicFetcher`クラスによる完全なブラウザ自動化で動的ウェブサイトを取得。
|
| 108 |
+
- **アンチボット回避**:`StealthyFetcher`とfingerprint偽装による高度なステルス機能。自動化でCloudflareのTurnstile/Interstitialのすべてのタイプを簡単に回避。
|
| 109 |
+
- **Session管理**:リクエスト間でCookieと状態を管理するための`FetcherSession`、`StealthySession`、`DynamicSession`クラスによる永続的なSessionサポート。
|
| 110 |
+
- **Proxy回転**:すべてのSessionタイプに対応したラウンドロビンまたはカスタム戦略の組み込み`ProxyRotator`、さらにリクエストごとのProxyオーバーライド。
|
| 111 |
+
- **ドメインブロック**:ブラウザベースのFetcherで特定のドメイン(およびそのサブドメイン)へのリクエストをブロック。
|
| 112 |
+
- **asyncサポート**:すべてのFetcherおよび専用asyncSessionクラス全体での完全なasyncサポート。
|
| 113 |
|
| 114 |
### 適応型スクレイピングとAI統合
|
| 115 |
- 🔄 **スマート要素追跡**:インテリジェントな類似性アルゴリズムを使用してウェブサイトの変更後に要素を再配置。
|
| 116 |
- 🎯 **スマート柔軟選択**:CSSセレクタ、XPathセレクタ、フィルタベース検索、テキスト検索、正規表現検索など。
|
| 117 |
+
- 🔍 **類似要素の検出**:見つ��った要素に類似した要素を自動的に特定。
|
| 118 |
+
- 🤖 **AIと使用するMCPサーバー**:AI支援Web Scrapingとデータ抽出のための組み込みMCPサーバー。MCPサーバーは、AI(Claude/Cursorなど)に渡す前にScraplingを活用してターゲットコンテンツを抽出する強力でカスタムな機能を備えており、操作を高速化し、トークン使用量を最小限に抑えることでコストを削減します。([デモ動画](https://www.youtube.com/watch?v=qyFk3ZNwOxE))
|
| 119 |
|
| 120 |
### 高性能で実戦テスト済みのアーキテクチャ
|
| 121 |
+
- 🚀 **超高速**:ほとんどのPythonスクレイピングライブラリを上回る最適化されたパフォーマンス。
|
| 122 |
- 🔋 **メモリ効率**:最小のメモリフットプリントのための最適化されたデータ構造と遅延読み込み。
|
| 123 |
- ⚡ **高速JSONシリアル化**:標準ライブラリの10倍の速度。
|
| 124 |
+
- 🏗️ **実戦テスト済み**:Scraplingは92%のテストカバレッジと完全な型ヒントカバレッジを備えているだけでなく、過去1年間に数百人のWeb Scraperによって毎日使用されてきました。
|
| 125 |
|
| 126 |
+
### 開発者/Web Scraperにやさしい体験
|
| 127 |
+
- 🎯 **インタラクティブWeb Scraping Shell**:Scrapling統合、ショートカット、curlリクエストをScraplingリクエストに変換したり、ブラウザでリクエスト結果を表示したりするなどの新しいツールを備えたオプションの組み込みIPython Shellで、Web Scrapingスクリプトの開発を加速。
|
| 128 |
- 🚀 **ターミナルから直接使用**:オプションで、コードを一行も書かずにScraplingを使用してURLをスクレイプできます!
|
| 129 |
- 🛠️ **豊富なナビゲーションAPI**:親、兄弟、子のナビゲーションメソッドによる高度なDOMトラバーサル。
|
| 130 |
- 🧬 **強化されたテキスト処理**:組み込みの正規表現、クリーニングメソッド、最適化された文字列操作。
|
| 131 |
- 📝 **自動セレクタ生成**:任意の要素に対して堅牢なCSS/XPathセレクタを生成。
|
| 132 |
+
- 🔌 **馴染みのあるAPI**:Scrapy/Parselで使用されている同じ疑似要素を持つScrapy/BeautifulSoupに似た設計。
|
| 133 |
+
- 📘 **完全な型カバレッジ**:優れたIDEサポートとコード補完のための完全な型ヒント。コードベース全体が変更のたびに**PyRight**と**MyPy**で自動的にスキャンされます。
|
| 134 |
- 🔋 **すぐに使えるDockerイメージ**:各リリースで、すべてのブラウザを含むDockerイメージが自動的にビルドおよびプッシュされます。
|
| 135 |
|
| 136 |
## はじめに
|
| 137 |
|
| 138 |
+
深く掘り下げずに、Scraplingにできることの簡単な概要をお見せしましょう。
|
| 139 |
+
|
| 140 |
### 基本的な使い方
|
| 141 |
+
Sessionサポート付きHTTPリクエスト
|
| 142 |
```python
|
| 143 |
+
from scrapling.fetchers import Fetcher, FetcherSession
|
|
|
|
| 144 |
|
| 145 |
+
with FetcherSession(impersonate='chrome') as session: # ChromeのTLS fingerprintの最新バージョンを使用
|
|
|
|
| 146 |
page = session.get('https://quotes.toscrape.com/', stealthy_headers=True)
|
| 147 |
+
quotes = page.css('.quote .text::text').getall()
|
| 148 |
|
| 149 |
# または一回限りのリクエストを使用
|
| 150 |
page = Fetcher.get('https://quotes.toscrape.com/')
|
| 151 |
+
quotes = page.css('.quote .text::text').getall()
|
| 152 |
+
```
|
| 153 |
+
高度なステルスモード
|
| 154 |
+
```python
|
| 155 |
+
from scrapling.fetchers import StealthyFetcher, StealthySession
|
| 156 |
|
| 157 |
+
with StealthySession(headless=True, solve_cloudflare=True) as session: # 完了するまでブラウザを開いたままにする
|
|
|
|
| 158 |
page = session.fetch('https://nopecha.com/demo/cloudflare', google_search=False)
|
| 159 |
+
data = page.css('#padded_content a').getall()
|
| 160 |
|
| 161 |
+
# または一回限りのリクエストスタイル、このリクエストのためにブラウザを開き、完了後に閉じる
|
| 162 |
page = StealthyFetcher.fetch('https://nopecha.com/demo/cloudflare')
|
| 163 |
+
data = page.css('#padded_content a').getall()
|
| 164 |
+
```
|
| 165 |
+
完全なブラウザ自動化
|
| 166 |
+
```python
|
| 167 |
+
from scrapling.fetchers import DynamicFetcher, DynamicSession
|
| 168 |
+
|
| 169 |
+
with DynamicSession(headless=True, disable_resources=False, network_idle=True) as session: # 完了するまでブラウザを開いたままにする
|
| 170 |
+
page = session.fetch('https://quotes.toscrape.com/', load_dom=False)
|
| 171 |
+
data = page.xpath('//span[@class="text"]/text()').getall() # お好みであればXPathセレクタを使用
|
| 172 |
+
|
| 173 |
+
# または一回限りのリクエストスタイル、このリクエストのためにブラウザを開き、完了後に閉じる
|
| 174 |
+
page = DynamicFetcher.fetch('https://quotes.toscrape.com/')
|
| 175 |
+
data = page.css('.quote .text::text').getall()
|
| 176 |
```
|
| 177 |
|
| 178 |
+
### Spider
|
| 179 |
+
並行リクエスト、複数のSessionタイプ、Pause & Resumeを備えた本格的なクローラーを構築:
|
| 180 |
```python
|
| 181 |
+
from scrapling.spiders import Spider, Request, Response
|
| 182 |
+
|
| 183 |
+
class QuotesSpider(Spider):
|
| 184 |
+
name = "quotes"
|
| 185 |
+
start_urls = ["https://quotes.toscrape.com/"]
|
| 186 |
+
concurrent_requests = 10
|
| 187 |
+
|
| 188 |
+
async def parse(self, response: Response):
|
| 189 |
+
for quote in response.css('.quote'):
|
| 190 |
+
yield {
|
| 191 |
+
"text": quote.css('.text::text').get(),
|
| 192 |
+
"author": quote.css('.author::text').get(),
|
| 193 |
+
}
|
| 194 |
+
|
| 195 |
+
next_page = response.css('.next a')
|
| 196 |
+
if next_page:
|
| 197 |
+
yield response.follow(next_page[0].attrib['href'])
|
| 198 |
+
|
| 199 |
+
result = QuotesSpider().start()
|
| 200 |
+
print(f"{len(result.items)}件の引用をスクレイプしました")
|
| 201 |
+
result.items.to_json("quotes.json")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 202 |
```
|
| 203 |
+
単一のSpiderで複数のSessionタイプを使用:
|
| 204 |
+
```python
|
| 205 |
+
from scrapling.spiders import Spider, Request, Response
|
| 206 |
+
from scrapling.fetchers import FetcherSession, AsyncStealthySession
|
| 207 |
+
|
| 208 |
+
class MultiSessionSpider(Spider):
|
| 209 |
+
name = "multi"
|
| 210 |
+
start_urls = ["https://example.com/"]
|
| 211 |
+
|
| 212 |
+
def configure_sessions(self, manager):
|
| 213 |
+
manager.add("fast", FetcherSession(impersonate="chrome"))
|
| 214 |
+
manager.add("stealth", AsyncStealthySession(headless=True), lazy=True)
|
| 215 |
+
|
| 216 |
+
async def parse(self, response: Response):
|
| 217 |
+
for link in response.css('a::attr(href)').getall():
|
| 218 |
+
# 保護されたページはステルスSessionを通してルーティング
|
| 219 |
+
if "protected" in link:
|
| 220 |
+
yield Request(link, sid="stealth")
|
| 221 |
+
else:
|
| 222 |
+
yield Request(link, sid="fast", callback=self.parse) # 明示的なcallback
|
| 223 |
+
```
|
| 224 |
+
Checkpointを使用して長時間のクロールをPause & Resume:
|
| 225 |
+
```python
|
| 226 |
+
QuotesSpider(crawldir="./crawl_data").start()
|
| 227 |
+
```
|
| 228 |
+
Ctrl+Cを押すと正常に一時停止し、進捗は自動的に保存されます。後でSpiderを再度起動する際に同じ`crawldir`を渡すと、中断したところから再開します。
|
| 229 |
+
|
| 230 |
+
### 高度なパースとナビゲーション
|
| 231 |
+
```python
|
| 232 |
+
from scrapling.fetchers import Fetcher
|
| 233 |
+
|
| 234 |
+
# 豊富な要素選択とナビゲーション
|
| 235 |
+
page = Fetcher.get('https://quotes.toscrape.com/')
|
| 236 |
|
| 237 |
+
# 複数の選択メソッドで引用を取得
|
| 238 |
+
quotes = page.css('.quote') # CSSセレクタ
|
| 239 |
+
quotes = page.xpath('//div[@class="quote"]') # XPath
|
| 240 |
+
quotes = page.find_all('div', {'class': 'quote'}) # BeautifulSoupスタイル
|
| 241 |
+
# 以下と同じ
|
| 242 |
+
quotes = page.find_all('div', class_='quote')
|
| 243 |
+
quotes = page.find_all(['div'], class_='quote')
|
| 244 |
+
quotes = page.find_all(class_='quote') # など...
|
| 245 |
+
# テキスト内容で要素を検索
|
| 246 |
+
quotes = page.find_by_text('quote', tag='div')
|
| 247 |
+
|
| 248 |
+
# 高度なナビゲーション
|
| 249 |
+
quote_text = page.css('.quote')[0].css('.text::text').get()
|
| 250 |
+
quote_text = page.css('.quote').css('.text::text').getall() # チェーンセレクタ
|
| 251 |
+
first_quote = page.css('.quote')[0]
|
| 252 |
+
author = first_quote.next_sibling.css('.author::text')
|
| 253 |
+
parent_container = first_quote.parent
|
| 254 |
+
|
| 255 |
+
# 要素の関連性と類似性
|
| 256 |
+
similar_elements = first_quote.find_similar()
|
| 257 |
+
below_elements = first_quote.below_elements()
|
| 258 |
+
```
|
| 259 |
+
ウェブサイトを取得せずにパーサーをすぐに使用することもできます:
|
| 260 |
```python
|
| 261 |
+
from scrapling.parser import Selector
|
| 262 |
+
|
| 263 |
+
page = Selector("<html>...</html>")
|
| 264 |
+
```
|
| 265 |
+
まったく同じ方法で動作します!
|
| 266 |
+
|
| 267 |
+
### 非同期Session管理の例
|
| 268 |
+
```python
|
| 269 |
+
import asyncio
|
| 270 |
+
from scrapling.fetchers import FetcherSession, AsyncStealthySession, AsyncDynamicSession
|
| 271 |
+
|
| 272 |
+
async with FetcherSession(http3=True) as session: # `FetcherSession`はコンテキストアウェアで、同期/非同期両方のパターンで動作可能
|
| 273 |
+
page1 = session.get('https://quotes.toscrape.com/')
|
| 274 |
page2 = session.get('https://quotes.toscrape.com/', impersonate='firefox135')
|
| 275 |
|
| 276 |
+
# 非同期Sessionの使用
|
| 277 |
async with AsyncStealthySession(max_pages=2) as session:
|
| 278 |
tasks = []
|
| 279 |
urls = ['https://example.com/page1', 'https://example.com/page2']
|
| 280 |
+
|
| 281 |
for url in urls:
|
| 282 |
task = session.fetch(url)
|
| 283 |
tasks.append(task)
|
| 284 |
+
|
| 285 |
print(session.get_pool_stats()) # オプション - ブラウザタブプールのステータス(ビジー/フリー/エラー)
|
| 286 |
results = await asyncio.gather(*tasks)
|
| 287 |
print(session.get_pool_stats())
|
| 288 |
```
|
| 289 |
|
| 290 |
+
## CLIとインタラクティブShell
|
| 291 |
|
| 292 |
+
Scraplingには強力なコマンドラインインターフェースが含まれています:
|
| 293 |
|
| 294 |
[](https://asciinema.org/a/736339)
|
| 295 |
|
| 296 |
+
インタラクティブWeb Scraping Shellを起動
|
| 297 |
```bash
|
| 298 |
scrapling shell
|
| 299 |
```
|
| 300 |
+
プログラミングせずに直接ページをファイルに抽出(デフォルトで`body`タグ内のコンテンツを抽出)。出力ファイルが`.txt`で終わる場合、ターゲットのテキストコンテンツが抽出されます。`.md`で終わる場合、HTMLコンテンツのMarkdown表現になります。`.html`で終わる場合、HTMLコンテンツそのものになります。
|
| 301 |
```bash
|
| 302 |
scrapling extract get 'https://example.com' content.md
|
| 303 |
scrapling extract get 'https://example.com' content.txt --css-selector '#fromSkipToProducts' --impersonate 'chrome' # CSSセレクタ'#fromSkipToProducts'に一致するすべての要素
|
|
|
|
| 306 |
```
|
| 307 |
|
| 308 |
> [!NOTE]
|
| 309 |
+
> MCPサーバーやインタラク��ィブWeb Scraping Shellなど、他にも多くの追加機能がありますが、このページは簡潔に保ちたいと思います。完全なドキュメントは[こちら](https://scrapling.readthedocs.io/en/latest/)をご覧ください
|
| 310 |
|
| 311 |
## パフォーマンスベンチマーク
|
| 312 |
|
| 313 |
+
Scraplingは強力であるだけでなく、超高速です。以下のベンチマークは、Scraplingのパーサーを他の人気ライブラリの最新バージョンと比較しています。
|
| 314 |
|
| 315 |
### テキスト抽出速度テスト(5000個のネストされた要素)
|
| 316 |
|
| 317 |
+
| # | ライブラリ | 時間(ms) | vs Scrapling |
|
| 318 |
+
|---|:-----------------:|:---------:|:------------:|
|
| 319 |
+
| 1 | Scrapling | 2.02 | 1.0x |
|
| 320 |
+
| 2 | Parsel/Scrapy | 2.04 | 1.01 |
|
| 321 |
+
| 3 | Raw Lxml | 2.54 | 1.257 |
|
| 322 |
+
| 4 | PyQuery | 24.17 | ~12x |
|
| 323 |
+
| 5 | Selectolax | 82.63 | ~41x |
|
| 324 |
+
| 6 | MechanicalSoup | 1549.71 | ~767.1x |
|
| 325 |
+
| 7 | BS4 with Lxml | 1584.31 | ~784.3x |
|
| 326 |
+
| 8 | BS4 with html5lib | 3391.91 | ~1679.1x |
|
| 327 |
|
| 328 |
|
| 329 |
### 要素類似性とテキスト検索のパフォーマンス
|
| 330 |
|
| 331 |
Scraplingの適応型要素検索機能は代替手段を大幅に上回ります:
|
| 332 |
|
| 333 |
+
| ライブラリ | 時間(ms) | vs Scrapling |
|
| 334 |
+
|-------------|:---------:|:------------:|
|
| 335 |
+
| Scrapling | 2.39 | 1.0x |
|
| 336 |
+
| AutoScraper | 12.45 | 5.209x |
|
| 337 |
|
| 338 |
|
| 339 |
> すべてのベンチマークは100回以上の実行の平均を表します。方法論については[benchmarks.py](https://github.com/D4Vinci/Scrapling/blob/main/benchmarks.py)を参照してください。
|
|
|
|
| 346 |
pip install scrapling
|
| 347 |
```
|
| 348 |
|
| 349 |
+
このインストールにはパーサーエンジンとその依存関係のみが含まれており、Fetcherやコマンドライン依存関係は含まれていません。
|
| 350 |
|
| 351 |
### オプションの依存関係
|
| 352 |
|
| 353 |
+
1. 以下の追加機能、Fetcher、またはそれらのクラスのいずれかを使用する場合は、Fetcherの依存関係とブラウザの依存関係を次のようにインストールする必要があります:
|
| 354 |
```bash
|
| 355 |
pip install "scrapling[fetchers]"
|
| 356 |
+
|
| 357 |
scrapling install
|
| 358 |
```
|
| 359 |
|
| 360 |
+
これにより、すべてのブラウザ、およびそれらのシステム依存関係とfingerprint操作依存関係がダウンロードされます。
|
| 361 |
|
| 362 |
2. 追加機能:
|
| 363 |
- MCPサーバー機能をインストール:
|
| 364 |
```bash
|
| 365 |
pip install "scrapling[ai]"
|
| 366 |
```
|
| 367 |
+
- Shell機能(Web Scraping Shellと`extract`コマンド)をインストール:
|
| 368 |
```bash
|
| 369 |
pip install "scrapling[shell]"
|
| 370 |
```
|
|
|
|
| 403 |
このプロジェクトには次から適応されたコードが含まれています:
|
| 404 |
- Parsel(BSDライセンス)— [translator](https://github.com/D4Vinci/Scrapling/blob/main/scrapling/core/translator.py)サブモジュールに使用
|
| 405 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 406 |
---
|
| 407 |
+
<div align="center"><small>Karim Shoairによって❤️でデザインおよび作成されました。</small></div><br>
|
docs/README_RU.md
CHANGED
|
@@ -6,8 +6,9 @@
|
|
| 6 |
</picture>
|
| 7 |
</a>
|
| 8 |
<br>
|
| 9 |
-
<small>Web Scraping
|
| 10 |
</h1>
|
|
|
|
| 11 |
<p align="center">
|
| 12 |
<a href="https://github.com/D4Vinci/Scrapling/actions/workflows/tests.yml" alt="Tests">
|
| 13 |
<img alt="Tests" src="https://github.com/D4Vinci/Scrapling/actions/workflows/tests.yml/badge.svg"></a>
|
|
@@ -28,46 +29,47 @@
|
|
| 28 |
</p>
|
| 29 |
|
| 30 |
<p align="center">
|
| 31 |
-
<a href="https://scrapling.readthedocs.io/en/latest/parsing/selection/">
|
| 32 |
-
|
| 33 |
-
</a>
|
| 34 |
-
|
| 35 |
-
<a href="https://scrapling.readthedocs.io/en/latest/
|
| 36 |
-
|
| 37 |
-
</a>
|
| 38 |
-
|
| 39 |
-
<a href="https://scrapling.readthedocs.io/en/latest/
|
| 40 |
-
CLI
|
| 41 |
-
</a>
|
| 42 |
-
·
|
| 43 |
-
<a href="https://scrapling.readthedocs.io/en/latest/ai/mcp-server/">
|
| 44 |
-
Режим MCP
|
| 45 |
-
</a>
|
| 46 |
-
·
|
| 47 |
-
<a href="https://scrapling.readthedocs.io/en/latest/tutorials/migrating_from_beautifulsoup/">
|
| 48 |
-
Миграция с Beautifulsoup
|
| 49 |
-
</a>
|
| 50 |
</p>
|
| 51 |
|
| 52 |
-
|
| 53 |
|
| 54 |
-
|
| 55 |
|
| 56 |
-
|
| 57 |
|
| 58 |
```python
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
#
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
200
|
| 65 |
-
>> products = page.css('.product', auto_save=True) # Скрапьте данные, которые переживут изменения дизайна сайта!
|
| 66 |
-
>> # Позже, если структура сайта изменится, передайте `adaptive=True`
|
| 67 |
-
>> products = page.css('.product', adaptive=True) # и Scrapling все равно их найдет!
|
| 68 |
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 69 |
|
| 70 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 71 |
|
| 72 |
<!-- sponsors -->
|
| 73 |
|
|
@@ -91,138 +93,211 @@ Scrapling - это не просто очередная библиотека д
|
|
| 91 |
|
| 92 |
## Ключевые особенности
|
| 93 |
|
| 94 |
-
###
|
| 95 |
-
- **
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 96 |
- **Динамическая загрузка**: Загрузка динамических сайтов с полной автоматизацией браузера через класс `DynamicFetcher`, поддерживающий Chromium от Playwright и Google Chrome.
|
| 97 |
-
- **Обход анти-ботов**: Расширенные возможности скрытности с `StealthyFetcher` и подмену о
|
| 98 |
- **Управление сессиями**: Поддержка постоянных сессий с классами `FetcherSession`, `StealthySession` и `DynamicSession` для управления cookie и состоянием между запросами.
|
| 99 |
-
- **
|
|
|
|
|
|
|
| 100 |
|
| 101 |
### Адаптивный скрапинг и интеграция с ИИ
|
| 102 |
- 🔄 **Умное отслеживание элементов**: Перемещайте элементы после изменений сайта с помощью интеллектуальных алгоритмов подобия.
|
| 103 |
- 🎯 **Умный гибкий выбор**: CSS-селекторы, XPath-селекторы, поиск на основе фильтров, текстовый поиск, поиск по регулярным выражениям и многое другое.
|
| 104 |
-
- 🔍 **Поиск похожих элементов**: Автоматически находите элементы, похожие на найденные
|
| 105 |
-
- 🤖 **MCP-сервер для использования с ИИ**: Встроенный MCP-сервер для
|
| 106 |
|
| 107 |
### Высокопроизводительная и проверенная в боях архитектура
|
| 108 |
-
- 🚀 **Молниеносн
|
| 109 |
- 🔋 **Эффективное использование памяти**: Оптимизированные структуры данных и ленивая загрузка для минимального потребления памяти.
|
| 110 |
-
- ⚡ **Быстрая сериализация JSON**: В 10 раз быстрее
|
| 111 |
- 🏗️ **Проверено в боях**: Scrapling имеет не только 92% покрытия тестами и полное покрытие type hints, но и ежедневно использовался сотнями веб-скраперов в течение последнего года.
|
| 112 |
|
| 113 |
### Удобный для разработчиков/веб-скраперов опыт
|
| 114 |
-
- 🎯 **Интерактивная
|
| 115 |
- 🚀 **Используйте прямо из терминала**: При желании вы можете использовать Scrapling для скрапинга URL без написания ни одной строки кода!
|
| 116 |
- 🛠️ **Богатый API навигации**: Расширенный обход DOM с методами навигации по родителям, братьям и детям.
|
| 117 |
- 🧬 **Улучшенная обработка текста**: Встроенные регулярные выражения, методы очистки и оптимизированные операции со строками.
|
| 118 |
-
- 📝 **Автоматическая генерация селекторов**: Генерация над
|
| 119 |
- 🔌 **Знакомый API**: Похож на Scrapy/BeautifulSoup с теми же псевдоэлементами, используемыми в Scrapy/Parsel.
|
| 120 |
-
- 📘 **Полное покрытие типами**: Полные
|
| 121 |
-
- 🔋 **Готовый Docker-образ**: С каждым релизом автоматически созда
|
| 122 |
|
| 123 |
## Начало работы
|
| 124 |
|
|
|
|
|
|
|
| 125 |
### Базовое использование
|
|
|
|
| 126 |
```python
|
| 127 |
-
from scrapling.fetchers import Fetcher,
|
| 128 |
-
from scrapling.fetchers import FetcherSession, StealthySession, DynamicSession
|
| 129 |
|
| 130 |
-
#
|
| 131 |
-
with FetcherSession(impersonate='chrome') as session: # Используйте последнюю версию TLS-отпечатка Chrome
|
| 132 |
page = session.get('https://quotes.toscrape.com/', stealthy_headers=True)
|
| 133 |
-
quotes = page.css('.quote .text::text')
|
| 134 |
|
| 135 |
# Или используйте одноразовые запросы
|
| 136 |
page = Fetcher.get('https://quotes.toscrape.com/')
|
| 137 |
-
quotes = page.css('.quote .text::text')
|
|
|
|
|
|
|
|
|
|
|
|
|
| 138 |
|
| 139 |
-
|
| 140 |
-
with StealthySession(headless=True, solve_cloudflare=True) as session:
|
| 141 |
page = session.fetch('https://nopecha.com/demo/cloudflare', google_search=False)
|
| 142 |
-
data = page.css('#padded_content a')
|
| 143 |
|
| 144 |
-
# Или используйте стиль одноразового запроса
|
| 145 |
page = StealthyFetcher.fetch('https://nopecha.com/demo/cloudflare')
|
| 146 |
-
data = page.css('#padded_content a')
|
| 147 |
-
|
| 148 |
-
|
| 149 |
-
|
| 150 |
-
|
| 151 |
-
|
| 152 |
-
|
| 153 |
-
|
| 154 |
-
|
| 155 |
-
|
|
|
|
|
|
|
|
|
|
| 156 |
```
|
| 157 |
|
| 158 |
-
###
|
|
|
|
| 159 |
```python
|
| 160 |
-
|
| 161 |
-
|
| 162 |
-
|
| 163 |
-
|
| 164 |
-
|
| 165 |
-
|
| 166 |
-
|
| 167 |
-
|
| 168 |
-
|
| 169 |
-
|
| 170 |
-
|
| 171 |
-
|
| 172 |
-
|
| 173 |
-
|
| 174 |
-
|
| 175 |
-
|
| 176 |
-
|
| 177 |
-
|
| 178 |
-
|
| 179 |
-
|
| 180 |
-
|
| 181 |
-
|
| 182 |
-
# Адаптивный скрапинг
|
| 183 |
-
saved_elements = page.css('.product', auto_save=True)
|
| 184 |
-
# Позже, когда сайт изменится:
|
| 185 |
-
page.css('.product', adaptive=True) # Найти элементы используя сохраненные позиции
|
| 186 |
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 187 |
|
| 188 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 189 |
```python
|
| 190 |
-
from scrapling.
|
| 191 |
-
|
| 192 |
-
|
| 193 |
-
|
| 194 |
-
|
| 195 |
-
|
| 196 |
-
|
| 197 |
-
|
| 198 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 199 |
page2 = session.get('https://quotes.toscrape.com/', impersonate='firefox135')
|
| 200 |
|
| 201 |
-
# Использование
|
| 202 |
async with AsyncStealthySession(max_pages=2) as session:
|
| 203 |
tasks = []
|
| 204 |
urls = ['https://example.com/page1', 'https://example.com/page2']
|
| 205 |
-
|
| 206 |
for url in urls:
|
| 207 |
task = session.fetch(url)
|
| 208 |
tasks.append(task)
|
| 209 |
-
|
| 210 |
-
print(session.get_pool_stats()) # Опционально
|
| 211 |
results = await asyncio.gather(*tasks)
|
| 212 |
print(session.get_pool_stats())
|
| 213 |
```
|
| 214 |
|
| 215 |
-
## CLI и интерактивная
|
| 216 |
|
| 217 |
-
Scrapling
|
| 218 |
|
| 219 |
[](https://asciinema.org/a/736339)
|
| 220 |
|
| 221 |
-
Запустить интерактивную
|
| 222 |
```bash
|
| 223 |
scrapling shell
|
| 224 |
```
|
| 225 |
-
Извлечь страницы в файл напрямую без программирования (
|
| 226 |
```bash
|
| 227 |
scrapling extract get 'https://example.com' content.md
|
| 228 |
scrapling extract get 'https://example.com' content.txt --css-selector '#fromSkipToProducts' --impersonate 'chrome' # Все элементы, соответствующие CSS-селектору '#fromSkipToProducts'
|
|
@@ -231,24 +306,24 @@ scrapling extract stealthy-fetch 'https://nopecha.com/demo/cloudflare' captchas.
|
|
| 231 |
```
|
| 232 |
|
| 233 |
> [!NOTE]
|
| 234 |
-
> Есть мно
|
| 235 |
|
| 236 |
## Тесты производительности
|
| 237 |
|
| 238 |
-
Scrapling не только мощный
|
| 239 |
|
| 240 |
### Тест скорости извлечения текста (5000 вложенных элементов)
|
| 241 |
|
| 242 |
-
| # | Библиотека | Время (мс) | vs Scrapling |
|
| 243 |
|---|:-----------------:|:----------:|:------------:|
|
| 244 |
-
| 1 | Scrapling |
|
| 245 |
-
| 2 | Parsel/Scrapy | 2.
|
| 246 |
-
| 3 | Raw Lxml | 2.
|
| 247 |
-
| 4 | PyQuery |
|
| 248 |
-
| 5 | Selectolax |
|
| 249 |
-
| 6 |
|
| 250 |
-
| 7 |
|
| 251 |
-
| 8 | BS4 with html5lib |
|
| 252 |
|
| 253 |
|
| 254 |
### Производительность подобия элементов и текстового поиска
|
|
@@ -257,8 +332,8 @@ Scrapling не только мощный - он также невероятно
|
|
| 257 |
|
| 258 |
| Библиотека | Время (мс) | vs Scrapling |
|
| 259 |
|-------------|:----------:|:------------:|
|
| 260 |
-
| Scrapling | 2.
|
| 261 |
-
| AutoScraper |
|
| 262 |
|
| 263 |
|
| 264 |
> Все тесты производительности представляют собой средние значения более 100 запусков. См. [benchmarks.py](https://github.com/D4Vinci/Scrapling/blob/main/benchmarks.py) для методологии.
|
|
@@ -271,33 +346,33 @@ Scrapling требует Python 3.10 или выше:
|
|
| 271 |
pip install scrapling
|
| 272 |
```
|
| 273 |
|
| 274 |
-
|
| 275 |
|
| 276 |
### Опциональные зависимости
|
| 277 |
|
| 278 |
-
1. Если вы собираетесь использовать какие-либо из дополнительных
|
| 279 |
```bash
|
| 280 |
pip install "scrapling[fetchers]"
|
| 281 |
-
|
| 282 |
scrapling install
|
| 283 |
```
|
| 284 |
|
| 285 |
-
Это загрузит все браузеры вместе с их системными зависимостями и зависимостями манипуляции
|
| 286 |
|
| 287 |
-
2. Дополнительные
|
| 288 |
- Установить функцию MCP-сервера:
|
| 289 |
```bash
|
| 290 |
pip install "scrapling[ai]"
|
| 291 |
```
|
| 292 |
-
- Установить функции
|
| 293 |
```bash
|
| 294 |
pip install "scrapling[shell]"
|
| 295 |
```
|
| 296 |
-
- Установить вс
|
| 297 |
```bash
|
| 298 |
pip install "scrapling[all]"
|
| 299 |
```
|
| 300 |
-
Помните, что вам нужно установить зависимости браузер
|
| 301 |
|
| 302 |
### Docker
|
| 303 |
Вы также можете установить Docker-образ со всеми дополнениями и браузерами с помощью следующей команды из DockerHub:
|
|
@@ -308,11 +383,11 @@ docker pull pyd4vinci/scrapling
|
|
| 308 |
```bash
|
| 309 |
docker pull ghcr.io/d4vinci/scrapling:latest
|
| 310 |
```
|
| 311 |
-
Этот образ автоматически созда
|
| 312 |
|
| 313 |
-
##
|
| 314 |
|
| 315 |
-
Мы приветствуем
|
| 316 |
|
| 317 |
## Отказ от ответственности
|
| 318 |
|
|
@@ -328,12 +403,5 @@ docker pull ghcr.io/d4vinci/scrapling:latest
|
|
| 328 |
Этот проект включает код, адаптированный из:
|
| 329 |
- Parsel (лицензия BSD) — Используется для подмодуля [translator](https://github.com/D4Vinci/Scrapling/blob/main/scrapling/core/translator.py)
|
| 330 |
|
| 331 |
-
## Благодарности и ссылки
|
| 332 |
-
|
| 333 |
-
- Блестящая работа [Daijro](https://github.com/daijro) над [BrowserForge](https://github.com/daijro/browserforge) и [Camoufox](https://github.com/daijro/camoufox)
|
| 334 |
-
- Блестящая работа [Vinyzu](https://github.com/Vinyzu) над [Botright](https://github.com/Vinyzu/Botright) и [PatchRight](https://github.com/Kaliiiiiiiiii-Vinyzu/patchright)
|
| 335 |
-
- [brotector](https://github.com/kaliiiiiiiiii/brotector) за техники обхода обнаружения браузера
|
| 336 |
-
- [fakebrowser](https://github.com/kkoooqq/fakebrowser) и [BotBrowser](https://github.com/botswin/BotBrowser) за исследование отпечатков
|
| 337 |
-
|
| 338 |
---
|
| 339 |
-
<div align="center"><small>Разработано и создано с ❤️ Карим Шоаир.</small></div><br>
|
|
|
|
| 6 |
</picture>
|
| 7 |
</a>
|
| 8 |
<br>
|
| 9 |
+
<small>Effortless Web Scraping for the Modern Web</small>
|
| 10 |
</h1>
|
| 11 |
+
|
| 12 |
<p align="center">
|
| 13 |
<a href="https://github.com/D4Vinci/Scrapling/actions/workflows/tests.yml" alt="Tests">
|
| 14 |
<img alt="Tests" src="https://github.com/D4Vinci/Scrapling/actions/workflows/tests.yml/badge.svg"></a>
|
|
|
|
| 29 |
</p>
|
| 30 |
|
| 31 |
<p align="center">
|
| 32 |
+
<a href="https://scrapling.readthedocs.io/en/latest/parsing/selection/"><strong>Методы выбора</strong></a>
|
| 33 |
+
·
|
| 34 |
+
<a href="https://scrapling.readthedocs.io/en/latest/fetching/choosing/"><strong>Выбор Fetcher</strong></a>
|
| 35 |
+
·
|
| 36 |
+
<a href="https://scrapling.readthedocs.io/en/latest/cli/overview/"><strong>CLI</strong></a>
|
| 37 |
+
·
|
| 38 |
+
<a href="https://scrapling.readthedocs.io/en/latest/ai/mcp-server/"><strong>Режим MCP</strong></a>
|
| 39 |
+
·
|
| 40 |
+
<a href="https://scrapling.readthedocs.io/en/latest/tutorials/migrating_from_beautifulsoup/"><strong>Миграция с Beautifulsoup</strong></a>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 41 |
</p>
|
| 42 |
|
| 43 |
+
Scrapling — это адаптивный фреймворк для Web Scraping, который берёт на себя всё: от одного запроса до полномасштабного обхода сайтов.
|
| 44 |
|
| 45 |
+
Его парсер учится на изменениях сайтов и автоматически перемещает ваши элементы при обновлении страниц. Его Fetcher'ы обходят анти-бот системы вроде Cloudflare Turnstile прямо из коробки. А его Spider-фреймворк позволяет масштабироваться до параллельных, многосессионных обходов с Pause & Resume и автоматической ротацией Proxy — и всё это в нескольких строках Python. Одна библиотека, без компромиссов.
|
| 46 |
|
| 47 |
+
Молниеносно быстрые обходы с отслеживанием статистики в реальном времени и Streaming. Создано веб-скраперами для веб-скраперов и обычных пользователей — здесь есть что-то для каждого.
|
| 48 |
|
| 49 |
```python
|
| 50 |
+
from scrapling.fetchers import Fetcher, AsyncFetcher, StealthyFetcher, DynamicFetcher
|
| 51 |
+
StealthyFetcher.adaptive = True
|
| 52 |
+
page = StealthyFetcher.fetch('https://example.com', headless=True, network_idle=True) # Загрузите сайт незаметно!
|
| 53 |
+
products = page.css('.product', auto_save=True) # Скрапьте данные, которые переживут изменения дизайна сайта!
|
| 54 |
+
products = page.css('.product', adaptive=True) # Позже, если структура сайта изменится, передайте `adaptive=True`, чтобы найти их!
|
|
|
|
|
|
|
|
|
|
|
|
|
| 55 |
```
|
| 56 |
+
Или масштабируйте до полного обхода
|
| 57 |
+
```python
|
| 58 |
+
from scrapling.spiders import Spider, Response
|
| 59 |
+
|
| 60 |
+
class MySpider(Spider):
|
| 61 |
+
name = "demo"
|
| 62 |
+
start_urls = ["https://example.com/"]
|
| 63 |
|
| 64 |
+
async def parse(self, response: Response):
|
| 65 |
+
for item in response.css('.product'):
|
| 66 |
+
yield {"title": item.css('h2::text').get()}
|
| 67 |
+
|
| 68 |
+
MySpider().start()
|
| 69 |
+
```
|
| 70 |
+
|
| 71 |
+
|
| 72 |
+
# Спонсоры
|
| 73 |
|
| 74 |
<!-- sponsors -->
|
| 75 |
|
|
|
|
| 93 |
|
| 94 |
## Ключевые особенности
|
| 95 |
|
| 96 |
+
### Spider'ы — полноценный фреймворк для обхода сайтов
|
| 97 |
+
- 🕷️ **Scrapy-подобный Spider API**: Определяйте Spider'ов с `start_urls`, async `parse` callback'ами и объектами `Request`/`Response`.
|
| 98 |
+
- ⚡ **Параллельный обход**: Настраиваемые лимиты параллелизма, ограничение скорости по домену и задержки загрузки.
|
| 99 |
+
- 🔄 **Поддержка нескольких сессий**: Единый интерфейс для HTTP-запросов и скрытных headless-браузеров в одном Spider — маршрутизируйте запросы к разным сессиям по ID.
|
| 100 |
+
- 💾 **Pause & Resume**: Persistence обхода на основе Checkpoint'ов. Нажмите Ctrl+C для мягкой остановки; перезапустите, чтобы продолжить с того места, где вы остановились.
|
| 101 |
+
- 📡 **Режим Streaming**: Стримьте извлечённые элементы по мере их поступления через `async for item in spider.stream()` со статистикой в реальном времени — идеально для UI, конвейеров и длительных обходов.
|
| 102 |
+
- 🛡️ **Обнаружение заблокированных запросов**: Автоматическое обнаружение и повторная отправка заблокированных запросов с настраиваемой логикой.
|
| 103 |
+
- 📦 **Встроенный экспорт**: Экспортируйте результаты через хуки и собственный конвейер или встроенный JSON/JSONL с `result.items.to_json()` / `result.items.to_jsonl()` соответственно.
|
| 104 |
+
|
| 105 |
+
### Продвинутая загрузка сайтов с поддержкой Session
|
| 106 |
+
- **HTTP-запросы**: Быстрые и скрытные HTTP-запросы с классом `Fetcher`. Может имитировать TLS fingerprint браузера, заголовки и использовать HTTP/3.
|
| 107 |
- **Динамическая загрузка**: Загрузка динамических сайтов с полной автоматизацией браузера через класс `DynamicFetcher`, поддерживающий Chromium от Playwright и Google Chrome.
|
| 108 |
+
- **Обход анти-ботов**: Расширенные возможности скрытности с `StealthyFetcher` и подмену fingerprint'ов. Может легко обойти все типы Cloudflare Turnstile/Interstitial с помощью автоматизации.
|
| 109 |
- **Управление сессиями**: Поддержка постоянных сессий с классами `FetcherSession`, `StealthySession` и `DynamicSession` для управления cookie и состоянием между запросами.
|
| 110 |
+
- **Ротация Proxy**: Встроенный `ProxyRotator` с round-robin или пользовательскими стратегиями для всех типов сессий, а также переопределение Proxy для каждого запроса.
|
| 111 |
+
- **Блокировка доменов**: Блокируйте запросы к определённым доменам (и их поддоменам) в браузерных Fetcher'ах.
|
| 112 |
+
- **Поддержка async**: Полная async-поддержка во всех Fetcher'ах и выделенных async-классах сессий.
|
| 113 |
|
| 114 |
### Адаптивный скрапинг и интеграция с ИИ
|
| 115 |
- 🔄 **Умное отслеживание элементов**: Перемещайте элементы после изменений сайта с помощью интеллектуальных алгоритмов подобия.
|
| 116 |
- 🎯 **Умный гибкий выбор**: CSS-селекторы, XPath-селекторы, поиск на основе фильтров, текстовый поиск, поиск по регулярным выражениям и многое другое.
|
| 117 |
+
- 🔍 **Поиск похожих элементов**: Автоматически находите элементы, похожие на найденные.
|
| 118 |
+
- 🤖 **MCP-сервер для использования с ИИ**: Встроенный MCP-сервер для Web Scraping с помощью ИИ и извлечения данных. MCP-сервер обладает мощными пользовательскими возможностями, которые используют Scrapling для извлечения целевого контента перед передачей его ИИ (Claude/Cursor/и т.д.), тем самым ускоряя операции и снижая затраты за счёт минимизации использования токенов. ([демо-видео](https://www.youtube.com/watch?v=qyFk3ZNwOxE))
|
| 119 |
|
| 120 |
### Высокопроизводительная и проверенная в боях архитектура
|
| 121 |
+
- 🚀 **Молниеносная скорость**: Оптимизированная производительность, превосходящая большинство Python-библиотек для скрапинга.
|
| 122 |
- 🔋 **Эффективное использование памяти**: Оптимизированные структуры данных и ленивая загрузка для минимального потребления памяти.
|
| 123 |
+
- ⚡ **Быстрая сериализация JSON**: В 10 раз быстрее стандартной библиотеки.
|
| 124 |
- 🏗️ **Проверено в боях**: Scrapling имеет не только 92% покрытия тестами и полное покрытие type hints, но и ежедневно использовался сотнями веб-скраперов в течение последнего года.
|
| 125 |
|
| 126 |
### Удобный для разработчиков/веб-скраперов опыт
|
| 127 |
+
- 🎯 **Интерактивная Web Scraping Shell**: Опциональная встроенная IPython-оболочка с интеграцией Scrapling, ярлыками и новыми инструментами для ускорения разработки скриптов Web Scraping, такими как преобразование curl-запросов в запросы Scrapling и просмотр результатов запросов в браузере.
|
| 128 |
- 🚀 **Используйте прямо из терминала**: При желании вы можете использовать Scrapling для скрапинга URL без написания ни одной строки кода!
|
| 129 |
- 🛠️ **Богатый API навигации**: Расширенный обход DOM с методами навигации по родителям, братьям и детям.
|
| 130 |
- 🧬 **Улучшенная обработка текста**: Встроенные регулярные выражения, методы очистки и оптимизированные операции со строками.
|
| 131 |
+
- 📝 **Автоматическая генерация селекторов**: Генерация надёжных CSS/XPath-селекторов для любого элемента.
|
| 132 |
- 🔌 **Знакомый API**: Похож на Scrapy/BeautifulSoup с теми же псевдоэлементами, используемыми в Scrapy/Parsel.
|
| 133 |
+
- 📘 **Полное покрытие типами**: Полные type hints для отличной поддержки IDE и автодополнения кода. Вся кодовая база автоматически проверяется **PyRight** и **MyPy** при каждом изменении.
|
| 134 |
+
- 🔋 **Готовый Docker-образ**: С каждым релизом автоматически создаётся и публикуется Docker-образ, содержащий все браузеры.
|
| 135 |
|
| 136 |
## Начало работы
|
| 137 |
|
| 138 |
+
Давайте кратко покажем, на что способен Scrapling, без глубокого погружения.
|
| 139 |
+
|
| 140 |
### Базовое использование
|
| 141 |
+
HTTP-запросы с поддержкой Session
|
| 142 |
```python
|
| 143 |
+
from scrapling.fetchers import Fetcher, FetcherSession
|
|
|
|
| 144 |
|
| 145 |
+
with FetcherSession(impersonate='chrome') as session: # Используйте последнюю версию TLS fingerprint Chrome
|
|
|
|
| 146 |
page = session.get('https://quotes.toscrape.com/', stealthy_headers=True)
|
| 147 |
+
quotes = page.css('.quote .text::text').getall()
|
| 148 |
|
| 149 |
# Или используйте одноразовые запросы
|
| 150 |
page = Fetcher.get('https://quotes.toscrape.com/')
|
| 151 |
+
quotes = page.css('.quote .text::text').getall()
|
| 152 |
+
```
|
| 153 |
+
Расширенный режим скрытности
|
| 154 |
+
```python
|
| 155 |
+
from scrapling.fetchers import StealthyFetcher, StealthySession
|
| 156 |
|
| 157 |
+
with StealthySession(headless=True, solve_cloudflare=True) as session: # Держите браузер открытым, пока не закончите
|
|
|
|
| 158 |
page = session.fetch('https://nopecha.com/demo/cloudflare', google_search=False)
|
| 159 |
+
data = page.css('#padded_content a').getall()
|
| 160 |
|
| 161 |
+
# Или используйте стиль одноразового запроса — открывает браузер для этого запроса, затем закрывает его после завершения
|
| 162 |
page = StealthyFetcher.fetch('https://nopecha.com/demo/cloudflare')
|
| 163 |
+
data = page.css('#padded_content a').getall()
|
| 164 |
+
```
|
| 165 |
+
Полная автоматизация браузера
|
| 166 |
+
```python
|
| 167 |
+
from scrapling.fetchers import DynamicFetcher, DynamicSession
|
| 168 |
+
|
| 169 |
+
with DynamicSession(headless=True, disable_resources=False, network_idle=True) as session: # Держите браузер открытым, пока не закончите
|
| 170 |
+
page = session.fetch('https://quotes.toscrape.com/', load_dom=False)
|
| 171 |
+
data = page.xpath('//span[@class="text"]/text()').getall() # XPath-селектор, если вы предпочитаете его
|
| 172 |
+
|
| 173 |
+
# Или используйте стиль одноразового запроса — открывает браузер для этого запроса, затем закрывает его после завершения
|
| 174 |
+
page = DynamicFetcher.fetch('https://quotes.toscrape.com/')
|
| 175 |
+
data = page.css('.quote .text::text').getall()
|
| 176 |
```
|
| 177 |
|
| 178 |
+
### Spider'ы
|
| 179 |
+
Создавайте полноценные обходчики с параллельными запросами, несколькими типами сессий и Pause & Resume:
|
| 180 |
```python
|
| 181 |
+
from scrapling.spiders import Spider, Request, Response
|
| 182 |
+
|
| 183 |
+
class QuotesSpider(Spider):
|
| 184 |
+
name = "quotes"
|
| 185 |
+
start_urls = ["https://quotes.toscrape.com/"]
|
| 186 |
+
concurrent_requests = 10
|
| 187 |
+
|
| 188 |
+
async def parse(self, response: Response):
|
| 189 |
+
for quote in response.css('.quote'):
|
| 190 |
+
yield {
|
| 191 |
+
"text": quote.css('.text::text').get(),
|
| 192 |
+
"author": quote.css('.author::text').get(),
|
| 193 |
+
}
|
| 194 |
+
|
| 195 |
+
next_page = response.css('.next a')
|
| 196 |
+
if next_page:
|
| 197 |
+
yield response.follow(next_page[0].attrib['href'])
|
| 198 |
+
|
| 199 |
+
result = QuotesSpider().start()
|
| 200 |
+
print(f"Извлечено {len(result.items)} цитат")
|
| 201 |
+
result.items.to_json("quotes.json")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 202 |
```
|
| 203 |
+
Используйте несколько типов сессий в одном Spider:
|
| 204 |
+
```python
|
| 205 |
+
from scrapling.spiders import Spider, Request, Response
|
| 206 |
+
from scrapling.fetchers import FetcherSession, AsyncStealthySession
|
| 207 |
+
|
| 208 |
+
class MultiSessionSpider(Spider):
|
| 209 |
+
name = "multi"
|
| 210 |
+
start_urls = ["https://example.com/"]
|
| 211 |
+
|
| 212 |
+
def configure_sessions(self, manager):
|
| 213 |
+
manager.add("fast", FetcherSession(impersonate="chrome"))
|
| 214 |
+
manager.add("stealth", AsyncStealthySession(headless=True), lazy=True)
|
| 215 |
+
|
| 216 |
+
async def parse(self, response: Response):
|
| 217 |
+
for link in response.css('a::attr(href)').getall():
|
| 218 |
+
# Направляйте защищённые страницы через stealth-сессию
|
| 219 |
+
if "protected" in link:
|
| 220 |
+
yield Request(link, sid="stealth")
|
| 221 |
+
else:
|
| 222 |
+
yield Request(link, sid="fast", callback=self.parse) # явный callback
|
| 223 |
+
```
|
| 224 |
+
Приостанавливайте и возобновляйте длительные обходы с помощью Checkpoint'ов, запуская Spider следующим образом:
|
| 225 |
+
```python
|
| 226 |
+
QuotesSpider(crawldir="./crawl_data").start()
|
| 227 |
+
```
|
| 228 |
+
Нажмите Ctrl+C для мягкой остановки — прогресс сохраняется автоматически. Позже, когда вы снова запустите Spider, передайте тот же `crawldir`, и он продолжит с того места, где остановился.
|
| 229 |
+
|
| 230 |
+
### Продвинутый парсинг и навигация
|
| 231 |
+
```python
|
| 232 |
+
from scrapling.fetchers import Fetcher
|
| 233 |
+
|
| 234 |
+
# Богатый выбор элементов и навигация
|
| 235 |
+
page = Fetcher.get('https://quotes.toscrape.com/')
|
| 236 |
|
| 237 |
+
# Получение цитат различными методами выбора
|
| 238 |
+
quotes = page.css('.quote') # CSS-селектор
|
| 239 |
+
quotes = page.xpath('//div[@class="quote"]') # XPath
|
| 240 |
+
quotes = page.find_all('div', {'class': 'quote'}) # В стиле BeautifulSoup
|
| 241 |
+
# То же самое, что
|
| 242 |
+
quotes = page.find_all('div', class_='quote')
|
| 243 |
+
quotes = page.find_all(['div'], class_='quote')
|
| 244 |
+
quotes = page.find_all(class_='quote') # и так далее...
|
| 245 |
+
# Найти элемент по текстовому содержимому
|
| 246 |
+
quotes = page.find_by_text('quote', tag='div')
|
| 247 |
+
|
| 248 |
+
# Продвинутая навигация
|
| 249 |
+
quote_text = page.css('.quote')[0].css('.text::text').get()
|
| 250 |
+
quote_text = page.css('.quote').css('.text::text').getall() # Цепочка селекторов
|
| 251 |
+
first_quote = page.css('.quote')[0]
|
| 252 |
+
author = first_quote.next_sibling.css('.author::text')
|
| 253 |
+
parent_container = first_quote.parent
|
| 254 |
+
|
| 255 |
+
# Связи элементов и подобие
|
| 256 |
+
similar_elements = first_quote.find_similar()
|
| 257 |
+
below_elements = first_quote.below_elements()
|
| 258 |
+
```
|
| 259 |
+
Вы можете использовать парсер напрямую, если не хотите загружать сайты, как показано ниже:
|
| 260 |
```python
|
| 261 |
+
from scrapling.parser import Selector
|
| 262 |
+
|
| 263 |
+
page = Selector("<html>...</html>")
|
| 264 |
+
```
|
| 265 |
+
И он работает точно так же!
|
| 266 |
+
|
| 267 |
+
### Примеры async Session
|
| 268 |
+
```python
|
| 269 |
+
import asyncio
|
| 270 |
+
from scrapling.fetchers import FetcherSession, AsyncStealthySession, AsyncDynamicSession
|
| 271 |
+
|
| 272 |
+
async with FetcherSession(http3=True) as session: # `FetcherSession` контекстно-осведомлён и может работать как в sync, так и в async-режимах
|
| 273 |
+
page1 = session.get('https://quotes.toscrape.com/')
|
| 274 |
page2 = session.get('https://quotes.toscrape.com/', impersonate='firefox135')
|
| 275 |
|
| 276 |
+
# Использование async-сессии
|
| 277 |
async with AsyncStealthySession(max_pages=2) as session:
|
| 278 |
tasks = []
|
| 279 |
urls = ['https://example.com/page1', 'https://example.com/page2']
|
| 280 |
+
|
| 281 |
for url in urls:
|
| 282 |
task = session.fetch(url)
|
| 283 |
tasks.append(task)
|
| 284 |
+
|
| 285 |
+
print(session.get_pool_stats()) # Опционально — статус пула вкладок браузера (занят/свободен/ошибка)
|
| 286 |
results = await asyncio.gather(*tasks)
|
| 287 |
print(session.get_pool_stats())
|
| 288 |
```
|
| 289 |
|
| 290 |
+
## CLI и интерактивная Shell
|
| 291 |
|
| 292 |
+
Scrapling включает мощный интерфейс командной строки:
|
| 293 |
|
| 294 |
[](https://asciinema.org/a/736339)
|
| 295 |
|
| 296 |
+
Запустить интерактивную Web Scraping Shell
|
| 297 |
```bash
|
| 298 |
scrapling shell
|
| 299 |
```
|
| 300 |
+
Извлечь страницы в файл напрямую без программирования (по умолчанию извлекает содержимое внутри тега `body`). Если выходной файл заканчивается на `.txt`, будет извлечено текстовое содержимое цели. Если заканчивается на `.md`, эт�� будет Markdown-представление HTML-содержимого; если заканчивается на `.html`, это будет само HTML-содержимое.
|
| 301 |
```bash
|
| 302 |
scrapling extract get 'https://example.com' content.md
|
| 303 |
scrapling extract get 'https://example.com' content.txt --css-selector '#fromSkipToProducts' --impersonate 'chrome' # Все элементы, соответствующие CSS-селектору '#fromSkipToProducts'
|
|
|
|
| 306 |
```
|
| 307 |
|
| 308 |
> [!NOTE]
|
| 309 |
+
> Есть множество дополнительных возможностей, но мы хотим сохранить эту страницу краткой, включая MCP-сервер и интерактивную Web Scraping Shell. Ознакомьтесь с полной документацией [здесь](https://scrapling.readthedocs.io/en/latest/)
|
| 310 |
|
| 311 |
## Тесты производительности
|
| 312 |
|
| 313 |
+
Scrapling не только мощный — он ещё и невероятно быстрый. Следующие тесты производительности сравнивают парсер Scrapling с последними версиями других популярных библиотек.
|
| 314 |
|
| 315 |
### Тест скорости извлечения текста (5000 вложенных элементов)
|
| 316 |
|
| 317 |
+
| # | Библиотека | Время (мс) | vs Scrapling |
|
| 318 |
|---|:-----------------:|:----------:|:------------:|
|
| 319 |
+
| 1 | Scrapling | 2.02 | 1.0x |
|
| 320 |
+
| 2 | Parsel/Scrapy | 2.04 | 1.01 |
|
| 321 |
+
| 3 | Raw Lxml | 2.54 | 1.257 |
|
| 322 |
+
| 4 | PyQuery | 24.17 | ~12x |
|
| 323 |
+
| 5 | Selectolax | 82.63 | ~41x |
|
| 324 |
+
| 6 | MechanicalSoup | 1549.71 | ~767.1x |
|
| 325 |
+
| 7 | BS4 with Lxml | 1584.31 | ~784.3x |
|
| 326 |
+
| 8 | BS4 with html5lib | 3391.91 | ~1679.1x |
|
| 327 |
|
| 328 |
|
| 329 |
### Производительность подобия элементов и текстового поиска
|
|
|
|
| 332 |
|
| 333 |
| Библиотека | Время (мс) | vs Scrapling |
|
| 334 |
|-------------|:----------:|:------------:|
|
| 335 |
+
| Scrapling | 2.39 | 1.0x |
|
| 336 |
+
| AutoScraper | 12.45 | 5.209x |
|
| 337 |
|
| 338 |
|
| 339 |
> Все тесты производительности представляют собой средние значения более 100 запусков. См. [benchmarks.py](https://github.com/D4Vinci/Scrapling/blob/main/benchmarks.py) для методологии.
|
|
|
|
| 346 |
pip install scrapling
|
| 347 |
```
|
| 348 |
|
| 349 |
+
Эта установка включает только движок парсера и его зависимости, без каких-либо Fetcher'ов или зависимостей командной строки.
|
| 350 |
|
| 351 |
### Опциональные зависимости
|
| 352 |
|
| 353 |
+
1. Если вы собираетесь использовать какие-либо из дополнительных возможностей ниже, Fetcher'ы или их классы, вам необходимо установить зависимости Fetcher'ов и браузеров следующим образом:
|
| 354 |
```bash
|
| 355 |
pip install "scrapling[fetchers]"
|
| 356 |
+
|
| 357 |
scrapling install
|
| 358 |
```
|
| 359 |
|
| 360 |
+
Это загрузит все браузеры вместе с их системными зависимостями и зависимостями для манипуляции fingerprint'ами.
|
| 361 |
|
| 362 |
+
2. Дополнительные возможности:
|
| 363 |
- Установить функцию MCP-сервера:
|
| 364 |
```bash
|
| 365 |
pip install "scrapling[ai]"
|
| 366 |
```
|
| 367 |
+
- Установить функции Shell (Web Scraping Shell и команда `extract`):
|
| 368 |
```bash
|
| 369 |
pip install "scrapling[shell]"
|
| 370 |
```
|
| 371 |
+
- Установить всё:
|
| 372 |
```bash
|
| 373 |
pip install "scrapling[all]"
|
| 374 |
```
|
| 375 |
+
Помните, что вам нужно установить зависимости браузеров с помощью `scrapling install` после любого из этих дополнений (если вы ещё этого не сделали)
|
| 376 |
|
| 377 |
### Docker
|
| 378 |
Вы также можете установить Docker-образ со всеми дополнениями и браузерами с помощью следующей команды из DockerHub:
|
|
|
|
| 383 |
```bash
|
| 384 |
docker pull ghcr.io/d4vinci/scrapling:latest
|
| 385 |
```
|
| 386 |
+
Этот образ автоматически создаётся и публикуется с помощью GitHub Actions и основной ветки репозитория.
|
| 387 |
|
| 388 |
+
## Участие в разработке
|
| 389 |
|
| 390 |
+
Мы приветствуем участие! Пожалуйста, прочитайте наши [руководства по участию в разработке](https://github.com/D4Vinci/Scrapling/blob/main/CONTRIBUTING.md) перед началом работы.
|
| 391 |
|
| 392 |
## Отказ от ответственности
|
| 393 |
|
|
|
|
| 403 |
Этот проект включает код, адаптированный из:
|
| 404 |
- Parsel (лицензия BSD) — Используется для подмодуля [translator](https://github.com/D4Vinci/Scrapling/blob/main/scrapling/core/translator.py)
|
| 405 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 406 |
---
|
| 407 |
+
<div align="center"><small>Разработано и создано с ❤️ Карим Шоаир.</small></div><br>
|