request.urlopen(url) 不是 return 网站响应或超时

request.urlopen(url) not return website response or timeout

我想为一个项目获取一些网站的资源。当我尝试获得响应时,程序只是卡住并等待响应。无论我等多久都没有超时或响应。这是我的代码:

link = "https://eu.mouser.com/"
linkResponse = urllib.request.urlopen(link)
readedResponse = linkResponse.readlines()
writer = open("html.txt", "w")
for line in readedResponse:
    writer.write(str(line))
    writer.write("\n")
writer.close()

当我尝试访问其他网站时,urlopen return 他们的回应。但是当我试图得到“eu.mouser.com”和“uk.farnell.com”而不是return他们的回应时。我将跳过他们的响应,甚至 urlopen 也不会 return 超时。那里有什么问题?还有其他方法可以获取网站的资源吗? (抱歉我的英语不好)

urllib.request.urlopen docs 声称

The optional timeout parameter specifies a timeout in seconds for blocking operations like the connection attempt (if not specified, the global default timeout setting will be used). This actually only works for HTTP, HTTPS and FTP connections.

没有解释如何找到所述默认值,我在直接提供 5(秒)作为 timeout

后设法引发超时
import urllib.request
url = "https://uk.farnell.com"
urllib.request.urlopen(url, timeout=5)

给予

socket.timeout: The read operation timed out

有些网站通过实施检测此类机器人的机制来保护自己免受自动爬虫的侵害。这些可能非常多样化,并且会随着时间而变化。如果您真的想竭尽所能让页面自动抓取,这通常意味着您必须自己实施步骤来规避这些保护性障碍。

其中一个例子是 header 随每个请求一起提供的信息。这可以在发出请求之前更改,例如通过 request's header customization。但是这里和那里可能还有更多的事情要做。

如果你有兴趣开始开发这样的东西(撇开这是否被允许的问题),你可以以此为起点:

from collections import namedtuple
from contextlib import suppress

import requests
from requests import ReadTimeout

Link = namedtuple("Link", ["url", "filename"])
links = {
    Link("https://eu.mouser.com/", "mouser.com"),
    Link("https://example.com/", "example1.com"),
    Link("https://example.com/", "example2.com"),
}

for link in links:
    with suppress(ReadTimeout):
        response = requests.get(link.url, timeout=3)
        with open(f"html-{link.filename}.txt", "w", encoding="utf-8") as file:
            file.write(response.text)

这种导致 ReadTimeOut 错误的受保护站点被简单地忽略并且有可能走得更远 - 例如通过使用合适的 headers 参数增强 requests.get(link.url, timeout=3)。但正如我已经提到的,这可能不是唯一必须完成的定制,法律方面也应该得到澄清。