Readd downloader code
This commit is contained in:
parent
4a89c8c136
commit
7a281528e3
110
libbmc/fetcher.py
Normal file
110
libbmc/fetcher.py
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
"""
|
||||||
|
This file contains functions to download locally some papers, eventually using
|
||||||
|
a proxy.
|
||||||
|
"""
|
||||||
|
import socket
|
||||||
|
import socks
|
||||||
|
import sys
|
||||||
|
import urllib
|
||||||
|
|
||||||
|
|
||||||
|
# Default socket to use, if no proxy is used
|
||||||
|
DEFAULT_SOCKET = socket.socket
|
||||||
|
|
||||||
|
|
||||||
|
def download(url, proxies=[None]):
|
||||||
|
"""
|
||||||
|
Download a PDF or DJVU document from a url, eventually using proxies.
|
||||||
|
|
||||||
|
:params url: The URL to the PDF/DJVU document to fetch.
|
||||||
|
:params proxies: An optional list of proxies to use. Proxies will be \
|
||||||
|
used sequentially. Proxies should be a list of proxy strings. \
|
||||||
|
Do not forget to include ``None`` in the list if you want to try \
|
||||||
|
direct fetching without any proxy.
|
||||||
|
|
||||||
|
:returns: A tuple of the raw content of the downloaded data and its \
|
||||||
|
associated content-type. Returns ``(None, None)`` if it was \
|
||||||
|
unable to download the document.
|
||||||
|
"""
|
||||||
|
# Loop over all available connections
|
||||||
|
for proxy in proxies:
|
||||||
|
# Handle no proxy case
|
||||||
|
if proxy is None:
|
||||||
|
socket.socket = DEFAULT_SOCKET
|
||||||
|
# Handle SOCKS proxy
|
||||||
|
elif proxy.startswith('socks'):
|
||||||
|
if proxy[5] == '4':
|
||||||
|
proxy_type = socks.SOCKS4
|
||||||
|
else:
|
||||||
|
proxy_type = socks.SOCKS5
|
||||||
|
proxy = proxy[proxy.find('://') + 3:]
|
||||||
|
try:
|
||||||
|
proxy, port = proxy.split(':')
|
||||||
|
except ValueError:
|
||||||
|
port = None
|
||||||
|
socks.set_default_proxy(proxy_type, proxy, port)
|
||||||
|
socket.socket = socks.socksocket
|
||||||
|
# Handle generic HTTP proxy
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
proxy, port = proxy.split(':')
|
||||||
|
except ValueError:
|
||||||
|
port = None
|
||||||
|
socks.set_default_proxy(socks.HTTP, proxy, port)
|
||||||
|
socket.socket = socks.socksocket
|
||||||
|
|
||||||
|
# Try to fetch the URL using the current proxy
|
||||||
|
try:
|
||||||
|
r = urllib.request.urlopen(url)
|
||||||
|
try:
|
||||||
|
size = int(dict(r.info())['content-length'].strip())
|
||||||
|
except KeyError:
|
||||||
|
try:
|
||||||
|
size = int(dict(r.info())['Content-Length'].strip())
|
||||||
|
except KeyError:
|
||||||
|
size = 0
|
||||||
|
# Download the document
|
||||||
|
dl = b""
|
||||||
|
dl_size = 0
|
||||||
|
while True:
|
||||||
|
buf = r.read(1024)
|
||||||
|
if buf:
|
||||||
|
dl += buf
|
||||||
|
dl_size += len(buf)
|
||||||
|
if size != 0:
|
||||||
|
# Write progress bar on stdout
|
||||||
|
done = int(50 * dl_size / size)
|
||||||
|
sys.stdout.write("\r[%s%s]" %
|
||||||
|
('='*done, ' '*(50-done)))
|
||||||
|
sys.stdout.write(" "+str(int(float(done)/52*100))+"%")
|
||||||
|
sys.stdout.flush()
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
# Fetch content type
|
||||||
|
contenttype = False
|
||||||
|
contenttype_req = None
|
||||||
|
try:
|
||||||
|
contenttype_req = dict(r.info())['content-type']
|
||||||
|
except KeyError:
|
||||||
|
try:
|
||||||
|
contenttype_req = dict(r.info())['Content-Type']
|
||||||
|
except KeyError:
|
||||||
|
continue
|
||||||
|
if 'pdf' in contenttype_req:
|
||||||
|
contenttype = 'pdf'
|
||||||
|
elif 'djvu' in contenttype_req:
|
||||||
|
contenttype = 'djvu'
|
||||||
|
|
||||||
|
# Check content type and status code are ok
|
||||||
|
if r.getcode() != 200 or contenttype is False:
|
||||||
|
# Else, try with the next available proxy
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Return a tuple of the downloaded content and the content-type
|
||||||
|
return (dl, contenttype)
|
||||||
|
# If an exception occurred, continue with next available proxy
|
||||||
|
except (urllib.error.URLError, socket.error, ValueError):
|
||||||
|
continue
|
||||||
|
|
||||||
|
# In case of running out of proxies, return (None, None)
|
||||||
|
return (None, None)
|
Loading…
Reference in New Issue
Block a user