termux - mechanize python documentation
Cómo obtener nombre de archivo de Content-Disposition en los encabezados (3)
Estas expresiones regulares se basan en la gramática de RFC 6266, pero se modifican para aceptar encabezados sin tipo de disposición, por ejemplo, Content-Disposition: filename = example.html
es decir, [tipo de disposición "; ] disposition-parm (";" disposition-parm) * / disposition-type
Manejará los parámetros de nombre de archivo con y sin comillas, y desvinculará los pares citados de los valores entre comillas, por ejemplo, nombre de archivo = "foo /" barra "-> barra de foo"
Manejará los parámetros extendidos de nombre de archivo * y preferirá un parámetro extendido de nombre de archivo sobre un parámetro de nombre de archivo, independientemente del orden en que aparezcan en el encabezado
Elimina la información del nombre de la carpeta, por ejemplo, / etc / passwd -> passwd, y toma como valor predeterminado el nombre base de la ruta URL en ausencia de un parámetro de nombre de archivo (o encabezado, o si el valor del parámetro es una cadena vacía)
Las expresiones regulares token y qdtext se basan en la gramática de RFC 2616, las expresiones regulares mimeCharset y valueChars se basan en la gramática de RFC 5987 y la expresión regular de lenguaje se basa en la gramática de RFC 5646
import re, urllib
from os import path
from urlparse import urlparse
# content-disposition = "Content-Disposition" ":"
# disposition-type *( ";" disposition-parm )
# disposition-type = "inline" | "attachment" | disp-ext-type
# ; case-insensitive
# disp-ext-type = token
# disposition-parm = filename-parm | disp-ext-parm
# filename-parm = "filename" "=" value
# | "filename*" "=" ext-value
# disp-ext-parm = token "=" value
# | ext-token "=" ext-value
# ext-token = <the characters in token, followed by "*">
token = ''[-!#-/'*+./dA-Z^-z|~]+''
qdtext=''[]-~/t !#-[]''
mimeCharset=''[-!#-&+/dA-Z^-z]+''
language=''(?:[A-Za-z]{2,3}(?:-[A-Za-z]{3}(?:-[A-Za-z]{3}){,2})?|[A-Za-z]{4,8})(?:-[A-Za-z]{4})?(?:-(?:[A-Za-z]{2}|/d{3}))(?:-(?:[/dA-Za-z]{5,8}|/d[/dA-Za-z]{3}))*(?:-[/dA-WY-Za-wy-z](?:-[/dA-Za-z]{2,8})+)*(?:-[Xx](?:-[/dA-Za-z]{1,8})+)?|[Xx](?:-[/dA-Za-z]{1,8})+|[Ee][Nn]-[Gg][Bb]-[Oo][Ee][Dd]|[Ii]-[Aa][Mm][Ii]|[Ii]-[Bb][Nn][Nn]|[Ii]-[Dd][Ee][Ff][Aa][Uu][Ll][Tt]|[Ii]-[Ee][Nn][Oo][Cc][Hh][Ii][Aa][Nn]|[Ii]-[Hh][Aa][Kk]|[Ii]-[Kk][Ll][Ii][Nn][Gg][Oo][Nn]|[Ii]-[Ll][Uu][Xx]|[Ii]-[Mm][Ii][Nn][Gg][Oo]|[Ii]-[Nn][Aa][Vv][Aa][Jj][Oo]|[Ii]-[Pp][Ww][Nn]|[Ii]-[Tt][Aa][Oo]|[Ii]-[Tt][Aa][Yy]|[Ii]-[Tt][Ss][Uu]|[Ss][Gg][Nn]-[Bb][Ee]-[Ff][Rr]|[Ss][Gg][Nn]-[Bb][Ee]-[Nn][Ll]|[Ss][Gg][Nn]-[Cc][Hh]-[Dd][Ee]''
valueChars = ''(?:%[/dA-F][/dA-F]|[-!#$&+./dA-Z^-z|~])*''
dispositionParm = ''[Ff][Ii][Ll][Ee][Nn][Aa][Mm][Ee]/s*=/s*(?:({token})|"((?:{qdtext}|////[/t !-~])*)")|[Ff][Ii][Ll][Ee][Nn][Aa][Mm][Ee]/*/s*=/s*({mimeCharset})/'(?:{language})?/'({valueChars})|{token}/s*=/s*(?:{token}|"(?:{qdtext}|////[/t !-~])*")|{token}/*/s*=/s*{mimeCharset}/'(?:{language})?/'{valueChars}''.format(**locals())
try:
m = re.match(''(?:{token}/s*;/s*)?(?:{dispositionParm})(?:/s*;/s*(?:{dispositionParm}))*|{token}''.format(**locals()), result.headers[''Content-Disposition''])
except KeyError:
name = path.basename(urllib.unquote(urlparse(url).path))
else:
if not m:
name = path.basename(urllib.unquote(urlparse(url).path))
# Many user agent implementations predating this specification do not
# understand the "filename*" parameter. Therefore, when both "filename"
# and "filename*" are present in a single header field value, recipients
# SHOULD pick "filename*" and ignore "filename"
elif m.group(8) is not None:
name = urllib.unquote(m.group(8)).decode(m.group(7))
elif m.group(4) is not None:
name = urllib.unquote(m.group(4)).decode(m.group(3))
elif m.group(6) is not None:
name = re.sub(''////(.)'', ''/1'', m.group(6))
elif m.group(5) is not None:
name = m.group(5)
elif m.group(2) is not None:
name = re.sub(''////(.)'', ''/1'', m.group(2))
else:
name = m.group(1)
# Recipients MUST NOT be able to write into any location other than one to
# which they are specifically entitled
if name:
name = path.basename(name)
else:
name = path.basename(urllib.unquote(urlparse(url).path))
Estoy descargando un archivo con Mechanize y en los encabezados de respuesta hay una cadena:
Content-Disposition: attachment; filename=myfilename.txt
¿Hay una manera estándar rápida de obtener ese valor de nombre de archivo? Lo que tengo en mente ahora es esto:
filename = f[1][''Content-Disposition''].split(''; '')[1].replace(''filename='', '''')
Pero parece una solución rápida y rápida.
Primero obtenga el valor del encabezado usando mecanizar, luego analice el encabezado usando el módulo cgi incorporado.
Demostrar:
>>> import mechanize
>>> browser = mechanize.Browser()
>>> response = browser.open(''http://example.com/your/url'')
>>> info = response.info()
>>> header = info.getheader(''Content-Disposition'')
>>> header
''attachment; filename=myfilename.txt''
El valor del encabezado puede entonces analizarse:
>>> import cgi
>>> value, params = cgi.parse_header(header)
>>> value
''attachment''
>>> params
{''filename'': ''myfilename.txt''}
params
es un dict simple, así que params[''filename'']
es lo que necesita. No importa si el nombre del archivo está entre comillas o no.
Probaría algo como:
import re
filename = re.findall("filename=(/S+)", f[1][''Content-Disposition''])
Esto maneja las citas y la URL que se escapa en los nombres de archivo