爬虫养成记 - 网络下载器urllib2伪装术

Onioncy 2019-06-21

前一个教程我们涉及到了urllib2的一些高级应用。这一片文章我们来比较系统的介绍一下。

该篇教程参考了静觅的博文:http://cuiqingcai.com/954.html
写这篇文章的目的仅仅是加深自己的印象。

Header

很多网站对我们用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()

Proxy(代理)设置

上面我们将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()

DELETE 和 PUT 函数

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()

相关推荐