pywaybackup 0.2.7__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.7 → pywaybackup-0.3.0}/PKG-INFO +2 -2
- {pywaybackup-0.2.7 → pywaybackup-0.3.0}/README.md +1 -1
- pywaybackup-0.3.0/pywaybackup/__version__.py +1 -0
- {pywaybackup-0.2.7 → pywaybackup-0.3.0}/pywaybackup/archive.py +28 -24
- {pywaybackup-0.2.7 → pywaybackup-0.3.0}/pywaybackup/main.py +2 -1
- {pywaybackup-0.2.7 → pywaybackup-0.3.0}/pywaybackup.egg-info/PKG-INFO +2 -2
- pywaybackup-0.2.7/pywaybackup/__version__.py +0 -1
- {pywaybackup-0.2.7 → pywaybackup-0.3.0}/LICENSE +0 -0
- {pywaybackup-0.2.7 → pywaybackup-0.3.0}/pywaybackup/__init__.py +0 -0
- {pywaybackup-0.2.7 → pywaybackup-0.3.0}/pywaybackup.egg-info/SOURCES.txt +0 -0
- {pywaybackup-0.2.7 → pywaybackup-0.3.0}/pywaybackup.egg-info/dependency_links.txt +0 -0
- {pywaybackup-0.2.7 → pywaybackup-0.3.0}/pywaybackup.egg-info/entry_points.txt +0 -0
- {pywaybackup-0.2.7 → pywaybackup-0.3.0}/pywaybackup.egg-info/requires.txt +0 -0
- {pywaybackup-0.2.7 → pywaybackup-0.3.0}/pywaybackup.egg-info/top_level.txt +0 -0
- {pywaybackup-0.2.7 → pywaybackup-0.3.0}/setup.cfg +0 -0
- {pywaybackup-0.2.7 → pywaybackup-0.3.0}/setup.py +0 -0
- {pywaybackup-0.2.7 → pywaybackup-0.3.0}/test/test.py +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,7 +12,7 @@ License-File: LICENSE
|
|
|
12
12
|
|
|
13
13
|
# archive wayback downloader
|
|
14
14
|
|
|
15
|
-

|
|
16
16
|

|
|
17
17
|

