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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pywaybackup
3
- Version: 0.2.6
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
- ![Version](https://img.shields.io/badge/Version-0.2.6-blue)
15
+ ![Version](https://img.shields.io/badge/Version-0.3.0-blue)
16
16
  ![Release](https://img.shields.io/badge/Release-alpha-red)
17
+ ![Python Version](https://img.shields.io/badge/Python-3.6-blue)
17
18
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](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 requirements <br>
45
- ```pip install -r requirements.txt```
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
- ![Version](https://img.shields.io/badge/Version-0.2.6-blue)
3
+ ![Version](https://img.shields.io/badge/Version-0.3.0-blue)
4
4
  ![Release](https://img.shields.io/badge/Release-alpha-red)
5
+ ![Python Version](https://img.shields.io/badge/Python-3.6-blue)
5
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](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 requirements <br>
33
- ```pip install -r requirements.txt```
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
- #import magic
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 download_url_list(cdxResult_list, output, retry, mode):
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
- # download urls
142
- for download_entry in download_list:
143
- print(f"\n-----> Snapshot [{download_list.index(download_entry) + 1}/{len(download_list)}]")
144
- download_url, download_filename, download_filepath = download_entry["url"], download_entry["filename"], download_entry["filepath"]
145
- download_status=download_url_entry(download_url, download_filename, download_filepath)
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 > 0 or retry is True:
148
- print(f"\n-----> Fail downloads: {len(failed_urls)}")
149
- download_retry(failed_urls, retry)
150
-
151
- # batch_size = len(download_list) // 10
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
- print(f"\n-----> RETRY attempt: [{attempt}/{max_attempt}] Snapshot [{failed_urls.index(failed_entry) + 1}/{len(failed_urls)}]")
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 url
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 = 40
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
- data = requests.get(url, headers=headers)
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.content)
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 requests.exceptions.ConnectionError as e:
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
- else:
207
- print(f"FAILED -> download, append to failed_urls: {url}")
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 guess_mimetype(filepath):
217
- # print("")
218
- # print("Guessing mimetypes for unknown files...")
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
- __version__ = "0.2.6"
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
- #special.add_argument('--detect-filetype', action='store_true', help='If a file has no extension, try to detect the filetype')
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.download_url_list(cdxResult_list, args.output, args.retry_failed, mode)
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.2.6
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
- ![Version](https://img.shields.io/badge/Version-0.2.6-blue)
15
+ ![Version](https://img.shields.io/badge/Version-0.3.0-blue)
16
16
  ![Release](https://img.shields.io/badge/Release-alpha-red)
17
+ ![Python Version](https://img.shields.io/badge/Python-3.6-blue)
17
18
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](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 requirements <br>
45
- ```pip install -r requirements.txt```
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/pywaybackup.py
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
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ waybackup = pywaybackup.main:main
@@ -0,0 +1,2 @@
1
+ python-magic==0.4.27
2
+ requests==2.31.0
@@ -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.pywaybackup:main',
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,2 +0,0 @@
1
- [console_scripts]
2
- waybackup = pywaybackup.pywaybackup:main
@@ -1 +0,0 @@
1
- requests==2.31.0
File without changes
File without changes