-1

我确实有一个 URL 列表,例如["www.bol.com ","www.dopper.com"]格式。为了在 scrappy 上作为起始 URL 输入,我需要知道正确的 HTTP 协议。

例如:

["https://www.bol.com/nl/nl/", "https://dopper.com/nl"]

如您所见,协议可能会有所不同,https甚至http有或没有www.

不确定是否有任何其他变化。

  1. 有没有可以确定正确协议的python工具?
  2. 如果不是,我必须自己构建逻辑,我应该考虑哪些情况?

对于选项 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

还有其他我应该考虑的可能性吗?

4

2 回答 2

2

无法直接从片段中确定协议/完整域,信息根本不存在。为了找到它,您需要:

  1. 正确协议/域的数据库,您可以在其中查找域片段
  2. 发出请求,看看服务器告诉你什么

如果您这样做(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 以及协议。

于 2021-10-08T10:06:58.143 回答
1

据我了解的问题,您需要在所有可能的重定向之后检索最终 url。它可以通过内置的urllib.request. 如果提供的 url 没有方案,您可以将http其用作默认值。为了解析输入 url,我使用了urlsplit()和的组合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))
于 2021-10-08T11:45:12.433 回答