从 url 派生协议
Derive protocol from url
我确实有一个 url 列表,例如 ["www.bol.com ","www.dopper.com"]
format。
为了在 scrappy 上作为起始 URL 输入,我需要知道正确的 HTTP 协议。
例如:
["https://www.bol.com/nl/nl/", "https://dopper.com/nl"]
如您所见,协议可能从 https
到 http
甚至有或没有 www.
都不同
不确定是否还有其他变化。
- 是否有任何 python 工具可以确定正确的协议?
- 如果没有,我必须自己构建逻辑,我应该考虑哪些情况?
对于选项 2,这是我目前所掌握的:
def identify_protocol(url):
try:
r = requests.get("https://" + url + "/", timeout=10)
return r.url, r.status_code
except requests.HTTPError:
r = requests.get("http//" + url + "/", timeout=10)
return r.url, r.status_code
except requests.HTTPError:
r = requests.get("https//" + url.replace("www.","") + "/", timeout=10)
return r.url, r.status_code
except:
return None, None
还有其他我应该考虑的可能性吗?
无法直接从片段中确定 protocol/full 域,信息根本不存在。为了找到它,您需要:
- 正确 protocol/domains 的数据库,您可以在其中查找您的域片段
- 发出请求并查看服务器告诉您的内容
如果您执行 (2),您当然可以逐步构建自己的数据库,以避免将来需要请求。
在许多 https 服务器上,如果您尝试使用 http 连接,您将被重定向到 https。如果不是,那么您可以可靠地使用 http.如果http失败了,你可以用https再试一下,看看能不能成功。
同样适用于域:如果站点通常重定向,您可以使用原始域执行请求并查看您被重定向到哪里。
使用 requests
的示例:
>>> import requests
>>> r = requests.get('http://bol.com')
>>> r
<Response [200]>
>>> r.url
'https://www.bol.com/nl/nl/'
如您所见,请求 对象url
参数具有最终目的地URL,加上协议。
据我了解,您需要在所有可能的重定向之后检索最终的 url。可以使用内置 urllib.request
. If provided url has no scheme you can use http
as default. To parse input url I used combination of urlsplit()
and urlunsplit()
.
来完成
代码:
import urllib.request as request
import urllib.parse as parse
def find_redirect_location(url, proxy=None):
parsed_url = parse.urlsplit(url.strip())
url = parse.urlunsplit((
parsed_url.scheme or "http",
parsed_url.netloc or parsed_url.path,
parsed_url.path.rstrip("/") + "/" if parsed_url.netloc else "/",
parsed_url.query,
parsed_url.fragment
))
if proxy:
handler = request.ProxyHandler(dict.fromkeys(("http", "https"), proxy))
opener = request.build_opener(handler, request.ProxyBasicAuthHandler())
else:
opener = request.build_opener()
with opener.open(url) as response:
return response.url
然后你可以在列表中的每个 url 上调用这个函数:
urls = ["bol.com ","www.dopper.com", "https://google.com"]
final_urls = list(map(find_redirect_location, urls))
您也可以使用代理:
from itertools import cycle
urls = ["bol.com ","www.dopper.com", "https://google.com"]
proxies = ["http://localhost:8888"]
final_urls = list(map(find_redirect_location, urls, cycle(proxies)))
为了加快速度,您可以使用 ThreadPoolExecutor
:
在并行线程中进行检查
from concurrent.futures import ThreadPoolExecutor
urls = ["bol.com ","www.dopper.com", "https://google.com"]
final_urls = list(ThreadPoolExecutor().map(find_redirect_location, urls))
我确实有一个 url 列表,例如 ["www.bol.com ","www.dopper.com"]
format。
为了在 scrappy 上作为起始 URL 输入,我需要知道正确的 HTTP 协议。
例如:
["https://www.bol.com/nl/nl/", "https://dopper.com/nl"]
如您所见,协议可能从 https
到 http
甚至有或没有 www.
不确定是否还有其他变化。
- 是否有任何 python 工具可以确定正确的协议?
- 如果没有,我必须自己构建逻辑,我应该考虑哪些情况?
对于选项 2,这是我目前所掌握的:
def identify_protocol(url):
try:
r = requests.get("https://" + url + "/", timeout=10)
return r.url, r.status_code
except requests.HTTPError:
r = requests.get("http//" + url + "/", timeout=10)
return r.url, r.status_code
except requests.HTTPError:
r = requests.get("https//" + url.replace("www.","") + "/", timeout=10)
return r.url, r.status_code
except:
return None, None
还有其他我应该考虑的可能性吗?
无法直接从片段中确定 protocol/full 域,信息根本不存在。为了找到它,您需要:
- 正确 protocol/domains 的数据库,您可以在其中查找您的域片段
- 发出请求并查看服务器告诉您的内容
如果您执行 (2),您当然可以逐步构建自己的数据库,以避免将来需要请求。
在许多 https 服务器上,如果您尝试使用 http 连接,您将被重定向到 https。如果不是,那么您可以可靠地使用 http.如果http失败了,你可以用https再试一下,看看能不能成功。
同样适用于域:如果站点通常重定向,您可以使用原始域执行请求并查看您被重定向到哪里。
使用 requests
的示例:
>>> import requests
>>> r = requests.get('http://bol.com')
>>> r
<Response [200]>
>>> r.url
'https://www.bol.com/nl/nl/'
如您所见,请求 对象url
参数具有最终目的地URL,加上协议。
据我了解,您需要在所有可能的重定向之后检索最终的 url。可以使用内置 urllib.request
. If provided url has no scheme you can use http
as default. To parse input url I used combination of urlsplit()
and urlunsplit()
.
代码:
import urllib.request as request
import urllib.parse as parse
def find_redirect_location(url, proxy=None):
parsed_url = parse.urlsplit(url.strip())
url = parse.urlunsplit((
parsed_url.scheme or "http",
parsed_url.netloc or parsed_url.path,
parsed_url.path.rstrip("/") + "/" if parsed_url.netloc else "/",
parsed_url.query,
parsed_url.fragment
))
if proxy:
handler = request.ProxyHandler(dict.fromkeys(("http", "https"), proxy))
opener = request.build_opener(handler, request.ProxyBasicAuthHandler())
else:
opener = request.build_opener()
with opener.open(url) as response:
return response.url
然后你可以在列表中的每个 url 上调用这个函数:
urls = ["bol.com ","www.dopper.com", "https://google.com"]
final_urls = list(map(find_redirect_location, urls))
您也可以使用代理:
from itertools import cycle
urls = ["bol.com ","www.dopper.com", "https://google.com"]
proxies = ["http://localhost:8888"]
final_urls = list(map(find_redirect_location, urls, cycle(proxies)))
为了加快速度,您可以使用 ThreadPoolExecutor
:
from concurrent.futures import ThreadPoolExecutor
urls = ["bol.com ","www.dopper.com", "https://google.com"]
final_urls = list(ThreadPoolExecutor().map(find_redirect_location, urls))