需求: 一台机器上有多个网卡, 如何访问指定的 URL 时使用指定的网卡发送数据呢?
阅读 urllib.py 的源码, 追述到 open_http �C> httplib.HTTP �C> httplib.HTTP._connection_class = HTTPConnection
HTTPConnection 在创建的时候会指定一个 source_address.
HTTPConnection.connect 时调用 HTTPConnection._create_connection = socket.create_connection
可以看到en0和en1, 这两块网卡都可以访问公网. lo0是本地回环.
直接修改 socket.py 做测试.
参考说明文档, 直接分三次绑定不通网卡的 IP 地址, 端口设置为0.
测试通过, 说明在多网卡情况下, 创建 socket 时绑定某块网卡的 IP 就可以, 端口需要设置为0. 如果端口不设置为0, 第二次请求时, 可以看到抛异常, 端口被占用.
如果是在项目中, 只需要把 socket.create_connection 这个函数的形参 source_address 设置为对应网卡的 (IP, 0) 就可以.
通过测试, 可以发现已经可以通过制定的网卡发送数据, 并且 IP 地址对应网卡分配的 IP.
问题, 爬虫经常使用 requests, requests 是否支持呢. 通过测试, 可以发现, requests 并没有使用 python 内置的 socket 模块.
看源码, requests 是如果创建的 socket 连接呢. 方法和查看 urllib 创建socket 的方式一样. 具体就不写了.
因为我用的是 python 2.7, 所以可以定位到 requests 使用的 socket 模块是 urllib3.utils.connection 的.
修改方法和 urllib 相差不大.
运行后, 可能会抛出异常. requests.exceptions.ConnectionError: Max retries exceeded with .. Invalid argument
这个异常不是每次出现, 跟 IP 段有关系, 跳转递归层数太多导致, 只需要将 kwargs 中的 socket_options去掉即可. 127.0.0.1肯定会出异常.
注意: 使用 urllib3.utils.connection 好像不起作用
稍微再完善一下, 就是把根据网卡名自动获取 IP.
只需要把 args[2] = SOURCE_ADDRESS 和 kwargs["source_address"] = SOURCE_ADDRESS改成 random_local_ip() 或者 get_local_ip("eth0")
至于有什么用途, 就全凭想象了.
以上这篇Python 使用指定的网卡发送HTTP请求的实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持脚本之家。