python有一些现成的类可以供网络文件的读取。比如urllib,urllib2以及httplib都可以。
urllib在网络文件读取方面功能较少,无法修改http头,无法设置timeout,也无法进行proxy认证。urllib类里面可以使用的是对url字符串的处理函数,比如说生成url字符串,对url串的字符进行转义处理等等。
urllib2提供的功能比较强大,除了支持http以及https协议的访问之外,还提供修改http头,设置超时时间,以及proxy认证,基本认证等功能,提供自动获取重定向网页的功能,自动处理cookies的功能。
httplib可以提供http协议的文件访问,但是需要对http协议熟悉才能够处理好。
所以这里主要介绍urllib2的使用。
17.1 获取网络文件
urllib2使用urlopen()方法来获取一个网络文件。urlopen的常用参数有三个,一个是url字符串或者是一个Request对象;第二个是data参数,如果使用了data参数,那么urlopen将用post方法来提交这个请求;第三个是timeout参数,是超时参数。
Request对象可以自定义网络请求的参数,如果需要修改http头,那么就必须要是用Request对象来请求。Request对象的常用参数也有三个,一个是url字符串;第二个是data参数,如果request对象设置了data参数,那么之后的urlopen方法就不需要设置data参数了;header参数是一个字典,用来修改http的请求头。
现在很多的网站服务器经常会根据http头的User-Agent域来判断请求的浏览器,根据Referer域来判断从哪个页面过来的请求。如果发现这两个域的值和预期不一致,那么这个请求就有可能被屏蔽掉,因此想要通过python代码来访问网页,通常都得对http头进行修改。这些域都可以通过chrome浏览器的开发者工具进行抓包查看。一个常用的模拟浏览器进行网页抓取的http头字典可能是下面这个样子的。
httpheaders=dict()httpheaders["Connection"]="keep-alive"httpheaders["User-Agent"]="Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36"httpheaders["Accept"]="*/*"httpheaders["Accept-Language"]="zh-CN,zh;q=0.8"
设置好了http头之后,进行网络文件访问了,一个完整的代码可能如下。
这段代码定义了一个url字符串,这里一定要使用http://头,因为urllib2还支持ftp协议以及文件的获取。
然后实例化一个Request对象,使用之前定义的http头。
接着使用urlopen方法获取这个网络文件,超市时间为15秒。
这段代码需要放到try...except...语句当中,这样才可以捕捉到各种网络错误。
使用了urlopen获取到文件之后,就可以使用f.read()方法进行文件内容的读取;
使用f.info()方法获取到返回的http头;
使用f.getcode()方法获取到http的返回码;
使用f.geturl()来获取到重定向的url。
这些操作完成了再使用f.close()来关闭这个网络文件的句柄。
常用的返回http头可以是读取服务器返回的cookies,或者是网页的类型和字符编码
f.info()['Set-Cookie']f.info()['Content-Type']
以上Set-Cookie是服务器返回的cookies,而Content-Type则包含了网页类型和字符编码。
如果在请求网络文件的时候带上cookie,那么可以在http头字典中添加cookie域。可以和上面一样直接设置httpheaders这个dict,也可以通过Request的add_header方法来设置。比如说。
其中第一项为header的域Cookie,而第二项为值。
17.2 使用代理
使用代理可以在一定程度上避免ip被封杀的情况。如果使用的代理是免密的,那么可以在urllib2的opener中添加一个ProxyHandler,示例代码为
proxy_handler = urllib2.ProxyHandler({'http': 'http://121.31.103.172:8123'})opener = urllib2.build_opener(proxy_handler)urllib2.install_opener(opener)
以上代码实例化了一个ProxyHandler的对象,这个对象可为http协议提供代理,代理的地址带着http://头以及代理的ip地址和端口。接着把这个handler包装成一个opener并且把它安装成默认的打开器。
接下来访问网页文件的代码和前面的一样了。
如果代理是带域名和密码的,那么就需要再添加一个ProxyBasicAuthHandler了。示例代码为
proxy_handler = urllib2.ProxyHandler({'http': 'http://121.31.103.172:8123'})proxy_auth_handler = urllib2.ProxyBasicAuthHandler()proxy_auth_handler.add_password('realm', 'host', 'username', 'password')opener = urllib2.build_opener(proxy_handler,proxy_auth_handler)urllib2.install_opener(opener)
接下来的访问网页文件的代码也和前面一样。
17.3 使用urllib处理url字符串
url的字符只能够是ascii字符,有一些字符比如说+ 空格 ?等等在url字符串中有另外的含义。比如说+号表示的是空格,/分隔目录,?分隔url和参数,%跟特殊字符,#表示书签,&是参数分隔,=是参数赋值。这些符号如果直接出现在url中,就不会表示它的字面意思。
如果想要它们表示其字面意思,就需要进行转义,变成%hh格式的字符串。其中h是一个十六进制的数。而hh就是这个字符的ascii序号。这样就把一个字符拆成三个字符来表示了。
使用quote()方法可以进行这样的转义。如果quote中指定了safe关键字参数,那么safe字符串中包含的字符不会进行转换,默认的safe字符串是'/'。
>>> urllib.quote('+ /?%#&=')'%2B%20/%3F%25%23%26%3D'>>> urllib.quote('+ /?%#&=',safe='&#')'%2B%20%2F%3F%25#&%3D'
如果使用quote_plus()方法,那么空格会自动转义成 '+'
>>> urllib.quote_plus('+ /?%#&=')'%2B+%2F%3F%25%23%26%3D'
quote和quote_plus有对称的方法。使用unquote以及unquote_plus,会把%hh类型的字符转义回来。
在请求网络文件的时候,经常需要在url后面带上很长的参数,格式类似于a=1&b=2&c=3。如果参数很长的话,一行代码都加不完。此时可以先把参数存在一个字典里面,然后使用urlencode快速地把这个字典转化为url的形式。示例代码如下:
>>> d={'a':'1','b':'2','c':'3'}>>> urllib.urlencode(d)'a=1&c=3&b=2'
领取专属 10元无门槛券
私享最新 技术干货