|
|
18
18
|
[](https://opensource.org/licenses/MIT)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# archive wayback downloader
|
|
2
2
|
|
|
3
|
-

|
|
4
4
|

|
|
5
5
|

|
|
6
6
|
[](https://opensource.org/licenses/MIT)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.3.0"
|
|
@@ -4,6 +4,7 @@ import requests
|
|
|
4
4
|
import datetime
|
|
5
5
|
import os
|
|
6
6
|
import magic
|
|
7
|
+
import threading
|
|
7
8
|
from pprint import pprint
|
|
8
9
|
import time
|
|
9
10
|
import pathlib
|
|
@@ -123,15 +124,12 @@ def remove_empty_folders(path, remove_root=True):
|
|
|
123
124
|
# example download: http://web.archive.org/web/20190815104545id_/https://www.google.com/
|
|
124
125
|
# example url: https://www.google.com/
|
|
125
126
|
# example timestamp: 20190815104545
|
|
126
|
-
def
|
|
127
|
+
def download_prepare_list(cdxResult_list, output, retry, workers, mode):
|
|
127
128
|
"""
|
|
128
129
|
Download a list of urls in format: [{"timestamp": "20190815104545", "url": "https://www.google.com/"}]
|
|
129
130
|
"""
|
|
130
|
-
#def download_batch(cdxResult_list):
|
|
131
131
|
print("\nDownloading latest snapshots of each file...")
|
|
132
|
-
failed_urls = []
|
|
133
132
|
download_list = []
|
|
134
|
-
connection = http.client.HTTPSConnection("web.archive.org")
|
|
135
133
|
for snapshot in cdxResult_list:
|
|
136
134
|
timestamp, url = snapshot["timestamp"], snapshot["url"]
|
|
137
135
|
type = determine_url_filetype(url)
|
|
@@ -139,28 +137,32 @@ def download_url_list(cdxResult_list, output, retry, mode):
|
|
|
139
137
|
domain, subdir, filename = split_url(url)
|
|
140
138
|
if mode == "current": download_dir = os.path.join(output, domain, subdir)
|
|
141
139
|
if mode == "full": download_dir = os.path.join(output, domain, timestamp, subdir)
|
|
142
|
-
download_filepath = os.path.join(download_dir, filename)
|
|
143
140
|
download_list.append({"url": download_url, "filename": filename, "filepath": download_dir})
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
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)
|
|
149
162
|
if download_status != bool(1): failed_urls.append({"url": download_url, "filename": download_filename, "filepath": download_filepath})
|
|
150
163
|
if retry:
|
|
151
|
-
print(f"\n-----> Fail downloads: {len(failed_urls)}")
|
|
152
164
|
download_retry(failed_urls, retry, connection)
|
|
153
165
|
connection.close()
|
|
154
|
-
|
|
155
|
-
# batch_size = len(download_list) // 10
|
|
156
|
-
# batch_list = [download_list[i:i + batch_size] for i in range(0, len(download_list), batch_size)]
|
|
157
|
-
# for batch in batch_list:
|
|
158
|
-
# threads = []
|
|
159
|
-
# thread = threading.Thread(target=download_batch, args=(batch,))
|
|
160
|
-
# thread.start()
|
|
161
|
-
# threads.append(thread)
|
|
162
|
-
# for thread in threads:
|
|
163
|
-
# thread.join()
|
|
164
166
|
|
|
165
167
|
def download_retry(failed_urls, retry, connection):
|
|
166
168
|
"""
|
|
@@ -174,16 +176,16 @@ def download_retry(failed_urls, retry, connection):
|
|
|
174
176
|
print(f"\n-----> Retrying...")
|
|
175
177
|
retry_urls = []
|
|
176
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)}]"
|
|
177
180
|
download_url, download_filename, download_filepath = failed_entry["url"], failed_entry["filename"], failed_entry["filepath"]
|
|
178
|
-
|
|
179
|
-
retry_status=download_url_entry(download_url, download_filename, download_filepath, connection)
|
|
181
|
+
retry_status=download_url_entry(download_url, download_filename, download_filepath, connection, status)
|
|
180
182
|
if retry_status != bool(1):
|
|
181
183
|
retry_urls.append({"url": download_url, "filename": download_filename, "filepath": download_filepath})
|
|
182
184
|
failed_urls = retry_urls
|
|
183
185
|
print(f"\n-----> Fail downloads: {len(failed_urls)}")
|
|
184
186
|
if retry != None: attempt += 1
|
|
185
187
|
|
|
186
|
-
def download_url_entry(url, filename, filepath, connection):
|
|
188
|
+
def download_url_entry(url, filename, filepath, connection, status):
|
|
187
189
|
"""
|
|
188
190
|
Download a single url.
|
|
189
191
|
Success: return bool(1)
|
|
@@ -201,10 +203,12 @@ def download_url_entry(url, filename, filepath, connection):
|
|
|
201
203
|
data = response.read()
|
|
202
204
|
with open(output, 'wb') as file:
|
|
203
205
|
file.write(data)
|
|
206
|
+
print(status)
|
|
204
207
|
print(f"SUCCESS -> {url}")
|
|
205
208
|
print(f" -> {output}")
|
|
206
209
|
return bool(1)
|
|
207
210
|
except http.client.HTTPException as e:
|
|
211
|
+
print(status)
|
|
208
212
|
print(f"REFUSED -> ({i+1}/{max_retries}), reconnect in {sleep_time} seconds...")
|
|
209
213
|
time.sleep(sleep_time)
|
|
210
214
|
print(f"FAILED -> download, append to failed_urls: {url}")
|
|
@@ -19,6 +19,7 @@ def main():
|
|
|
19
19
|
special = parser.add_argument_group('special')
|
|
20
20
|
special.add_argument('--detect-filetype', action='store_true', help='If a file has no extension, try to detect the filetype')
|
|
21
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)')
|
|
22
23
|
|
|
23
24
|
args = parser.parse_args()
|
|
24
25
|
if args.current:
|
|
@@ -32,7 +33,7 @@ def main():
|
|
|
32
33
|
if args.list:
|
|
33
34
|
archive.print_result(cdxResult_list)
|
|
34
35
|
if not args.list:
|
|
35
|
-
archive.
|
|
36
|
+
archive.download_prepare_list(cdxResult_list, args.output, args.retry_failed, args.workers, mode)
|
|
36
37
|
archive.remove_empty_folders(args.output)
|
|
37
38
|
if args.detect_filetype:
|
|
38
39
|
archive.detect_filetype(args.output)
|
|
@@ -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,7 +12,7 @@ License-File: LICENSE
|
|
|
12
12
|
|
|
13
13
|
# archive wayback downloader
|
|
14
14
|
|
|
15
|
-

|
|
16
16
|

|
|
17
17
|

|
|
18
18
|
[](https://opensource.org/licenses/MIT)
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.2.7"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|