pywaybackup 0.2.6__tar.gz → 0.3.0__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.
- {pywaybackup-0.2.6 → pywaybackup-0.3.0}/PKG-INFO +5 -14
- {pywaybackup-0.2.6 → pywaybackup-0.3.0}/README.md +4 -13
- pywaybackup-0.3.0/pywaybackup/__version__.py +1 -0
- {pywaybackup-0.2.6 → pywaybackup-0.3.0}/pywaybackup/archive.py +61 -45
- pywaybackup-0.2.6/pywaybackup/pywaybackup.py → pywaybackup-0.3.0/pywaybackup/main.py +7 -3
- {pywaybackup-0.2.6 → pywaybackup-0.3.0}/pywaybackup.egg-info/PKG-INFO +5 -14
- {pywaybackup-0.2.6 → pywaybackup-0.3.0}/pywaybackup.egg-info/SOURCES.txt +4 -2
- pywaybackup-0.3.0/pywaybackup.egg-info/entry_points.txt +2 -0
- pywaybackup-0.3.0/pywaybackup.egg-info/requires.txt +2 -0
- {pywaybackup-0.2.6 → pywaybackup-0.3.0}/setup.py +2 -2
- pywaybackup-0.3.0/test/test.py +25 -0
- pywaybackup-0.2.6/pywaybackup.egg-info/entry_points.txt +0 -2
- pywaybackup-0.2.6/pywaybackup.egg-info/requires.txt +0 -1
- {pywaybackup-0.2.6 → pywaybackup-0.3.0}/LICENSE +0 -0
- {pywaybackup-0.2.6 → pywaybackup-0.3.0}/pywaybackup/__init__.py +0 -0
- {pywaybackup-0.2.6 → pywaybackup-0.3.0}/pywaybackup.egg-info/dependency_links.txt +0 -0
- {pywaybackup-0.2.6 → pywaybackup-0.3.0}/pywaybackup.egg-info/top_level.txt +0 -0
- {pywaybackup-0.2.6 → pywaybackup-0.3.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pywaybackup
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Download snapshots from the Wayback Machine
|
|
5
5
|
Home-page: https://github.com/bitdruid/waybackup
|
|
6
6
|
Author: bitdruid
|
|
@@ -12,22 +12,15 @@ License-File: LICENSE
|
|
|
12
12
|
|
|
13
13
|
# archive wayback downloader
|
|
14
14
|
|
|
15
|
-

|
|
16
16
|

|
|
17
|
+

|
|
17
18
|
[](https://opensource.org/licenses/MIT)
|
|
18
19
|
|
|
19
20
|
Downloading archived web pages from the [Wayback Machine](https://archive.org/web/).
|
|
20
21
|
|
|
21
22
|
Internet-archive is a nice source for several OSINT-information. This script is a work in progress to query and fetch archived web pages.
|
|
22
23
|
|
|
23
|
-
This project is not intended to get fast results. Moreover it is a tool to get a lot of data over a long period of time.
|
|
24
|
-
|
|
25
|
-
## Limitations
|
|
26
|
-
|
|
27
|
-
The wayback-machine does refuse connections over public access if the query rate is too high. So for now there seems no possibility to implement a multi-threaded download. As soon as a connection is refused, the script will wait and retry the query. Existing projects seem to ignore this limitation and just rush through the queries. This resulted in a lot of missing files and probably missing knowledge about the target.
|
|
28
|
-
|
|
29
|
-
Timeout seems to be about 2.5 minutes per 20 downloads.
|
|
30
|
-
|
|
31
24
|
## Installation
|
|
32
25
|
|
|
33
26
|
### Pip
|
|
@@ -41,10 +34,8 @@ Timeout seems to be about 2.5 minutes per 20 downloads.
|
|
|
41
34
|
|
|
42
35
|
1. Clone the repository <br>
|
|
43
36
|
```git clone https://github.com/bitdruid/waybackup.git```
|
|
44
|
-
2. Install
|
|
45
|
-
```
|
|
46
|
-
3. Run the script <br>
|
|
47
|
-
```python waybackup.py -h```
|
|
37
|
+
2. Install <br>
|
|
38
|
+
```python setup.py install```
|
|
48
39
|
|
|
49
40
|
## Usage
|
|
50
41
|
|
|
@@ -1,21 +1,14 @@
|
|
|
1
1
|
# archive wayback downloader
|
|
2
2
|
|
|
3
|
-

|
|
4
4
|

|
|
5
|
+

|
|
5
6
|
[](https://opensource.org/licenses/MIT)
|
|
6
7
|
|
|
7
8
|
Downloading archived web pages from the [Wayback Machine](https://archive.org/web/).
|
|
8
9
|
|
|
9
10
|
Internet-archive is a nice source for several OSINT-information. This script is a work in progress to query and fetch archived web pages.
|
|
10
11
|
|
|
11
|
-
This project is not intended to get fast results. Moreover it is a tool to get a lot of data over a long period of time.
|
|
12
|
-
|
|
13
|
-
## Limitations
|
|
14
|
-
|
|
15
|
-
The wayback-machine does refuse connections over public access if the query rate is too high. So for now there seems no possibility to implement a multi-threaded download. As soon as a connection is refused, the script will wait and retry the query. Existing projects seem to ignore this limitation and just rush through the queries. This resulted in a lot of missing files and probably missing knowledge about the target.
|
|
16
|
-
|
|
17
|
-
Timeout seems to be about 2.5 minutes per 20 downloads.
|
|
18
|
-
|
|
19
12
|
## Installation
|
|
20
13
|
|
|
21
14
|
### Pip
|
|
@@ -29,10 +22,8 @@ Timeout seems to be about 2.5 minutes per 20 downloads.
|
|
|
29
22
|
|
|
30
23
|
1. Clone the repository <br>
|
|
31
24
|
```git clone https://github.com/bitdruid/waybackup.git```
|
|
32
|
-
2. Install
|
|
33
|
-
```
|
|
34
|
-
3. Run the script <br>
|
|
35
|
-
```python waybackup.py -h```
|
|
25
|
+
2. Install <br>
|
|
26
|
+
```python setup.py install```
|
|
36
27
|
|
|
37
28
|
## Usage
|
|
38
29
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.3.0"
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
import threading
|
|
1
|
+
#import threading
|
|
2
|
+
from pathlib import Path
|
|
2
3
|
import requests
|
|
3
4
|
import datetime
|
|
4
5
|
import os
|
|
5
|
-
|
|
6
|
+
import magic
|
|
7
|
+
import threading
|
|
6
8
|
from pprint import pprint
|
|
7
9
|
import time
|
|
8
10
|
import pathlib
|
|
11
|
+
import http.client
|
|
9
12
|
|
|
10
13
|
def print_result(result_list):
|
|
11
14
|
print("")
|
|
@@ -121,13 +124,11 @@ def remove_empty_folders(path, remove_root=True):
|
|
|
121
124
|
# example download: http://web.archive.org/web/20190815104545id_/https://www.google.com/
|
|
122
125
|
# example url: https://www.google.com/
|
|
123
126
|
# example timestamp: 20190815104545
|
|
124
|
-
def
|
|
127
|
+
def download_prepare_list(cdxResult_list, output, retry, workers, mode):
|
|
125
128
|
"""
|
|
126
129
|
Download a list of urls in format: [{"timestamp": "20190815104545", "url": "https://www.google.com/"}]
|
|
127
130
|
"""
|
|
128
|
-
#def download_batch(cdxResult_list):
|
|
129
131
|
print("\nDownloading latest snapshots of each file...")
|
|
130
|
-
failed_urls = []
|
|
131
132
|
download_list = []
|
|
132
133
|
for snapshot in cdxResult_list:
|
|
133
134
|
timestamp, url = snapshot["timestamp"], snapshot["url"]
|
|
@@ -136,29 +137,34 @@ def download_url_list(cdxResult_list, output, retry, mode):
|
|
|
136
137
|
domain, subdir, filename = split_url(url)
|
|
137
138
|
if mode == "current": download_dir = os.path.join(output, domain, subdir)
|
|
138
139
|
if mode == "full": download_dir = os.path.join(output, domain, timestamp, subdir)
|
|
139
|
-
download_filepath = os.path.join(download_dir, filename)
|
|
140
140
|
download_list.append({"url": download_url, "filename": filename, "filepath": download_dir})
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
141
|
+
if workers > 1:
|
|
142
|
+
print(f"\n-----> Simultaneous downloads: {workers}")
|
|
143
|
+
threads = []
|
|
144
|
+
worker = 0
|
|
145
|
+
batch_size = len(download_list) // workers + 1
|
|
146
|
+
batch_list = [download_list[i:i + batch_size] for i in range(0, len(download_list), batch_size)]
|
|
147
|
+
for batch in batch_list:
|
|
148
|
+
worker += 1
|
|
149
|
+
thread = threading.Thread(target=download_url_list, args=(batch, worker, retry))
|
|
150
|
+
threads.append(thread)
|
|
151
|
+
thread.start()
|
|
152
|
+
for thread in threads:
|
|
153
|
+
thread.join()
|
|
154
|
+
|
|
155
|
+
def download_url_list(url_list, worker, retry):
|
|
156
|
+
failed_urls = []
|
|
157
|
+
connection = http.client.HTTPSConnection("web.archive.org")
|
|
158
|
+
for url_entry in url_list:
|
|
159
|
+
status = f"\n-----> Snapshot [{url_list.index(url_entry) + 1}/{len(url_list)}] Worker: {worker}"
|
|
160
|
+
download_url, download_filename, download_filepath = url_entry["url"], url_entry["filename"], url_entry["filepath"]
|
|
161
|
+
download_status=download_url_entry(download_url, download_filename, download_filepath, connection, status)
|
|
146
162
|
if download_status != bool(1): failed_urls.append({"url": download_url, "filename": download_filename, "filepath": download_filepath})
|
|
147
|
-
if retry
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
# batch_list = [download_list[i:i + batch_size] for i in range(0, len(download_list), batch_size)]
|
|
153
|
-
# for batch in batch_list:
|
|
154
|
-
# threads = []
|
|
155
|
-
# thread = threading.Thread(target=download_batch, args=(batch,))
|
|
156
|
-
# thread.start()
|
|
157
|
-
# threads.append(thread)
|
|
158
|
-
# for thread in threads:
|
|
159
|
-
# thread.join()
|
|
160
|
-
|
|
161
|
-
def download_retry(failed_urls, retry):
|
|
163
|
+
if retry:
|
|
164
|
+
download_retry(failed_urls, retry, connection)
|
|
165
|
+
connection.close()
|
|
166
|
+
|
|
167
|
+
def download_retry(failed_urls, retry, connection):
|
|
162
168
|
"""
|
|
163
169
|
Retry failed downloads.
|
|
164
170
|
failed_urls: [{"url": download_url, "filename": download_filename, "filepath": download_filepath}]
|
|
@@ -170,50 +176,60 @@ def download_retry(failed_urls, retry):
|
|
|
170
176
|
print(f"\n-----> Retrying...")
|
|
171
177
|
retry_urls = []
|
|
172
178
|
for failed_entry in failed_urls:
|
|
179
|
+
status = f"\n-----> RETRY attempt: [{attempt}/{max_attempt}] Snapshot [{failed_urls.index(failed_entry) + 1}/{len(failed_urls)}]"
|
|
173
180
|
download_url, download_filename, download_filepath = failed_entry["url"], failed_entry["filename"], failed_entry["filepath"]
|
|
174
|
-
|
|
175
|
-
retry_status=download_url_entry(download_url, download_filename, download_filepath)
|
|
181
|
+
retry_status=download_url_entry(download_url, download_filename, download_filepath, connection, status)
|
|
176
182
|
if retry_status != bool(1):
|
|
177
183
|
retry_urls.append({"url": download_url, "filename": download_filename, "filepath": download_filepath})
|
|
178
184
|
failed_urls = retry_urls
|
|
179
185
|
print(f"\n-----> Fail downloads: {len(failed_urls)}")
|
|
180
186
|
if retry != None: attempt += 1
|
|
181
187
|
|
|
182
|
-
def download_url_entry(url, filename, filepath):
|
|
188
|
+
def download_url_entry(url, filename, filepath, connection, status):
|
|
183
189
|
"""
|
|
184
190
|
Download a single url.
|
|
185
191
|
Success: return bool(1)
|
|
186
|
-
Fail: return
|
|
192
|
+
Fail: return bool(0)
|
|
187
193
|
"""
|
|
188
|
-
# create output dirs
|
|
189
194
|
create_dirs(filepath)
|
|
190
195
|
output = os.path.join(filepath, filename)
|
|
191
196
|
max_retries = 2
|
|
192
|
-
sleep_time =
|
|
197
|
+
sleep_time = 45
|
|
193
198
|
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36'}
|
|
194
|
-
# download url
|
|
195
199
|
for i in range(max_retries):
|
|
196
200
|
try:
|
|
197
|
-
|
|
201
|
+
connection.request("GET", url, headers=headers)
|
|
202
|
+
response = connection.getresponse()
|
|
203
|
+
data = response.read()
|
|
198
204
|
with open(output, 'wb') as file:
|
|
199
|
-
file.write(data
|
|
205
|
+
file.write(data)
|
|
206
|
+
print(status)
|
|
200
207
|
print(f"SUCCESS -> {url}")
|
|
201
208
|
print(f" -> {output}")
|
|
202
209
|
return bool(1)
|
|
203
|
-
except
|
|
210
|
+
except http.client.HTTPException as e:
|
|
211
|
+
print(status)
|
|
204
212
|
print(f"REFUSED -> ({i+1}/{max_retries}), reconnect in {sleep_time} seconds...")
|
|
205
213
|
time.sleep(sleep_time)
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
return bool(0)
|
|
209
|
-
|
|
210
|
-
|
|
214
|
+
print(f"FAILED -> download, append to failed_urls: {url}")
|
|
215
|
+
return bool(0)
|
|
211
216
|
|
|
212
217
|
|
|
213
218
|
|
|
214
219
|
# scan output folder and guess mimetype for each file
|
|
215
220
|
# if add file extension if not present
|
|
216
|
-
# def
|
|
217
|
-
# print("")
|
|
218
|
-
#
|
|
219
|
-
|
|
221
|
+
# def detect_filetype(filepath):
|
|
222
|
+
# print("\nDetecting filetypes...")
|
|
223
|
+
# path = Path(filepath)
|
|
224
|
+
# if not path.is_dir():
|
|
225
|
+
# print(f"\n-----> ERROR: {filepath} is not a directory"); return
|
|
226
|
+
# for file_path in path.rglob("*"):
|
|
227
|
+
# if file_path.is_file():
|
|
228
|
+
# file_extension = file_path.suffix
|
|
229
|
+
# if not file_extension:
|
|
230
|
+
# mime_type = magic.from_file(str(file_path), mime=True)
|
|
231
|
+
# file_extension = mime_type.split("/")[-1]
|
|
232
|
+
# new_file_path = file_path.with_suffix('.' + file_extension)
|
|
233
|
+
# file_path.rename(new_file_path)
|
|
234
|
+
# print(f"NO EXT -> {file_path}")
|
|
235
|
+
# print(f" NEW -> {new_file_path}")
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import pywaybackup.archive as archive
|
|
2
2
|
import argparse
|
|
3
3
|
import os
|
|
4
|
-
|
|
4
|
+
|
|
5
|
+
from pywaybackup.__version__ import __version__
|
|
5
6
|
|
|
6
7
|
def main():
|
|
7
8
|
parser = argparse.ArgumentParser(description='Download from wayback machine (archive.org)')
|
|
@@ -16,8 +17,9 @@ def main():
|
|
|
16
17
|
optional.add_argument('-r', '--range', type=int, help='Range in years to search')
|
|
17
18
|
optional.add_argument('-o', '--output', type=str, help='Output folder')
|
|
18
19
|
special = parser.add_argument_group('special')
|
|
19
|
-
|
|
20
|
+
special.add_argument('--detect-filetype', action='store_true', help='If a file has no extension, try to detect the filetype')
|
|
20
21
|
special.add_argument('--retry-failed', nargs='?', const=True, type=int, help='Retry failed downloads (opt tries as int, else infinite)')
|
|
22
|
+
special.add_argument('--workers', type=int, default=1, help='Number of workers (simultaneous downloads)')
|
|
21
23
|
|
|
22
24
|
args = parser.parse_args()
|
|
23
25
|
if args.current:
|
|
@@ -31,8 +33,10 @@ def main():
|
|
|
31
33
|
if args.list:
|
|
32
34
|
archive.print_result(cdxResult_list)
|
|
33
35
|
if not args.list:
|
|
34
|
-
archive.
|
|
36
|
+
archive.download_prepare_list(cdxResult_list, args.output, args.retry_failed, args.workers, mode)
|
|
35
37
|
archive.remove_empty_folders(args.output)
|
|
38
|
+
if args.detect_filetype:
|
|
39
|
+
archive.detect_filetype(args.output)
|
|
36
40
|
|
|
37
41
|
if __name__ == "__main__":
|
|
38
42
|
main()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pywaybackup
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Download snapshots from the Wayback Machine
|
|
5
5
|
Home-page: https://github.com/bitdruid/waybackup
|
|
6
6
|
Author: bitdruid
|
|
@@ -12,22 +12,15 @@ License-File: LICENSE
|
|
|
12
12
|
|
|
13
13
|
# archive wayback downloader
|
|
14
14
|
|
|
15
|
-

|
|
16
16
|

|
|
17
|
+

|
|
17
18
|
[](https://opensource.org/licenses/MIT)
|
|
18
19
|
|
|
19
20
|
Downloading archived web pages from the [Wayback Machine](https://archive.org/web/).
|
|
20
21
|
|
|
21
22
|
Internet-archive is a nice source for several OSINT-information. This script is a work in progress to query and fetch archived web pages.
|
|
22
23
|
|
|
23
|
-
This project is not intended to get fast results. Moreover it is a tool to get a lot of data over a long period of time.
|
|
24
|
-
|
|
25
|
-
## Limitations
|
|
26
|
-
|
|
27
|
-
The wayback-machine does refuse connections over public access if the query rate is too high. So for now there seems no possibility to implement a multi-threaded download. As soon as a connection is refused, the script will wait and retry the query. Existing projects seem to ignore this limitation and just rush through the queries. This resulted in a lot of missing files and probably missing knowledge about the target.
|
|
28
|
-
|
|
29
|
-
Timeout seems to be about 2.5 minutes per 20 downloads.
|
|
30
|
-
|
|
31
24
|
## Installation
|
|
32
25
|
|
|
33
26
|
### Pip
|
|
@@ -41,10 +34,8 @@ Timeout seems to be about 2.5 minutes per 20 downloads.
|
|
|
41
34
|
|
|
42
35
|
1. Clone the repository <br>
|
|
43
36
|
```git clone https://github.com/bitdruid/waybackup.git```
|
|
44
|
-
2. Install
|
|
45
|
-
```
|
|
46
|
-
3. Run the script <br>
|
|
47
|
-
```python waybackup.py -h```
|
|
37
|
+
2. Install <br>
|
|
38
|
+
```python setup.py install```
|
|
48
39
|
|
|
49
40
|
## Usage
|
|
50
41
|
|
|
@@ -2,11 +2,13 @@ LICENSE
|
|
|
2
2
|
README.md
|
|
3
3
|
setup.py
|
|
4
4
|
pywaybackup/__init__.py
|
|
5
|
+
pywaybackup/__version__.py
|
|
5
6
|
pywaybackup/archive.py
|
|
6
|
-
pywaybackup/
|
|
7
|
+
pywaybackup/main.py
|
|
7
8
|
pywaybackup.egg-info/PKG-INFO
|
|
8
9
|
pywaybackup.egg-info/SOURCES.txt
|
|
9
10
|
pywaybackup.egg-info/dependency_links.txt
|
|
10
11
|
pywaybackup.egg-info/entry_points.txt
|
|
11
12
|
pywaybackup.egg-info/requires.txt
|
|
12
|
-
pywaybackup.egg-info/top_level.txt
|
|
13
|
+
pywaybackup.egg-info/top_level.txt
|
|
14
|
+
test/test.py
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
2
|
from setuptools import setup, find_packages
|
|
3
|
+
from pywaybackup.__version__ import __version__ as VERSION
|
|
3
4
|
|
|
4
|
-
VERSION = '0.2.6'
|
|
5
5
|
DESCRIPTION = 'Download snapshots from the Wayback Machine'
|
|
6
6
|
|
|
7
7
|
import pkg_resources
|
|
@@ -21,7 +21,7 @@ setup(
|
|
|
21
21
|
install_requires=parse_requirements('./requirements.txt'),
|
|
22
22
|
entry_points={
|
|
23
23
|
'console_scripts': [
|
|
24
|
-
'waybackup = pywaybackup.
|
|
24
|
+
'waybackup = pywaybackup.main:main',
|
|
25
25
|
],
|
|
26
26
|
},
|
|
27
27
|
author='bitdruid',
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
def dl(url: str):
|
|
2
|
+
from selenium import webdriver
|
|
3
|
+
from bs4 import BeautifulSoup
|
|
4
|
+
browser = webdriver.Chrome()
|
|
5
|
+
options = webdriver.ChromeOptions()
|
|
6
|
+
options.add_argument('--headless=new')
|
|
7
|
+
options.add_argument('--disable-gpu')
|
|
8
|
+
options.add_argument('--no-sandbox')
|
|
9
|
+
options.add_argument('--disable-dev-shm-usage')
|
|
10
|
+
browser = webdriver.Chrome(options=options)
|
|
11
|
+
browser.get(url)
|
|
12
|
+
soup = BeautifulSoup(browser.page_source, 'html.parser')
|
|
13
|
+
target_path = "test.html"
|
|
14
|
+
with open (target_path, "w") as file:
|
|
15
|
+
file.write(soup.prettify())
|
|
16
|
+
print(soup.prettify())
|
|
17
|
+
|
|
18
|
+
if __name__ == "__main__":
|
|
19
|
+
import sys
|
|
20
|
+
if sys.argv is None or len(sys.argv) < 2:
|
|
21
|
+
print("No url given")
|
|
22
|
+
sys.exit()
|
|
23
|
+
url = sys.argv[1]
|
|
24
|
+
dl(url)
|
|
25
|
+
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
requests==2.31.0
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|