Python编程金典 pdf版(49M)
ÐèÇó: һ̨»úÆ÷ÉÏÓжà¸öÍø¿¨, ÈçºÎ·ÃÎÊÖ¸¶¨µÄ URL ʱʹÓÃÖ¸¶¨µÄÍø¿¨·¢ËÍÊý¾ÝÄØ?
$ curl --interface eth0 www.baidu.com # curl interface ¿ÉÒÔÖ¸¶¨Íø¿¨
ÔĶÁ urllib.py µÄÔ´Âë, ×·Êöµ½ open_http ¨C> httplib.HTTP ¨C> httplib.HTTP._connection_class = HTTPConnection
HTTPConnection ÔÚ´´½¨µÄʱºò»áÖ¸¶¨Ò»¸ö source_address.
HTTPConnection.connect ʱµ÷Óà HTTPConnection._create_connection = socket.create_connection
# ÏÈ¿´Ò»Ï±¾µØÍø¿¨ÐÅÏ¢ $ ifconfig lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384 options=3<RXCSUM,TXCSUM> inet6 ::1 prefixlen 128 inet 127.0.0.1 netmask 0xff000000 inet6 fe80::1%lo0 prefixlen 64 scopeid 0x1 nd6 options=1<PERFORMNUD> en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500 ether c8:e0:eb:17:3a:73 inet6 fe80::cae0:ebff:fe17:3a73%en0 prefixlen 64 scopeid 0x4 inet 192.168.20.2 netmask 0xffffff00 broadcast 192.168.20.255 nd6 options=1<PERFORMNUD> media: autoselect status: active en1: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500 options=4<VLAN_MTU> ether 0c:5b:8f:27:9a:64 inet6 fe80::e5b:8fff:fe27:9a64%en8 prefixlen 64 scopeid 0xa inet 192.168.8.100 netmask 0xffffff00 broadcast 192.168.8.255 nd6 options=1<PERFORMNUD> media: autoselect (100baseTX <full-duplex>) status: active
¿ÉÒÔ¿´µ½en0ºÍen1, ÕâÁ½¿éÍø¿¨¶¼¿ÉÒÔ·ÃÎʹ«Íø. lo0ÊDZ¾µØ»Ø»·.
Ö±½ÓÐÞ¸Ä socket.py ×ö²âÊÔ.
def create_connection(address, timeout=_GLOBAL_DEFAULT_TIMEOUT, source_address=None): """If *source_address* is set it must be a tuple of (host, port) for the socket to bind as a source address before making the connection. An host of '' or port 0 tells the OS to use the default. source_address Èç¹ûÉèÖÃ, ±ØÐëÊÇ´«µÝÔª×é (host, port), ĬÈÏÊÇ ("", 0) """ host, port = address err = None for res in getaddrinfo(host, port, 0, SOCK_STREAM): af, socktype, proto, canonname, sa = res sock = None try: sock = socket(af, socktype, proto) # sock.bind(("192.168.20.2", 0)) # en0 # sock.bind(("192.168.8.100", 0)) # en1 # sock.bind(("127.0.0.1", 0)) # lo0 if timeout is not _GLOBAL_DEFAULT_TIMEOUT: sock.settimeout(timeout) if source_address: print "socket bind source_address: %s" % source_address sock.bind(source_address) sock.connect(sa) return sock except error as _: err = _ if sock is not None: sock.close() if err is not None: raise err else: raise error("getaddrinfo returns an empty list")
²Î¿¼ËµÃ÷Îĵµ, Ö±½Ó·ÖÈý´Î°ó¶¨²»Í¨Íø¿¨µÄ IP µØÖ·, ¶Ë¿ÚÉèÖÃΪ0.
# ²âÊÔ en0 $ python -c 'import urllib as u;print u.urlopen("http://ip.haschek.at").read()' .148.245.16 # ²âÊÔ en1 $ python -c 'import urllib as u;print u.urlopen("http://ip.haschek.at").read()' .94.115.227 # ²âÊÔ lo0 $ python -c 'import urllib as u;print u.urlopen("http://ip.haschek.at").read()' Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib.py", line 87, in urlopen return opener.open(url) File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib.py", line 213, in open return getattr(self, name)(url) File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib.py", line 350, in open_http h.endheaders(data) File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/httplib.py", line 1049, in endheaders self._send_output(message_body) File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/httplib.py", line 893, in _send_output self.send(msg) File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/httplib.py", line 855, in send self.connect() File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/httplib.py", line 832, in connect self.timeout, self.source_address) File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py", line 578, in create_connection raise err IOError: [Errno socket error] [Errno 49] Can't assign requested address
²âÊÔͨ¹ý, ˵Ã÷ÔÚ¶àÍø¿¨Çé¿öÏÂ, ´´½¨ socket ʱ°ó¶¨Ä³¿éÍø¿¨µÄ IP ¾Í¿ÉÒÔ, ¶Ë¿ÚÐèÒªÉèÖÃΪ0. Èç¹û¶Ë¿Ú²»ÉèÖÃΪ0, µÚ¶þ´ÎÇëÇóʱ, ¿ÉÒÔ¿´µ½Å×Òì³£, ¶Ë¿Ú±»Õ¼ÓÃ.
Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib.py", line 87, in urlopen return opener.open(url) File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib.py", line 213, in open return getattr(self, name)(url) File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/urllib.py", line 350, in open_http h.endheaders(data) File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/httplib.py", line 1049, in endheaders self._send_output(message_body) File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/httplib.py", line 893, in _send_output self.send(msg) File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/httplib.py", line 855, in send self.connect() File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/httplib.py", line 832, in connect self.timeout, self.source_address) File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py", line 577, in create_connection raise err IOError: [Errno socket error] [Errno 48] Address already in use
Èç¹ûÊÇÔÚÏîÄ¿ÖÐ, Ö»ÐèÒª°Ñ socket.create_connection Õâ¸öº¯ÊýµÄÐβΠsource_address ÉèÖÃΪ¶ÔÓ¦Íø¿¨µÄ (IP, 0) ¾Í¿ÉÒÔ.
# test-interface_urllib.py import socket import urllib, urllib2 _create_socket = socket.create_connection SOURCE_ADDRESS = ("127.0.0.1", 0) #SOURCE_ADDRESS = ("172.28.153.121", 0) #SOURCE_ADDRESS = ("172.16.30.41", 0) def create_connection(*args, **kwargs): in_args = False if len(args) >=3: args = list(args) args[2] = SOURCE_ADDRESS args = tuple(args) in_args = True if not in_args: kwargs["source_address"] = SOURCE_ADDRESS print "args", args print "kwargs", str(kwargs) return _create_socket(*args, **kwargs) socket.create_connection = create_connection print urllib.urlopen("http://ip.haschek.at").read()
ͨ¹ý²âÊÔ, ¿ÉÒÔ·¢ÏÖÒѾ¿ÉÒÔͨ¹ýÖƶ¨µÄÍø¿¨·¢ËÍÊý¾Ý, ²¢ÇÒ IP µØÖ·¶ÔÓ¦Íø¿¨·ÖÅäµÄ IP.
ÎÊÌâ, ÅÀ³æ¾³£Ê¹Óà requests, requests ÊÇ·ñÖ§³ÖÄØ. ͨ¹ý²âÊÔ, ¿ÉÒÔ·¢ÏÖ, requests ²¢Ã»ÓÐʹÓà python ÄÚÖÃµÄ socket Ä£¿é.
¿´Ô´Âë, requests ÊÇÈç¹û´´½¨µÄ socket Á¬½ÓÄØ. ·½·¨ºÍ²é¿´ urllib ´´½¨socket µÄ·½Ê½Ò»Ñù. ¾ßÌå¾Í²»Ð´ÁË.
ÒòΪÎÒÓõÄÊÇ python 2.7, ËùÒÔ¿ÉÒÔ¶¨Î»µ½ requests ʹÓÃµÄ socket Ä£¿éÊÇ urllib3.utils.connection µÄ.
Ð޸ķ½·¨ºÍ urllib Ïà²î²»´ó.
import urllib3.connection _create_socket = urllib3.connection.connection.create_connection # pass urllib3.connection.connection.create_connection = create_connection # pass
ÔËÐкó, ¿ÉÄÜ»áÅ׳öÒì³£. requests.exceptions.ConnectionError: Max retries exceeded with .. Invalid argument
Õâ¸öÒì³£²»ÊÇÿ´Î³öÏÖ, ¸ú IP ¶ÎÓйØϵ, ÌøתµÝ¹é²ãÊýÌ«¶àµ¼ÖÂ, Ö»ÐèÒª½« kwargs ÖÐµÄ socket_optionsÈ¥µô¼´¿É. 127.0.0.1¿Ï¶¨»á³öÒì³£.
import socket import urllib import urllib2 import urllib3.connection import requests as req _default_create_socket = socket.create_connection _urllib3_create_socket = urllib3.connection.connection.create_connection SOURCE_ADDRESS = ("127.0.0.1", 0) #SOURCE_ADDRESS = ("172.28.153.121", 0) #SOURCE_ADDRESS = ("172.16.30.41", 0) def default_create_connection(*args, **kwargs): try: del kwargs["socket_options"] except: pass in_args = False if len(args) >=3: args = list(args) args[2] = SOURCE_ADDRESS args = tuple(args) in_args = True if not in_args: kwargs["source_address"] = SOURCE_ADDRESS print "args", args print "kwargs", str(kwargs) return _default_create_socket(*args, **kwargs) def urllib3_create_connection(*args, **kwargs): in_args = False if len(args) >=3: args = list(args) args[2] = SOURCE_ADDRESS in_args = True args = tuple(args) if not in_args: kwargs["source_address"] = SOURCE_ADDRESS print "args", args print "kwargs", str(kwargs) return _urllib3_create_socket(*args, **kwargs) socket.create_connection = default_create_connection # ÒòΪż¶û»á³öÎÊÌâ, ËùÒÔʹÓÃĬÈ쵀 socket.create_connection # urllib3.connection.connection.create_connection = urllib3_create_connection urllib3.connection.connection.create_connection = default_create_connection print " *** test requests: " + req.get("http://ip.haschek.at").content print " *** test urllib: " + urllib.urlopen("http://ip.haschek.at").read() print " *** test urllib2: " + urllib2.urlopen("http://ip.haschek.at").read()
×¢Òâ: ʹÓà urllib3.utils.connection ºÃÏñ²»Æð×÷ÓÃ
ÉÔ΢ÔÙÍêÉÆÒ»ÏÂ, ¾ÍÊǰѸù¾ÝÍø¿¨Ãû×Ô¶¯»ñÈ¡ IP.
import subprocess def get_all_net_devices(): sub = subprocess.Popen("ls /sys/class/net", shell=True, stdout=subprocess.PIPE) sub.wait() net_devices = sub.stdout.read().strip().splitlines() # ['eth0', 'eth1', 'lo'] # ÕâÀï¼òµ¥¹ýÂËÒ»ÏÂÍø¿¨Ãû×Ö, ¸ù¾ÝÐèÇó¸Ä¶¯ net_devices = [i for i in net_devices if "ppp" in i] return net_devices ALL_DEVICES = get_all_net_devices() def get_local_ip(device_name): sub = subprocess.Popen("/sbin/ifconfig en0 | grep '%s ' | awk '{print $2}'" % device_name, shell=True, stdout=subprocess.PIPE) sub.wait() ip = sub.stdout.read().strip() return ip def random_local_ip(): return get_local_ip(random.choice(ALL_DEVICES)) # code ...
Ö»ÐèÒª°Ñ args[2] = SOURCE_ADDRESS ºÍ kwargs["source_address"] = SOURCE_ADDRESS¸Ä³É random_local_ip() »òÕß get_local_ip("eth0")
ÖÁÓÚÓÐʲôÓÃ;, ¾ÍȫƾÏëÏóÁË.
ÒÔÉÏÕâƪPython ʹÓÃÖ¸¶¨µÄÍø¿¨·¢ËÍHTTPÇëÇóµÄʵÀý¾ÍÊÇС±à·ÖÏí¸ø´ó¼ÒµÄÈ«²¿ÄÚÈÝÁË£¬Ï£ÍûÄܸø´ó¼ÒÒ»¸ö²Î¿¼£¬Ò²Ï£Íû´ó¼Ò¶à¶àÖ§³Ö½Å±¾Ö®¼Ò¡£
转载请注明:谷谷点程序 » Python 使用指定的网卡发送HTTP请求的实例