Как правильно использовать win32inet.WinHttpGetProxyForUrl?
Вопрос
Я пытаюсь использовать функцию библиотеки Microsoft WinHttp, предоставленную разработчиками Win32com.К сожалению, большая часть библиотеки не документирована, и нет примеров правильного использования функций win32inet через библиотеку win32com.
Это то, что у меня есть до сих пор:
import win32inet
hinternet = win32inet.InternetOpen("foo 1.0", 0, "", "", 0)
# Does not work!!!
proxy = win32inet.WinHttpGetProxyForUrl( hinternet, u"http://www.foo.com", 0 )
Как видите, все, что я пытаюсь сделать, это использовать функцию win32inet, чтобы выяснить, какой прокси подходит для данного URL-адреса, в его случае foo.com.
Можете ли вы помочь мне исправить синтаксис последней строки?В MSN есть некоторые хорошая документация для оборачиваемой функции но аргументы, похоже, не идеально сопоставляются с аргументами библиотеки Python.
Исправленная версия этого скрипта должна:
Иметь возможность посмотреть, какой прокси использовать для любого данного URL.
Он всегда должен делать то же, что и Internet Explorer (т.используйте тот же прокси)
Он должен быть действительным для любой допустимой установки Windows XP.Это означает, что он должен работать с явно настроенным прокси-сервером, а также вообще без прокси.
Он должен работать только в 32-разрядной версии Windows XP с Python 2.4.4.Он может использовать любую официальную версию win32com.
Я использую Python2.4.4 с Win32Com в Windows XP.
ОБНОВЛЕНИЕ 0:
ИЛИ...Можете ли вы дать мне альтернативную реализацию в cTypes?Пока я могу заставить это работать, я счастлив!
Решение
Вот код, который создает сеанс HINTERNET и использует его для получения сведений о прокси-сервере, используя ctypes для прямого доступа к Winhttp DLL.Он работает без каких-либо ошибок, но на моем компьютере не установлен прокси-сервер, возможно, вам придется настроить несколько констант, чтобы все было правильно.Просмотрите ссылки msdn в коде, где я видел API.
import ctypes
import ctypes.wintypes
winHttp = ctypes.windll.LoadLibrary("Winhttp.dll")
# http://msdn.microsoft.com/en-us/library/aa384098(VS.85).aspx
# first get a handle to HTTP session
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY=0
WINHTTP_NO_PROXY_NAME=WINHTTP_NO_PROXY_BYPASS=0
WINHTTP_FLAG_ASYNC=0x10000000
HINTERNET = winHttp.WinHttpOpen("PyWin32", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, WINHTTP_FLAG_ASYNC)
print HINTERNET
# now get proxy using HTTP session
# http://msdn.microsoft.com/en-us/library/aa384097(VS.85).aspx
"""
BOOL WinHttpGetProxyForUrl(
__in HINTERNET hSession,
__in LPCWSTR lpcwszUrl,
__in WINHTTP_AUTOPROXY_OPTIONS *pAutoProxyOptions,
__out WINHTTP_PROXY_INFO *pProxyInfo
);
"""
# create C structure for WINHTTP_AUTOPROXY_OPTIONS
#http://msdn.microsoft.com/en-us/library/aa384123(VS.85).aspx
"""
typedef struct {
DWORD dwFlags;
DWORD dwAutoDetectFlags;
LPCWSTR lpszAutoConfigUrl;
LPVOID lpvReserved;
DWORD dwReserved;
BOOL fAutoLogonIfChallenged;
} WINHTTP_AUTOPROXY_OPTIONS;
"""
class WINHTTP_AUTOPROXY_OPTIONS(ctypes.Structure):
_fields_ = [("dwFlags", ctypes.wintypes.DWORD),
("dwAutoDetectFlags", ctypes.wintypes.DWORD),
("lpszAutoConfigUrl", ctypes.wintypes.LPCWSTR),
("lpvReserved", ctypes.c_void_p ),
("dwReserved", ctypes.wintypes.DWORD),
("fAutoLogonIfChallenged",ctypes.wintypes.BOOL),]
WINHTTP_AUTOPROXY_AUTO_DETECT = 0x00000001;
WINHTTP_AUTO_DETECT_TYPE_DHCP = 0x00000001;
WINHTTP_AUTO_DETECT_TYPE_DNS_A = 0x00000002;
options = WINHTTP_AUTOPROXY_OPTIONS()
options.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT
options.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DHCP|WINHTTP_AUTO_DETECT_TYPE_DNS_A
options.lpszAutoConfigUrl = 0
options.fAutoLogonIfChallenged = False
# create C structure for WINHTTP_AUTOPROXY_OPTIONS
# http://msdn.microsoft.com/en-us/library/aa383912(VS.85).aspx
"""
struct WINHTTP_PROXY_INFO {
DWORD dwAccessType;
LPWSTR lpszProxy;
LPWSTR lpszProxyBypass;
};
"""
class WINHTTP_PROXY_INFO(ctypes.Structure):
_fields_ = [("dwAccessType", ctypes.wintypes.DWORD),
("lpszProxy", ctypes.wintypes.LPCWSTR),
("lpszProxyBypass", ctypes.wintypes.LPCWSTR),]
info = WINHTTP_PROXY_INFO()
ret = winHttp.WinHttpGetProxyForUrl(HINTERNET, "http://www.google.com", ctypes.pointer(options), ctypes.pointer(info) )
print "proxy success?",ret
if not ret:
# some error lets see what is that?
import win32api
import win32con
errorCode = win32api.GetLastError()
print "win32 Error:",errorCode
s = ""
print win32api.FormatMessage(errorCode)
print info.dwAccessType, info.lpszProxy, info.lpszProxyBypass
Другие советы
Если нет веской причины для использования win32inet
(что в этой области беспорядочно из-за ограничений SWIG
), я рекомендую вам использовать ctypes
вместо.
По крайней мере с Python 2.7.6
и Pywin 218
в Windows XP x86 и Windows 8 x64 это работает:
import win32inet
# http://msdn.microsoft.com/en-us/library/windows/desktop/aa384098(v=vs.85).aspx
hinternet = win32inet.WinHttpOpen("foo", 0, "", "", 0)
# http://msdn.microsoft.com/en-us/library/windows/desktop/aa384123(v=vs.85).aspx
autoproxy_options = (2, 0, u"http://your-proxy-script-path", None, 0, 1)
# http://msdn.microsoft.com/en-us/library/windows/desktop/aa384097(v=vs.85).aspx
proxy = win32inet.WinHttpGetProxyForUrl(hinternet, u"http://www.google.com",
autoproxy_options)
print proxy
Стоит отметить, что в примере используется опция автопрокси WINHTTP_AUTOPROXY_CONFIG_URL для передачи явного URL-адреса.Вы можете использовать другие параметры, например, если вы хотите автоматически обнаружить с помощью DNS или DHCP, вы можете сделать:
autoproxy_options = (1, 1|2, u"", None, 0, 1)
Другие параметры вы можете найти по ссылке, указанной выше (в коде).