Onioncy 2019-06-21
前一个教程我们涉及到了urllib2
的一些高级应用。这一片文章我们来比较系统的介绍一下。
该篇教程参考了静觅的博文:http://cuiqingcai.com/954.html。
写这篇文章的目的仅仅是加深自己的印象。
很多网站对我们用urllib2发起的请求进行辨别,所以我们需要对我们的请求做一定的伪装。
我打开一个Chrome开发者工具的Network Tab。
查看一个Request Headers
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Accept-Encoding:gzip, deflate, sdch, br Accept-Language:zh-CN,zh;q=0.8,en;q=0.6,zh-TW;q=0.4 Cache-Control:max-age=0 Connection:keep-alive Cookie:__jsluid=237f8e30a392dd2dc08dda3c008b89bc; editor-code-detect-disabled=1; PHPSESSID=web1~1f6bt88ejrrdj2mgchjgfhi3c5; _gat=1; _ga=GA1.2.1502881944.1485175337; Hm_lvt_e23800c454aa573c0ccb16b52665ac26=1485175337,1485352359,1485352371; Hm_lpvt_e23800c454aa573c0ccb16b52665ac26=1485610162; sf_remember=f464bd79380df4d3c64702ba71d500f2 DNT:1 Host:segmentfault.com Referer:https://segmentfault.com/u/charliecharlie/articles Upgrade-Insecure-Requests:1 User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.95 Safari/537.36
Accept: 客户端可以响应的数据类型
Accept-Encoding: 客户端可以接受的编码类型
Accept-Language: 客户端可以允许的语言
Cache-Control: 如果制定了max-age=5,则访问过某一个连接5秒内,再访问则不会再请求服务器。
Connection: 如果指定keep-alive则客户端请求长链接。
Cookie: 指定Cookie
DNT: 即Do not Tack。 发送请求方不希望被跟踪。
Host: 即主机。在http 1.0的加强版和http 1.1中加入了Host行。用于区分同一个ip的不同域名。
Referer: 即该请求的来源
User-Agent: 即发出请求的用户信息。
Content-Type: 在使用REST接口的时候,服务器会检查该值。用来确定HTTP Body内容该如何解析。主要的值有 application/xml application/json application/x-www-form-urlencoded等
上面对于爬虫比较重要的有User-Agent、Referer。
User-Agent主要用来将Python urllib2伪装成一个正常的浏览器。
Referer主要用来应对有些网站的防盗链措施,给Referer指定一个网址,就是告诉服务器该请求来自域名内的某一个页面。
import urllib2 url = "http://www.baidu.com" headers = { "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.95 Safari/537.36", "Referer": "http://www.baidu.com" } request = urllib2.Request(url, headers=headers) response = urllib2.urlopen(request) print response.read()
上面我们将urllib2通过设置headers将自己伪装成一个正常的浏览器,但是如果我们频繁快速地访问某一个域名,那么服务器就会很快发现我们是一个爬虫,因为正常的一个用户不会如此频繁快速地访问一个网站。
那么,我们就得将自己伪装成好几个用户(IP). 这时候就需要用到代理。
urllib2 默认会使用环境变量 http_proxy 来设置 HTTP Proxy。
但是我们需要更加灵活的切换代理。我们用一个代理访问一段时间后,就需要切换到其他代理再访问。
我们可以给urllib2安装ProxyHandler。ProxyHandler需要传入一个字典。该字典:it must be a dictionary mapping protocol names to URLs of proxies.
. 就是说key是网络协议名称,value是代理的url。
例如:
proxies = { "http":"http://some_proxy.com:8080", "https":"https://some_proxy.com:8080" }
下面是一个示例代码,展示了如何使用ProxyHandler。
import urllib2 proxy_handler = urllib2.ProxyHandler(proxies={"http": "http://124.88.67.54:80"}) opener = urllib2.build_opener(proxy_handler) urllib2.install_opener(opener) response = urllib2.urlopen('http://www.baidu.com') print response.getcode()
http协议有六种请求方法,get,head,put,delete,post,options。
GET 客户端发送一个请求来获取服务器的资源。 服务器返回一组headers和呈现数据(html、图片资源等)给客户端。
HEAD 客户端发送一个请求来获取服务器资源等头信息。服务器只headers信息但是不返回呈现数据。主要的应用场景是用于判断某一个资源是否存在。
PUT 客户端请求新增一个资源。PUT与POST类似,但是表单不支持PUT。另外PUT一般会明确指定资源存放的位置。例如"http://www.myblog.com/articles/2100"。意思是将现在提交的数据存放于articles下第2100篇。由于表单不支持PUT
操作,很多框架则是在form表单中设置一个隐藏的input来标示该请求应该是PUT。<input type="hidden" name="_method" value="put" />
DELETE 请求删除某一个资源。
POST 向服务器提交数据。
OPTIONS 向服务器查询该链接支持哪些请求方法。
理论上urllib2只支持GET、POST方法。并不支持http的其他方法。通过源码可知,Request判断采用哪种请求方式是通过判断是否设置了data。
def get_method(self): if self.has_data(): return "POST" else: return "GET"
因此我们可以临时覆写request的get_method方法来更改请求方法。例如
request = urllib2.Request("http://www.baidu.com") request.get_method = lambda: "PUT" # 用匿名函数覆写request的get_method方法。 response = urllib2.urlopen(request) print response.info()