docpull 1.0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- docpull-1.0.1/LICENSE +21 -0
- docpull-1.0.1/PKG-INFO +440 -0
- docpull-1.0.1/README.md +373 -0
- docpull-1.0.1/docpull/__init__.py +29 -0
- docpull-1.0.1/docpull/__main__.py +6 -0
- docpull-1.0.1/docpull/cli.py +440 -0
- docpull-1.0.1/docpull/config.py +199 -0
- docpull-1.0.1/docpull/fetchers/__init__.py +23 -0
- docpull-1.0.1/docpull/fetchers/async_fetcher.py +322 -0
- docpull-1.0.1/docpull/fetchers/base.py +450 -0
- docpull-1.0.1/docpull/fetchers/bun.py +59 -0
- docpull-1.0.1/docpull/fetchers/d3.py +211 -0
- docpull-1.0.1/docpull/fetchers/generic.py +255 -0
- docpull-1.0.1/docpull/fetchers/generic_async.py +282 -0
- docpull-1.0.1/docpull/fetchers/nextjs.py +50 -0
- docpull-1.0.1/docpull/fetchers/parallel_base.py +93 -0
- docpull-1.0.1/docpull/fetchers/plaid.py +92 -0
- docpull-1.0.1/docpull/fetchers/react.py +59 -0
- docpull-1.0.1/docpull/fetchers/stripe.py +60 -0
- docpull-1.0.1/docpull/fetchers/tailwind.py +59 -0
- docpull-1.0.1/docpull/fetchers/turborepo.py +57 -0
- docpull-1.0.1/docpull/profiles/__init__.py +70 -0
- docpull-1.0.1/docpull/profiles/base.py +64 -0
- docpull-1.0.1/docpull/profiles/bun.py +14 -0
- docpull-1.0.1/docpull/profiles/d3.py +17 -0
- docpull-1.0.1/docpull/profiles/nextjs.py +15 -0
- docpull-1.0.1/docpull/profiles/plaid.py +16 -0
- docpull-1.0.1/docpull/profiles/react.py +14 -0
- docpull-1.0.1/docpull/profiles/stripe.py +14 -0
- docpull-1.0.1/docpull/profiles/tailwind.py +14 -0
- docpull-1.0.1/docpull/profiles/turborepo.py +14 -0
- docpull-1.0.1/docpull/py.typed +0 -0
- docpull-1.0.1/docpull/utils/__init__.py +6 -0
- docpull-1.0.1/docpull/utils/file_utils.py +97 -0
- docpull-1.0.1/docpull/utils/logging_config.py +54 -0
- docpull-1.0.1/docpull.egg-info/PKG-INFO +440 -0
- docpull-1.0.1/docpull.egg-info/SOURCES.txt +44 -0
- docpull-1.0.1/docpull.egg-info/dependency_links.txt +1 -0
- docpull-1.0.1/docpull.egg-info/entry_points.txt +2 -0
- docpull-1.0.1/docpull.egg-info/requires.txt +29 -0
- docpull-1.0.1/docpull.egg-info/top_level.txt +1 -0
- docpull-1.0.1/pyproject.toml +162 -0
- docpull-1.0.1/setup.cfg +4 -0
- docpull-1.0.1/tests/test_async_fetcher.py +147 -0
- docpull-1.0.1/tests/test_config.py +46 -0
- docpull-1.0.1/tests/test_fetchers.py +57 -0
docpull-1.0.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Raintree Technology
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
docpull-1.0.1/PKG-INFO
ADDED
|
@@ -0,0 +1,440 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: docpull
|
|
3
|
+
Version: 1.0.1
|
|
4
|
+
Summary: Pull documentation from the web and convert to clean markdown
|
|
5
|
+
Author-email: Zachary Roth <support@raintree.technology>
|
|
6
|
+
Maintainer-email: Raintree Technology <support@raintree.technology>
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
Project-URL: Homepage, https://github.com/raintree-technology/docpull
|
|
9
|
+
Project-URL: Documentation, https://github.com/raintree-technology/docpull#readme
|
|
10
|
+
Project-URL: Repository, https://github.com/raintree-technology/docpull
|
|
11
|
+
Project-URL: Source Code, https://github.com/raintree-technology/docpull
|
|
12
|
+
Project-URL: Bug Tracker, https://github.com/raintree-technology/docpull/issues
|
|
13
|
+
Project-URL: Changelog, https://github.com/raintree-technology/docpull/blob/main/CHANGELOG.md
|
|
14
|
+
Keywords: python,markdown,documentation,web-scraping,developer-tools,claude,ai-training-data
|
|
15
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
16
|
+
Classifier: Intended Audience :: Developers
|
|
17
|
+
Classifier: Intended Audience :: Information Technology
|
|
18
|
+
Classifier: Intended Audience :: Science/Research
|
|
19
|
+
Classifier: Intended Audience :: Education
|
|
20
|
+
Classifier: Environment :: Console
|
|
21
|
+
Classifier: Topic :: Documentation
|
|
22
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: Indexing/Search
|
|
23
|
+
Classifier: Topic :: Software Development :: Documentation
|
|
24
|
+
Classifier: Topic :: Text Processing :: Markup :: HTML
|
|
25
|
+
Classifier: Topic :: Text Processing :: Markup :: Markdown
|
|
26
|
+
Classifier: Topic :: Utilities
|
|
27
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
28
|
+
Classifier: Natural Language :: English
|
|
29
|
+
Classifier: Operating System :: OS Independent
|
|
30
|
+
Classifier: Programming Language :: Python :: 3
|
|
31
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
32
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
33
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
34
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
35
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
36
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
37
|
+
Classifier: Typing :: Typed
|
|
38
|
+
Requires-Python: >=3.9
|
|
39
|
+
Description-Content-Type: text/markdown
|
|
40
|
+
License-File: LICENSE
|
|
41
|
+
Requires-Dist: requests>=2.31.0
|
|
42
|
+
Requires-Dist: beautifulsoup4>=4.12.0
|
|
43
|
+
Requires-Dist: html2text>=2020.1.16
|
|
44
|
+
Requires-Dist: defusedxml>=0.7.1
|
|
45
|
+
Requires-Dist: aiohttp>=3.9.0
|
|
46
|
+
Requires-Dist: rich>=13.0.0
|
|
47
|
+
Provides-Extra: yaml
|
|
48
|
+
Requires-Dist: pyyaml>=6.0; extra == "yaml"
|
|
49
|
+
Provides-Extra: js
|
|
50
|
+
Requires-Dist: playwright>=1.40.0; extra == "js"
|
|
51
|
+
Provides-Extra: all
|
|
52
|
+
Requires-Dist: pyyaml>=6.0; extra == "all"
|
|
53
|
+
Requires-Dist: playwright>=1.40.0; extra == "all"
|
|
54
|
+
Provides-Extra: dev
|
|
55
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
56
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
57
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
|
58
|
+
Requires-Dist: black>=23.0.0; extra == "dev"
|
|
59
|
+
Requires-Dist: mypy>=1.0.0; extra == "dev"
|
|
60
|
+
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
61
|
+
Requires-Dist: bandit>=1.7.0; extra == "dev"
|
|
62
|
+
Requires-Dist: pip-audit>=2.0.0; extra == "dev"
|
|
63
|
+
Requires-Dist: types-requests>=2.31.0; extra == "dev"
|
|
64
|
+
Requires-Dist: types-beautifulsoup4>=4.12.0; extra == "dev"
|
|
65
|
+
Requires-Dist: types-aiohttp>=3.9.0; extra == "dev"
|
|
66
|
+
Dynamic: license-file
|
|
67
|
+
|
|
68
|
+
# docpull
|
|
69
|
+
|
|
70
|
+
**Pull documentation from ANY website and convert to clean, AI-ready markdown.**
|
|
71
|
+
|
|
72
|
+
[](https://www.python.org/downloads/)
|
|
73
|
+
[](https://badge.fury.io/py/docpull)
|
|
74
|
+
[](https://github.com/raintree-technology/docpull/blob/main/LICENSE)
|
|
75
|
+
[](https://github.com/psf/black)
|
|
76
|
+
[](http://mypy-lang.org/)
|
|
77
|
+
[](https://github.com/PyCQA/bandit)
|
|
78
|
+
|
|
79
|
+
## Why docpull?
|
|
80
|
+
|
|
81
|
+
Unlike wget or httrack that dump messy HTML, **docpull extracts clean markdown** perfect for:
|
|
82
|
+
- Training AI models / RAG systems
|
|
83
|
+
- Building knowledge bases
|
|
84
|
+
- Creating searchable documentation archives
|
|
85
|
+
- Offline documentation reading
|
|
86
|
+
|
|
87
|
+
**Production-ready**: Full type safety (mypy), security scanning (Bandit), zero linting issues (Ruff), comprehensive test coverage, and no known vulnerabilities.
|
|
88
|
+
|
|
89
|
+
## Features
|
|
90
|
+
|
|
91
|
+
- **Universal**: Scrape ANY documentation site - not limited to predefined sources
|
|
92
|
+
- **Smart extraction**: Auto-detects main content, removes navigation/ads
|
|
93
|
+
- **Blazing fast**: Async/parallel fetching (10x faster than sync)
|
|
94
|
+
- **JavaScript support**: Handles JS-heavy sites with Playwright
|
|
95
|
+
- **Progress bars**: Beautiful real-time progress with Rich
|
|
96
|
+
- **Sitemap support**: Auto-discovers pages via sitemap.xml
|
|
97
|
+
- **Link crawling**: Optionally follows links to discover all pages
|
|
98
|
+
- **Secure**: Rate limiting, content validation, timeout controls
|
|
99
|
+
- **Clean output**: Markdown with YAML frontmatter
|
|
100
|
+
- **Configurable**: Control depth, page limits, concurrency
|
|
101
|
+
- **Resumable**: Skip already-fetched files
|
|
102
|
+
|
|
103
|
+
## Quick Start
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
# Install
|
|
107
|
+
pip install docpull
|
|
108
|
+
|
|
109
|
+
# Scrape ANY documentation site
|
|
110
|
+
docpull https://aptos.dev
|
|
111
|
+
docpull https://docs.anthropic.com
|
|
112
|
+
docpull https://go.dev/doc
|
|
113
|
+
|
|
114
|
+
# Use optimized profiles for popular sites
|
|
115
|
+
docpull stripe
|
|
116
|
+
docpull nextjs react
|
|
117
|
+
|
|
118
|
+
# Control scraping behavior
|
|
119
|
+
docpull https://newsite.com/docs --max-pages 100 --max-concurrent 20
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Installation
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
# Basic installation
|
|
126
|
+
pip install docpull
|
|
127
|
+
|
|
128
|
+
# With YAML config support
|
|
129
|
+
pip install docpull[yaml]
|
|
130
|
+
|
|
131
|
+
# With JavaScript rendering (for JS-heavy sites)
|
|
132
|
+
pip install docpull[js]
|
|
133
|
+
python -m playwright install chromium
|
|
134
|
+
|
|
135
|
+
# Everything
|
|
136
|
+
pip install docpull[all]
|
|
137
|
+
python -m playwright install chromium
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## Usage
|
|
141
|
+
|
|
142
|
+
### Scrape Any URL
|
|
143
|
+
|
|
144
|
+
The primary way to use docpull is by providing any documentation URL:
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
# Single site
|
|
148
|
+
docpull https://aptos.dev
|
|
149
|
+
|
|
150
|
+
# Multiple sites
|
|
151
|
+
docpull https://aptos.dev https://docs.soliditylang.org
|
|
152
|
+
|
|
153
|
+
# Control crawling
|
|
154
|
+
docpull https://docs.example.com \
|
|
155
|
+
--max-pages 200 \
|
|
156
|
+
--max-depth 4 \
|
|
157
|
+
--rate-limit 1.0
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### Use Optimized Profiles
|
|
161
|
+
|
|
162
|
+
For popular documentation sites, use shortcut names for optimized scraping:
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
# Single profile
|
|
166
|
+
docpull stripe
|
|
167
|
+
|
|
168
|
+
# Multiple profiles
|
|
169
|
+
docpull stripe plaid nextjs
|
|
170
|
+
|
|
171
|
+
# Mix profiles and URLs
|
|
172
|
+
docpull stripe https://newsite.com/docs
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### JavaScript Rendering
|
|
176
|
+
|
|
177
|
+
For sites that require JavaScript to render content:
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
# Enable JS rendering with Playwright
|
|
181
|
+
docpull https://js-heavy-site.com --js
|
|
182
|
+
|
|
183
|
+
# Combine with other options
|
|
184
|
+
docpull https://site.com --js --max-pages 50 --max-concurrent 5
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
**Note:** JS rendering is slower but handles modern SPAs and dynamically-loaded content.
|
|
188
|
+
|
|
189
|
+
### Available Profiles
|
|
190
|
+
|
|
191
|
+
| Profile | Site | Optimizations |
|
|
192
|
+
|---------|------|---------------|
|
|
193
|
+
| `stripe` | docs.stripe.com | Filters changelog, focused on API docs |
|
|
194
|
+
| `nextjs` | nextjs.org | Excludes blog/showcase, docs only |
|
|
195
|
+
| `react` | react.dev | Learn & reference sections only |
|
|
196
|
+
| `plaid` | plaid.com | API + guides, excludes marketing |
|
|
197
|
+
| `tailwind` | tailwindcss.com | Documentation only |
|
|
198
|
+
| `bun` | bun.sh | Runtime documentation |
|
|
199
|
+
| `d3` | d3js.org | Data visualization docs |
|
|
200
|
+
| `turborepo` | turbo.build | Monorepo tooling docs |
|
|
201
|
+
|
|
202
|
+
### Python API
|
|
203
|
+
|
|
204
|
+
```python
|
|
205
|
+
from docpull import GenericAsyncFetcher
|
|
206
|
+
|
|
207
|
+
# Scrape any URL (async/parallel)
|
|
208
|
+
fetcher = GenericAsyncFetcher(
|
|
209
|
+
url_or_profile="https://aptos.dev",
|
|
210
|
+
output_dir="./docs",
|
|
211
|
+
max_pages=100,
|
|
212
|
+
max_concurrent=20,
|
|
213
|
+
use_js=False, # Set to True for JS rendering
|
|
214
|
+
)
|
|
215
|
+
fetcher.fetch()
|
|
216
|
+
|
|
217
|
+
# Or use a profile
|
|
218
|
+
fetcher = GenericAsyncFetcher(
|
|
219
|
+
url_or_profile="stripe",
|
|
220
|
+
output_dir="./docs",
|
|
221
|
+
)
|
|
222
|
+
fetcher.fetch()
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### Advanced Options
|
|
226
|
+
|
|
227
|
+
```bash
|
|
228
|
+
# Limit pages and depth
|
|
229
|
+
docpull https://docs.example.com --max-pages 50 --max-depth 2
|
|
230
|
+
|
|
231
|
+
# Control concurrent requests (default: 10)
|
|
232
|
+
docpull https://site.com --max-concurrent 20
|
|
233
|
+
|
|
234
|
+
# Enable JavaScript rendering
|
|
235
|
+
docpull https://site.com --js
|
|
236
|
+
|
|
237
|
+
# Custom output directory
|
|
238
|
+
docpull stripe --output-dir ./my-docs
|
|
239
|
+
|
|
240
|
+
# Adjust rate limiting
|
|
241
|
+
docpull https://site.com --rate-limit 2.0
|
|
242
|
+
|
|
243
|
+
# Re-fetch existing files
|
|
244
|
+
docpull stripe --no-skip-existing
|
|
245
|
+
|
|
246
|
+
# Verbose logging
|
|
247
|
+
docpull https://site.com --verbose
|
|
248
|
+
|
|
249
|
+
# Disable progress bars
|
|
250
|
+
docpull https://site.com --no-progress
|
|
251
|
+
|
|
252
|
+
# Dry run (see what would be fetched)
|
|
253
|
+
docpull https://site.com --dry-run
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
## Performance
|
|
257
|
+
|
|
258
|
+
**Async/Parallel Fetching** makes docpull **10x faster** than traditional sync scrapers:
|
|
259
|
+
|
|
260
|
+
| Pages | Sync (old) | Async (new) | Speedup |
|
|
261
|
+
|-------|-----------|-------------|---------|
|
|
262
|
+
| 5 | ~5.0s | ~1.8s | 2.8x faster |
|
|
263
|
+
| 50 | ~50s | ~6s | 8.3x faster |
|
|
264
|
+
| 500 | ~500s | ~45s | 11x faster |
|
|
265
|
+
|
|
266
|
+
With `--max-concurrent 20`, even faster for large sites!
|
|
267
|
+
|
|
268
|
+
## Output Format
|
|
269
|
+
|
|
270
|
+
Each page is saved as markdown with YAML frontmatter:
|
|
271
|
+
|
|
272
|
+
```markdown
|
|
273
|
+
---
|
|
274
|
+
url: https://stripe.com/docs/payments
|
|
275
|
+
fetched: 2025-11-13
|
|
276
|
+
---
|
|
277
|
+
|
|
278
|
+
# Payment Intents
|
|
279
|
+
|
|
280
|
+
Your clean documentation content here...
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
Files are organized by URL structure:
|
|
284
|
+
|
|
285
|
+
```
|
|
286
|
+
docs/
|
|
287
|
+
├── stripe/
|
|
288
|
+
│ ├── api/
|
|
289
|
+
│ │ ├── charges.md
|
|
290
|
+
│ │ └── customers.md
|
|
291
|
+
│ └── payments/
|
|
292
|
+
│ └── payment-intents.md
|
|
293
|
+
└── aptos_dev/
|
|
294
|
+
├── guides/
|
|
295
|
+
│ └── getting-started.md
|
|
296
|
+
└── reference/
|
|
297
|
+
└── api.md
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
## How It Works
|
|
301
|
+
|
|
302
|
+
1. **Discovery**: Tries sitemap.xml first, falls back to link crawling
|
|
303
|
+
2. **Filtering**: Applies URL patterns to focus on documentation
|
|
304
|
+
3. **Extraction**: Removes nav/footer/ads, extracts main content
|
|
305
|
+
4. **Conversion**: Converts HTML to clean markdown
|
|
306
|
+
5. **Organization**: Saves with structure that mirrors the site
|
|
307
|
+
6. **Async Magic**: Fetches multiple pages concurrently with rate limiting
|
|
308
|
+
|
|
309
|
+
## Configuration File
|
|
310
|
+
|
|
311
|
+
Create `config.yaml` for complex setups:
|
|
312
|
+
|
|
313
|
+
```yaml
|
|
314
|
+
output_dir: ./docs
|
|
315
|
+
rate_limit: 0.5
|
|
316
|
+
skip_existing: true
|
|
317
|
+
log_level: INFO
|
|
318
|
+
|
|
319
|
+
sources:
|
|
320
|
+
- stripe
|
|
321
|
+
- nextjs
|
|
322
|
+
- react
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
Run with:
|
|
326
|
+
```bash
|
|
327
|
+
docpull --config config.yaml
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
## Creating Custom Profiles
|
|
331
|
+
|
|
332
|
+
You can create optimized profiles for your frequently-scraped sites:
|
|
333
|
+
|
|
334
|
+
```python
|
|
335
|
+
from docpull.profiles.base import SiteProfile
|
|
336
|
+
|
|
337
|
+
MY_PROFILE = SiteProfile(
|
|
338
|
+
name="mysite",
|
|
339
|
+
domains={"docs.mysite.com"},
|
|
340
|
+
sitemap_url="https://docs.mysite.com/sitemap.xml",
|
|
341
|
+
base_url="https://docs.mysite.com/",
|
|
342
|
+
include_patterns=["/docs/", "/api/"],
|
|
343
|
+
exclude_patterns=["/blog/"],
|
|
344
|
+
output_subdir="mysite",
|
|
345
|
+
rate_limit=0.5,
|
|
346
|
+
)
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
## Security
|
|
350
|
+
|
|
351
|
+
docpull is designed with security in mind:
|
|
352
|
+
|
|
353
|
+
- **HTTPS-only** by default
|
|
354
|
+
- **Private IP blocking** (no localhost, 192.168.x.x, etc.)
|
|
355
|
+
- **Content size limits** (50MB max per page)
|
|
356
|
+
- **Timeout controls** (30s per request)
|
|
357
|
+
- **Rate limiting** (async-safe, prevents DoS)
|
|
358
|
+
- **Concurrent connection limits** (prevents overwhelming servers)
|
|
359
|
+
- **Content-type validation** (only fetches HTML/XML)
|
|
360
|
+
- **Playwright sandboxing** (when using --js)
|
|
361
|
+
|
|
362
|
+
See [SECURITY.md](SECURITY.md) for detailed security information.
|
|
363
|
+
|
|
364
|
+
## Comparison with Alternatives
|
|
365
|
+
|
|
366
|
+
| Tool | Output | Works on any site? | Clean extraction? | Speed | JS Support |
|
|
367
|
+
|------|--------|-------------------|-------------------|-------|------------|
|
|
368
|
+
| **docpull** | Clean markdown | Yes | Yes | Fast (async) | Optional |
|
|
369
|
+
| wget | Raw HTML | Yes | No | Slow (sync) | No |
|
|
370
|
+
| httrack | Raw HTML | Yes | No | Slow (sync) | No |
|
|
371
|
+
| Site-specific | Varies | No | Varies | Varies | No |
|
|
372
|
+
|
|
373
|
+
## Troubleshooting
|
|
374
|
+
|
|
375
|
+
### Site requires JavaScript
|
|
376
|
+
|
|
377
|
+
```bash
|
|
378
|
+
# Install Playwright support
|
|
379
|
+
pip install docpull[js]
|
|
380
|
+
python -m playwright install chromium
|
|
381
|
+
|
|
382
|
+
# Use --js flag
|
|
383
|
+
docpull https://site.com --js
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
### Too slow / rate limited
|
|
387
|
+
|
|
388
|
+
```bash
|
|
389
|
+
# Reduce concurrent requests
|
|
390
|
+
docpull https://site.com --max-concurrent 5 --rate-limit 2.0
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
### Memory issues on large sites
|
|
394
|
+
|
|
395
|
+
```bash
|
|
396
|
+
# Limit pages fetched
|
|
397
|
+
docpull https://site.com --max-pages 1000
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
## Contributing
|
|
401
|
+
|
|
402
|
+
Contributions welcome! To add:
|
|
403
|
+
- **New site profiles**: Create a profile in `docpull/profiles/`
|
|
404
|
+
- **Better extraction**: Improve content detection in `fetchers/base.py`
|
|
405
|
+
- **Performance improvements**: Optimize async fetching
|
|
406
|
+
- **Bug reports**: Use the [issue tracker](https://github.com/raintree-technology/docpull/issues)
|
|
407
|
+
|
|
408
|
+
### Development Setup
|
|
409
|
+
|
|
410
|
+
```bash
|
|
411
|
+
# Clone and install
|
|
412
|
+
git clone https://github.com/raintree-technology/docpull
|
|
413
|
+
cd docpull
|
|
414
|
+
pip install -e ".[dev]"
|
|
415
|
+
|
|
416
|
+
# Run all quality checks (as per CI)
|
|
417
|
+
black --check . # Code formatting
|
|
418
|
+
ruff check . # Linting
|
|
419
|
+
mypy docpull # Type checking
|
|
420
|
+
bandit -r docpull # Security scanning
|
|
421
|
+
pip-audit # Dependency vulnerabilities
|
|
422
|
+
pytest --cov=docpull -v # Tests with coverage
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
All PRs must pass these checks before merging.
|
|
426
|
+
|
|
427
|
+
## Documentation
|
|
428
|
+
|
|
429
|
+
- [Changelog](CHANGELOG.md)
|
|
430
|
+
- [Security Policy](SECURITY.md)
|
|
431
|
+
|
|
432
|
+
## License
|
|
433
|
+
|
|
434
|
+
MIT License - see [LICENSE](LICENSE) file for details
|
|
435
|
+
|
|
436
|
+
## Links
|
|
437
|
+
|
|
438
|
+
- [PyPI](https://pypi.org/project/docpull/)
|
|
439
|
+
- [GitHub](https://github.com/raintree-technology/docpull)
|
|
440
|
+
- [Issues](https://github.com/raintree-technology/docpull/issues)
|