headless-driver 0.2.0__tar.gz → 0.2.2__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.
- headless_driver-0.2.2/PKG-INFO +227 -0
- headless_driver-0.2.2/README.md +183 -0
- headless_driver-0.2.2/headless/__init__.py +23 -0
- headless_driver-0.2.2/headless/cli.py +357 -0
- {headless_driver-0.2.0 → headless_driver-0.2.2}/headless/core.py +131 -115
- {headless_driver-0.2.0 → headless_driver-0.2.2}/headless/manager.py +32 -31
- headless_driver-0.2.2/headless/scraper.py +471 -0
- headless_driver-0.2.2/headless/ui.py +250 -0
- headless_driver-0.2.2/headless_driver.egg-info/PKG-INFO +227 -0
- {headless_driver-0.2.0 → headless_driver-0.2.2}/headless_driver.egg-info/SOURCES.txt +4 -0
- headless_driver-0.2.2/headless_driver.egg-info/entry_points.txt +2 -0
- {headless_driver-0.2.0 → headless_driver-0.2.2}/headless_driver.egg-info/requires.txt +5 -0
- headless_driver-0.2.2/pyproject.toml +75 -0
- headless_driver-0.2.2/tests/test_cli.py +367 -0
- headless_driver-0.2.2/tests/test_headless.py +490 -0
- headless_driver-0.2.0/PKG-INFO +0 -237
- headless_driver-0.2.0/README.md +0 -206
- headless_driver-0.2.0/headless/__init__.py +0 -12
- headless_driver-0.2.0/headless/scraper.py +0 -313
- headless_driver-0.2.0/headless_driver.egg-info/PKG-INFO +0 -237
- headless_driver-0.2.0/pyproject.toml +0 -46
- headless_driver-0.2.0/tests/test_headless.py +0 -238
- {headless_driver-0.2.0 → headless_driver-0.2.2}/LICENSE +0 -0
- {headless_driver-0.2.0 → headless_driver-0.2.2}/headless_driver.egg-info/dependency_links.txt +0 -0
- {headless_driver-0.2.0 → headless_driver-0.2.2}/headless_driver.egg-info/top_level.txt +0 -0
- {headless_driver-0.2.0 → headless_driver-0.2.2}/setup.cfg +0 -0
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: headless-driver
|
|
3
|
+
Version: 0.2.2
|
|
4
|
+
Summary: Headless Chrome automation and multi-engine search scraper - DuckDuckGo, Bing, Google and more with automatic fallback, proxy, stealth, screenshots, PDF export and a CLI.
|
|
5
|
+
Author-email: nuhmanpk <nuhmanpk7@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/nuhmanpk/headless-driver
|
|
8
|
+
Project-URL: Documentation, https://github.com/nuhmanpk/headless-driver/blob/main/DOCS.md
|
|
9
|
+
Project-URL: Source, https://github.com/nuhmanpk/headless-driver
|
|
10
|
+
Project-URL: Issues, https://github.com/nuhmanpk/headless-driver/issues
|
|
11
|
+
Keywords: search-scraper,search-engine-scraper,search-scraping,serp,serp-scraper,search-results,web-scraping,scraper,scraping,duckduckgo,bing,google-search,mojeek,startpage,yandex,selenium,headless,headless-browser,headless-chrome,chrome,chromium,webdriver,chromedriver,browser-automation,automation,screenshot,pdf-export,stealth,anti-detection,proxy,crawler,cli
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Intended Audience :: Information Technology
|
|
16
|
+
Classifier: Intended Audience :: Science/Research
|
|
17
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
18
|
+
Classifier: Operating System :: OS Independent
|
|
19
|
+
Classifier: Programming Language :: Python :: 3
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
25
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
26
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
27
|
+
Classifier: Topic :: Software Development :: Testing
|
|
28
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: Browsers
|
|
29
|
+
Classifier: Topic :: Internet :: WWW/HTTP :: Indexing/Search
|
|
30
|
+
Classifier: Topic :: Text Processing :: Indexing
|
|
31
|
+
Classifier: Topic :: Utilities
|
|
32
|
+
Requires-Python: >=3.9
|
|
33
|
+
Description-Content-Type: text/markdown
|
|
34
|
+
License-File: LICENSE
|
|
35
|
+
Requires-Dist: selenium==4.35.0
|
|
36
|
+
Requires-Dist: webdriver-manager>=4.0.0
|
|
37
|
+
Requires-Dist: selenium-stealth>=1.0.6
|
|
38
|
+
Requires-Dist: geckodriver-autoinstaller>=0.1.0
|
|
39
|
+
Provides-Extra: dev
|
|
40
|
+
Requires-Dist: build>=1.0; extra == "dev"
|
|
41
|
+
Requires-Dist: twine>=5.0; extra == "dev"
|
|
42
|
+
Requires-Dist: trove-classifiers; extra == "dev"
|
|
43
|
+
Dynamic: license-file
|
|
44
|
+
|
|
45
|
+
<div align="center">
|
|
46
|
+
|
|
47
|
+
<img src="https://raw.githubusercontent.com/nuhmanpk/headless-driver/main/images/logo.png" alt="headless-driver" width="560" />
|
|
48
|
+
|
|
49
|
+
# headless-driver
|
|
50
|
+
|
|
51
|
+
**Headless Chrome automation and a multi-engine search scraper for Python.**<br/>
|
|
52
|
+
Proxy and stealth support, automatic driver installation, screenshots and PDF export,
|
|
53
|
+
multi-driver management, and a colourful CLI.
|
|
54
|
+
|
|
55
|
+
<a href="https://pypi.org/project/headless-driver/"><img alt="PyPI version" src="https://img.shields.io/pypi/v/headless-driver?style=flat-square&logo=pypi&logoColor=white&color=3775A9" /></a>
|
|
56
|
+
<a href="https://pypi.org/project/headless-driver/"><img alt="Python versions" src="https://img.shields.io/pypi/pyversions/headless-driver?style=flat-square&logo=python&logoColor=white" /></a>
|
|
57
|
+
<a href="https://pepy.tech/project/headless-driver"><img alt="Downloads" src="https://img.shields.io/pypi/dm/headless-driver?style=flat-square&logo=pypi&logoColor=white&color=orange" /></a>
|
|
58
|
+
<a href="https://pypi.org/project/headless-driver/"><img alt="Package status" src="https://img.shields.io/pypi/status/headless-driver?style=flat-square" /></a>
|
|
59
|
+
<a href="LICENSE"><img alt="License" src="https://img.shields.io/pypi/l/headless-driver?style=flat-square&color=yellow" /></a>
|
|
60
|
+
|
|
61
|
+
<a href="https://github.com/nuhmanpk/headless-driver/actions/workflows/tests.yml"><img alt="Tests" src="https://img.shields.io/github/actions/workflow/status/nuhmanpk/headless-driver/tests.yml?style=flat-square&logo=githubactions&logoColor=white&label=tests" /></a>
|
|
62
|
+
<img alt="Selenium" src="https://img.shields.io/badge/selenium-4.35-43B02A?style=flat-square&logo=selenium&logoColor=white" />
|
|
63
|
+
<img alt="Chrome headless" src="https://img.shields.io/badge/chrome-headless-4285F4?style=flat-square&logo=googlechrome&logoColor=white" />
|
|
64
|
+
<img alt="Platforms" src="https://img.shields.io/badge/platform-linux%20%7C%20macOS%20%7C%20windows-lightgrey?style=flat-square" />
|
|
65
|
+
|
|
66
|
+
<a href="https://github.com/nuhmanpk/headless-driver/stargazers"><img alt="Stars" src="https://img.shields.io/github/stars/nuhmanpk/headless-driver?style=flat-square&logo=github&logoColor=white&color=f5c518" /></a>
|
|
67
|
+
<a href="https://github.com/nuhmanpk/headless-driver/network/members"><img alt="Forks" src="https://img.shields.io/github/forks/nuhmanpk/headless-driver?style=flat-square&logo=github&logoColor=white" /></a>
|
|
68
|
+
<a href="https://github.com/nuhmanpk/headless-driver/issues"><img alt="Issues" src="https://img.shields.io/github/issues/nuhmanpk/headless-driver?style=flat-square&logo=github&logoColor=white" /></a>
|
|
69
|
+
<a href="https://github.com/nuhmanpk/headless-driver/commits/main"><img alt="Last commit" src="https://img.shields.io/github/last-commit/nuhmanpk/headless-driver?style=flat-square&logo=git&logoColor=white" /></a>
|
|
70
|
+
<a href="https://github.com/nuhmanpk/headless-driver/pulls"><img alt="PRs welcome" src="https://img.shields.io/badge/PRs-welcome-brightgreen?style=flat-square" /></a>
|
|
71
|
+
|
|
72
|
+
<a href="https://github.com/nuhmanpk"><img alt="Sponsor" src="https://img.shields.io/badge/sponsor-nuhmanpk-EA4AAA?style=flat-square&logo=githubsponsors&logoColor=white" /></a>
|
|
73
|
+
<a href="https://buymeacoffee.com/nuhmanpk"><img alt="Buy me a coffee" src="https://img.shields.io/badge/buy%20me%20a%20coffee-nuhmanpk-FFDD00?style=flat-square&logo=buymeacoffee&logoColor=black" /></a>
|
|
74
|
+
|
|
75
|
+
<br/>
|
|
76
|
+
|
|
77
|
+
[**Documentation**](DOCS.md) · [Quick start](#quick-start) · [CLI](#command-line) · [Engines](#search-engines) · [PyPI](https://pypi.org/project/headless-driver/) · [Issues](https://github.com/nuhmanpk/headless-driver/issues)
|
|
78
|
+
|
|
79
|
+
</div>
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Features
|
|
84
|
+
|
|
85
|
+
- Headless and windowed Chrome management, with temporary or persistent profiles
|
|
86
|
+
- HTTP and SOCKS proxy support, plus optional stealth mode
|
|
87
|
+
- Automatic ChromeDriver installation, and recovery when the installed driver does not match your Chrome
|
|
88
|
+
- Screenshot and PDF export via Chrome DevTools
|
|
89
|
+
- Download folder management
|
|
90
|
+
- Multi-driver manager for many isolated browser instances
|
|
91
|
+
- Search scraping across 8 engines, starting with DuckDuckGo's no-JavaScript endpoint and falling back automatically when one blocks you
|
|
92
|
+
- Bounded page-load timeouts, so a stalled engine fails over instead of hanging
|
|
93
|
+
- A `headless-driver` CLI with coloured output, `--json` for piping, and a `doctor` command that diagnoses your setup
|
|
94
|
+
|
|
95
|
+
## Install
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
pip install headless-driver
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Needs Python 3.9+ and an installed Chrome or Chromium. A matching ChromeDriver
|
|
102
|
+
is downloaded automatically when required.
|
|
103
|
+
|
|
104
|
+
On Debian/Ubuntu you can install a system browser and driver with:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
sudo apt update && sudo apt install -y chromium chromium-driver
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Quick start
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
from headless import Headless
|
|
114
|
+
|
|
115
|
+
with Headless() as driver:
|
|
116
|
+
driver.get("https://example.com")
|
|
117
|
+
print(driver.title)
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Search the web:
|
|
121
|
+
|
|
122
|
+
```python
|
|
123
|
+
from headless import AdvancedSearchScraper
|
|
124
|
+
|
|
125
|
+
with AdvancedSearchScraper(max_results=5) as scraper:
|
|
126
|
+
for item in scraper.search("python headless browser"):
|
|
127
|
+
print(item["title"], item["url"])
|
|
128
|
+
print("answered by", scraper.last_engine)
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Screenshot and PDF:
|
|
132
|
+
|
|
133
|
+
```python
|
|
134
|
+
from headless import ExtendedHeadless
|
|
135
|
+
|
|
136
|
+
hl = ExtendedHeadless(stealth=True)
|
|
137
|
+
driver = hl.get_driver()
|
|
138
|
+
driver.get("https://example.com")
|
|
139
|
+
|
|
140
|
+
hl.screenshot("example.png")
|
|
141
|
+
hl.save_pdf("example.pdf")
|
|
142
|
+
hl.quit()
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Command line
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
headless-driver search "python headless browser" -n 5
|
|
149
|
+
headless-driver search "selenium stealth" --json | jq -r '.results[].url'
|
|
150
|
+
headless-driver engines # engine list and fallback order
|
|
151
|
+
headless-driver doctor # check chrome, driver, connectivity
|
|
152
|
+
headless-driver shot https://example.com -o page.png --window 1280x720
|
|
153
|
+
headless-driver pdf https://example.com -o page.pdf
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
`doctor` is the quickest way to explain a failing run:
|
|
157
|
+
|
|
158
|
+
```
|
|
159
|
+
── browser ──────────────────────────────────────────────
|
|
160
|
+
✓ chrome Google Chrome 151.0.7922.140
|
|
161
|
+
✓ chromedriver ChromeDriver 148.0.7778.179
|
|
162
|
+
! version match chrome 151 vs driver 148 - a matching driver will be downloaded
|
|
163
|
+
── connectivity ─────────────────────────────────────────
|
|
164
|
+
✓ html.duckduckgo.com reachable
|
|
165
|
+
✓ www.bing.com reachable
|
|
166
|
+
── smoke test ───────────────────────────────────────────
|
|
167
|
+
✓ launch and navigate page title 'ok'
|
|
168
|
+
|
|
169
|
+
13 passed, 1 warning +++++++++++++~
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Colour switches off automatically when output is not a terminal, so piping
|
|
173
|
+
gives plain text. `NO_COLOR=1` or `--no-color` disables it; `FORCE_COLOR=1`
|
|
174
|
+
forces it on. Diagnostics go to stderr, keeping `--json` on stdout clean.
|
|
175
|
+
Exit status is `0` on success, `1` when nothing could be produced, `2` for a
|
|
176
|
+
usage error.
|
|
177
|
+
|
|
178
|
+
See [DOCS.md](DOCS.md#command-line) for every command and flag.
|
|
179
|
+
|
|
180
|
+
## Search engines
|
|
181
|
+
|
|
182
|
+
Searching starts at DuckDuckGo's no-JavaScript endpoint, which returns
|
|
183
|
+
server-rendered HTML and so is much faster than the JavaScript front end. If an
|
|
184
|
+
engine serves a bot check, returns nothing, or stalls, the next one is tried:
|
|
185
|
+
|
|
186
|
+
```
|
|
187
|
+
duckduckgo → duckduckgo_lite → bing → mojeek
|
|
188
|
+
→ duckduckgo_js → startpage → google → yandex
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
`search()` returns `[]` only once every engine has been tried.
|
|
192
|
+
|
|
193
|
+
```python
|
|
194
|
+
AdvancedSearchScraper(search_engine="bing") # start elsewhere
|
|
195
|
+
AdvancedSearchScraper(fallback=False) # single engine
|
|
196
|
+
AdvancedSearchScraper(fallback_engines=["bing", "mojeek"]) # custom order
|
|
197
|
+
scraper.search("query", engine="bing") # force, one-off
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Add your own engine with `register_engine()`. Full details, including the result
|
|
201
|
+
dict and redirect handling, are in
|
|
202
|
+
[DOCS.md](DOCS.md#search-engines).
|
|
203
|
+
|
|
204
|
+
## More
|
|
205
|
+
|
|
206
|
+
- [Full documentation](DOCS.md) — every class, argument and CLI flag
|
|
207
|
+
- [Python API](DOCS.md#python-api) — `Headless`, `ExtendedHeadless`, `MultiDriverManager`, `AdvancedSearchScraper`, `SearchScraper`
|
|
208
|
+
- [Timeouts](DOCS.md#timeouts) and [troubleshooting](DOCS.md#troubleshooting)
|
|
209
|
+
- [Running the tests](DOCS.md#running-the-tests)
|
|
210
|
+
|
|
211
|
+
## Support
|
|
212
|
+
|
|
213
|
+
If this project saves you time, you can support its development:
|
|
214
|
+
|
|
215
|
+
[](https://github.com/nuhmanpk)
|
|
216
|
+
[](https://buymeacoffee.com/nuhmanpk)
|
|
217
|
+
|
|
218
|
+
- Sponsor on GitHub — [github.com/nuhmanpk](https://github.com/nuhmanpk)
|
|
219
|
+
- Buy me a coffee — [buymeacoffee.com/nuhmanpk](https://buymeacoffee.com/nuhmanpk)
|
|
220
|
+
|
|
221
|
+
Starring the [repository](https://github.com/nuhmanpk/headless-driver) helps too.
|
|
222
|
+
|
|
223
|
+
## License
|
|
224
|
+
|
|
225
|
+
MIT — see [LICENSE](LICENSE).
|
|
226
|
+
|
|
227
|
+
[Happy coding 🚀](https://github.com/nuhmanpk/)
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
<img src="https://raw.githubusercontent.com/nuhmanpk/headless-driver/main/images/logo.png" alt="headless-driver" width="560" />
|
|
4
|
+
|
|
5
|
+
# headless-driver
|
|
6
|
+
|
|
7
|
+
**Headless Chrome automation and a multi-engine search scraper for Python.**<br/>
|
|
8
|
+
Proxy and stealth support, automatic driver installation, screenshots and PDF export,
|
|
9
|
+
multi-driver management, and a colourful CLI.
|
|
10
|
+
|
|
11
|
+
<a href="https://pypi.org/project/headless-driver/"><img alt="PyPI version" src="https://img.shields.io/pypi/v/headless-driver?style=flat-square&logo=pypi&logoColor=white&color=3775A9" /></a>
|
|
12
|
+
<a href="https://pypi.org/project/headless-driver/"><img alt="Python versions" src="https://img.shields.io/pypi/pyversions/headless-driver?style=flat-square&logo=python&logoColor=white" /></a>
|
|
13
|
+
<a href="https://pepy.tech/project/headless-driver"><img alt="Downloads" src="https://img.shields.io/pypi/dm/headless-driver?style=flat-square&logo=pypi&logoColor=white&color=orange" /></a>
|
|
14
|
+
<a href="https://pypi.org/project/headless-driver/"><img alt="Package status" src="https://img.shields.io/pypi/status/headless-driver?style=flat-square" /></a>
|
|
15
|
+
<a href="LICENSE"><img alt="License" src="https://img.shields.io/pypi/l/headless-driver?style=flat-square&color=yellow" /></a>
|
|
16
|
+
|
|
17
|
+
<a href="https://github.com/nuhmanpk/headless-driver/actions/workflows/tests.yml"><img alt="Tests" src="https://img.shields.io/github/actions/workflow/status/nuhmanpk/headless-driver/tests.yml?style=flat-square&logo=githubactions&logoColor=white&label=tests" /></a>
|
|
18
|
+
<img alt="Selenium" src="https://img.shields.io/badge/selenium-4.35-43B02A?style=flat-square&logo=selenium&logoColor=white" />
|
|
19
|
+
<img alt="Chrome headless" src="https://img.shields.io/badge/chrome-headless-4285F4?style=flat-square&logo=googlechrome&logoColor=white" />
|
|
20
|
+
<img alt="Platforms" src="https://img.shields.io/badge/platform-linux%20%7C%20macOS%20%7C%20windows-lightgrey?style=flat-square" />
|
|
21
|
+
|
|
22
|
+
<a href="https://github.com/nuhmanpk/headless-driver/stargazers"><img alt="Stars" src="https://img.shields.io/github/stars/nuhmanpk/headless-driver?style=flat-square&logo=github&logoColor=white&color=f5c518" /></a>
|
|
23
|
+
<a href="https://github.com/nuhmanpk/headless-driver/network/members"><img alt="Forks" src="https://img.shields.io/github/forks/nuhmanpk/headless-driver?style=flat-square&logo=github&logoColor=white" /></a>
|
|
24
|
+
<a href="https://github.com/nuhmanpk/headless-driver/issues"><img alt="Issues" src="https://img.shields.io/github/issues/nuhmanpk/headless-driver?style=flat-square&logo=github&logoColor=white" /></a>
|
|
25
|
+
<a href="https://github.com/nuhmanpk/headless-driver/commits/main"><img alt="Last commit" src="https://img.shields.io/github/last-commit/nuhmanpk/headless-driver?style=flat-square&logo=git&logoColor=white" /></a>
|
|
26
|
+
<a href="https://github.com/nuhmanpk/headless-driver/pulls"><img alt="PRs welcome" src="https://img.shields.io/badge/PRs-welcome-brightgreen?style=flat-square" /></a>
|
|
27
|
+
|
|
28
|
+
<a href="https://github.com/nuhmanpk"><img alt="Sponsor" src="https://img.shields.io/badge/sponsor-nuhmanpk-EA4AAA?style=flat-square&logo=githubsponsors&logoColor=white" /></a>
|
|
29
|
+
<a href="https://buymeacoffee.com/nuhmanpk"><img alt="Buy me a coffee" src="https://img.shields.io/badge/buy%20me%20a%20coffee-nuhmanpk-FFDD00?style=flat-square&logo=buymeacoffee&logoColor=black" /></a>
|
|
30
|
+
|
|
31
|
+
<br/>
|
|
32
|
+
|
|
33
|
+
[**Documentation**](DOCS.md) · [Quick start](#quick-start) · [CLI](#command-line) · [Engines](#search-engines) · [PyPI](https://pypi.org/project/headless-driver/) · [Issues](https://github.com/nuhmanpk/headless-driver/issues)
|
|
34
|
+
|
|
35
|
+
</div>
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Features
|
|
40
|
+
|
|
41
|
+
- Headless and windowed Chrome management, with temporary or persistent profiles
|
|
42
|
+
- HTTP and SOCKS proxy support, plus optional stealth mode
|
|
43
|
+
- Automatic ChromeDriver installation, and recovery when the installed driver does not match your Chrome
|
|
44
|
+
- Screenshot and PDF export via Chrome DevTools
|
|
45
|
+
- Download folder management
|
|
46
|
+
- Multi-driver manager for many isolated browser instances
|
|
47
|
+
- Search scraping across 8 engines, starting with DuckDuckGo's no-JavaScript endpoint and falling back automatically when one blocks you
|
|
48
|
+
- Bounded page-load timeouts, so a stalled engine fails over instead of hanging
|
|
49
|
+
- A `headless-driver` CLI with coloured output, `--json` for piping, and a `doctor` command that diagnoses your setup
|
|
50
|
+
|
|
51
|
+
## Install
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
pip install headless-driver
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Needs Python 3.9+ and an installed Chrome or Chromium. A matching ChromeDriver
|
|
58
|
+
is downloaded automatically when required.
|
|
59
|
+
|
|
60
|
+
On Debian/Ubuntu you can install a system browser and driver with:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
sudo apt update && sudo apt install -y chromium chromium-driver
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Quick start
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
from headless import Headless
|
|
70
|
+
|
|
71
|
+
with Headless() as driver:
|
|
72
|
+
driver.get("https://example.com")
|
|
73
|
+
print(driver.title)
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Search the web:
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
from headless import AdvancedSearchScraper
|
|
80
|
+
|
|
81
|
+
with AdvancedSearchScraper(max_results=5) as scraper:
|
|
82
|
+
for item in scraper.search("python headless browser"):
|
|
83
|
+
print(item["title"], item["url"])
|
|
84
|
+
print("answered by", scraper.last_engine)
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Screenshot and PDF:
|
|
88
|
+
|
|
89
|
+
```python
|
|
90
|
+
from headless import ExtendedHeadless
|
|
91
|
+
|
|
92
|
+
hl = ExtendedHeadless(stealth=True)
|
|
93
|
+
driver = hl.get_driver()
|
|
94
|
+
driver.get("https://example.com")
|
|
95
|
+
|
|
96
|
+
hl.screenshot("example.png")
|
|
97
|
+
hl.save_pdf("example.pdf")
|
|
98
|
+
hl.quit()
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Command line
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
headless-driver search "python headless browser" -n 5
|
|
105
|
+
headless-driver search "selenium stealth" --json | jq -r '.results[].url'
|
|
106
|
+
headless-driver engines # engine list and fallback order
|
|
107
|
+
headless-driver doctor # check chrome, driver, connectivity
|
|
108
|
+
headless-driver shot https://example.com -o page.png --window 1280x720
|
|
109
|
+
headless-driver pdf https://example.com -o page.pdf
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
`doctor` is the quickest way to explain a failing run:
|
|
113
|
+
|
|
114
|
+
```
|
|
115
|
+
── browser ──────────────────────────────────────────────
|
|
116
|
+
✓ chrome Google Chrome 151.0.7922.140
|
|
117
|
+
✓ chromedriver ChromeDriver 148.0.7778.179
|
|
118
|
+
! version match chrome 151 vs driver 148 - a matching driver will be downloaded
|
|
119
|
+
── connectivity ─────────────────────────────────────────
|
|
120
|
+
✓ html.duckduckgo.com reachable
|
|
121
|
+
✓ www.bing.com reachable
|
|
122
|
+
── smoke test ───────────────────────────────────────────
|
|
123
|
+
✓ launch and navigate page title 'ok'
|
|
124
|
+
|
|
125
|
+
13 passed, 1 warning +++++++++++++~
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Colour switches off automatically when output is not a terminal, so piping
|
|
129
|
+
gives plain text. `NO_COLOR=1` or `--no-color` disables it; `FORCE_COLOR=1`
|
|
130
|
+
forces it on. Diagnostics go to stderr, keeping `--json` on stdout clean.
|
|
131
|
+
Exit status is `0` on success, `1` when nothing could be produced, `2` for a
|
|
132
|
+
usage error.
|
|
133
|
+
|
|
134
|
+
See [DOCS.md](DOCS.md#command-line) for every command and flag.
|
|
135
|
+
|
|
136
|
+
## Search engines
|
|
137
|
+
|
|
138
|
+
Searching starts at DuckDuckGo's no-JavaScript endpoint, which returns
|
|
139
|
+
server-rendered HTML and so is much faster than the JavaScript front end. If an
|
|
140
|
+
engine serves a bot check, returns nothing, or stalls, the next one is tried:
|
|
141
|
+
|
|
142
|
+
```
|
|
143
|
+
duckduckgo → duckduckgo_lite → bing → mojeek
|
|
144
|
+
→ duckduckgo_js → startpage → google → yandex
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
`search()` returns `[]` only once every engine has been tried.
|
|
148
|
+
|
|
149
|
+
```python
|
|
150
|
+
AdvancedSearchScraper(search_engine="bing") # start elsewhere
|
|
151
|
+
AdvancedSearchScraper(fallback=False) # single engine
|
|
152
|
+
AdvancedSearchScraper(fallback_engines=["bing", "mojeek"]) # custom order
|
|
153
|
+
scraper.search("query", engine="bing") # force, one-off
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Add your own engine with `register_engine()`. Full details, including the result
|
|
157
|
+
dict and redirect handling, are in
|
|
158
|
+
[DOCS.md](DOCS.md#search-engines).
|
|
159
|
+
|
|
160
|
+
## More
|
|
161
|
+
|
|
162
|
+
- [Full documentation](DOCS.md) — every class, argument and CLI flag
|
|
163
|
+
- [Python API](DOCS.md#python-api) — `Headless`, `ExtendedHeadless`, `MultiDriverManager`, `AdvancedSearchScraper`, `SearchScraper`
|
|
164
|
+
- [Timeouts](DOCS.md#timeouts) and [troubleshooting](DOCS.md#troubleshooting)
|
|
165
|
+
- [Running the tests](DOCS.md#running-the-tests)
|
|
166
|
+
|
|
167
|
+
## Support
|
|
168
|
+
|
|
169
|
+
If this project saves you time, you can support its development:
|
|
170
|
+
|
|
171
|
+
[](https://github.com/nuhmanpk)
|
|
172
|
+
[](https://buymeacoffee.com/nuhmanpk)
|
|
173
|
+
|
|
174
|
+
- Sponsor on GitHub — [github.com/nuhmanpk](https://github.com/nuhmanpk)
|
|
175
|
+
- Buy me a coffee — [buymeacoffee.com/nuhmanpk](https://buymeacoffee.com/nuhmanpk)
|
|
176
|
+
|
|
177
|
+
Starring the [repository](https://github.com/nuhmanpk/headless-driver) helps too.
|
|
178
|
+
|
|
179
|
+
## License
|
|
180
|
+
|
|
181
|
+
MIT — see [LICENSE](LICENSE).
|
|
182
|
+
|
|
183
|
+
[Happy coding 🚀](https://github.com/nuhmanpk/)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from .core import (
|
|
2
|
+
Headless,
|
|
3
|
+
SearchScraper,
|
|
4
|
+
find_chromedriver_path,
|
|
5
|
+
find_chrome_binary,
|
|
6
|
+
install_chromedriver,
|
|
7
|
+
)
|
|
8
|
+
from .manager import ExtendedHeadless, MultiDriverManager
|
|
9
|
+
from .scraper import AdvancedSearchScraper, ENGINE_SPECS, DEFAULT_ENGINE, DEFAULT_FALLBACK_ENGINES
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
"Headless",
|
|
13
|
+
"SearchScraper",
|
|
14
|
+
"ExtendedHeadless",
|
|
15
|
+
"MultiDriverManager",
|
|
16
|
+
"AdvancedSearchScraper",
|
|
17
|
+
"find_chromedriver_path",
|
|
18
|
+
"find_chrome_binary",
|
|
19
|
+
"install_chromedriver",
|
|
20
|
+
"ENGINE_SPECS",
|
|
21
|
+
"DEFAULT_ENGINE",
|
|
22
|
+
"DEFAULT_FALLBACK_ENGINES",
|
|
23
|
+
]
|