代理服务器的设置
有时使用同一个IP去爬取同一个网站上的网页,久了之后会被该网站服务器屏蔽。那么怎么解决这个问题呢?
解决的方法很简单,就是使用代理服务器。
使用代理服务器去爬取某个网站的内容的时候,在对方的网站上,显示的不是我们真实的IP地址,而是代理服务器的IP地址。并且在Python爬虫中,使用代理服务器设置起来也很简单。
给大家推荐一个网址,http://www.xicidaili.com/,这上面有免费的代理Ip。
选择好代理ip地址后,我们就可以进行相应的程序编写了,可以使用以下程序,实现通过代理服务器来爬取网站内容。
def use_proxy(proxy_addr,url):
import urllib.request
proxy=urllib.request.ProxyHandler({'http':proxy_addr})
opener=urllib.request.build_opener(proxy,urllib.request.HTTPHandler)
urllib.request.install_opener(opener)
data=urllib.request.urlopen(url).read().decode('utf8')
return data
proxy_addr='61.163.39.70:9999'
data=use_proxy(proxy_addr,'http://www.baidu.com')
print(len(data))
我们首先建立一个名为use_proxy的自定义函数,该函数主要实现使用代理服务器来爬取某个URL网页的功能。
在函数中,我们设置两个形参,第一个形参为代理服务器的地址,第二个形参代表要爬取的网页的地址。
然后,使用urllib.request.ProxyHandler()来设置对应的代理服务器信息,设置格式为:urllib.request.ProxyHandler({‘http’:代理服务器地址}),接下来,使用urllib.request.build_opener()创建了一个自定义的opener对象,第一个参数为代理信息,第二个参数为urllib.request.HTTPHandler类。
为了方便,可以使用urllib.request.install_opener()创建全局默认的opener对象,那么,在使用urlopen()时亦会使用我们安装的opener对象,所以我们下面才可以直接使用urllib.request.urlopen()打开对应网址爬取网页并读取,编码后赋给变量data,最后返回data的值。
如果在使用代理服务器进行网站爬取时,出现相应异常,则需要考虑是否对应的代理IP失效了,如果是,换一个代理Ip即可。实际爬取的时候,可以准备多个代理IP,轮流进行爬取,若失效,则程序直接自动替换为其他代理ip地址,进行爬取。
Cookie的使用
在爬虫的使用中,如果涉及登录等操作,经常会使用到Cookie。
那什么是Cookie呢?
简单来说,我们访问每一个互联网页面,都是通过HTTP协议进行的,而HTTP协议是一个无状态协议,所谓的无状态协议即无法维持会话之间的状态。
比如,仅使用HTTP协议的话,我们登录一个网站的时候,假如登录成功了,但是当我们访问该网站的其他网页的时候,该登录与状态则会消失,此时还需要再登录一次,只要页面涉及更新,就需要反复的进行登录,这是非常不方便的。
所以此时,我们需要将对应的会话信息,比如登录成功等信息通过一些方式保存下来,比较常见的方式有两种:通过Cookie保存会话信息或通过Session保存会话信息。
不管是通过哪种方式进行会话控制,在大部分时候,都会用到Cookie。比如在爬虫的登录中,如果没有Cookie,我们登录成功了一个网页,但如果我们要爬取该网站的其他网页的时候,仍然会是未登录状态。如果有了Cookie,当我们登录成功后,爬取该网站的其他网页时,则会保持登录状态进行内容的爬取。
实战
我们拿ChinaUnix这个论坛网址就行实战测试一下吧,网址:http://bbs.chinaunix.net/。
我注册了一个帐号,进入网址,点击登录。我们会看到这样的界面:
按下F12,此时我们随便输入一个帐号和密码。查看network发生了哪些变化。
此时,我们找到了其中的一个POST请求,如图:
首先,我们能看到登录时提交表单数据的真实URL:http://bbs.chinaunix.net/member.php?mod=logging&action=login&loginsubmit=yes&loginhash=Lq8Qi
再往下拉,我们会看到提交的表单数据:
此时我们知道了,帐号的关键字是username,密码的关键字为password。
知道了这些,我们就可以开工了。
我们先测试一下不使用cookie登录成功后,再次访问别的界面会有什么效果:
代码如下:
import urllib.request
import urllib.parse
import urllib.error
import http.cookiejar
url='http://bbs.chinaunix.net/member.php?mod=logging&action=login&loginsubmit=yes&loginhash=LcHFP'
data={
'username':'fengxin88888',
'password':'mima',
}
postdata=urllib.parse.urlencode(data).encode('utf8')
#添加头部信息
header={
'User-Agent':'Mozilla/5.0 (X11; Fedora; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36',
'Referer':'http://bbs.chinaunix.net/member.php?mod=logging&action=login&logsubmit=yes'
}
request=urllib.request.Request(url,postdata,headers=header)
try:
reponse=urllib.request.urlopen(request)
except urllib.error.HTTPError as e:
print(e.code)
print(e.reason)
fhandle=open('./test.html','wb') #保存登录后的页面到文件
fhandle.write(reponse.read())
fhandle.close()
url2='http://bbs.chinaunix.net/forum-327-1.html' #再次访问该网站别的页面
reponse2=urllib.request.urlopen(url)
fhandle2=open('./test2.html','wb') #保存到文件中
fhandle2.write(reponse2.read())
fhandle2.close()
别盯着上面代码中的password看了,那个不是真实密码 ,嘿嘿。
此时,我们先在浏览器打开我们保存的test.html文件,我们会看到:
我们会发现,此时已经登录成功。我们再打开test2.html文件,看看是什么情况。
我们会发现,此时是没有登录的状态。
出现这样的情况,就是因为我们没有设置Cookie处理,而HTTP协议是一个无状态的协议,我们访问了新网页,自然会话信息会消失。
如果希望登录状态一直保持,则需要进行Cookie处理。
进行Cookie处理的一种常用思路如下:
- 导入Cookie处理模块http.cookiejar。
- 使用http.cookiejar.CookieJar()创建CookieJar对象。
- 使用HTTPCookieProcessor创建cookie处理器,并以其为参数构建opener对象。
- 创建全局默认的opener对象。
所以,以上代码可以改进为;
import urllib.request
import urllib.parse
import urllib.error
import http.cookiejar
url='http://bbs.chinaunix.net/member.php?mod=logging&action=login&loginsubmit=yes&loginhash=LcHFP'
data={
'username':'fengxin88888',
'password':'mima',
}
postdata=urllib.parse.urlencode(data).encode('utf8')
header={
'User-Agent':'Mozilla/5.0 (X11; Fedora; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36',
'Referer':'http://bbs.chinaunix.net/member.php?mod=logging&action=login&logsubmit=yes'
}
request=urllib.request.Request(url,postdata,headers=header)
#使用http.cookiejar.CookieJar()创建CookieJar对象
cjar=http.cookiejar.CookieJar()
#使用HTTPCookieProcessor创建cookie处理器,并以其为参数构建opener对象
cookie=urllib.request.HTTPCookieProcessor(cjar)
opener=urllib.request.build_opener(cookie)
#将opener安装为全局
urllib.request.install_opener(opener)
try:
reponse=urllib.request.urlopen(request)
except urllib.error.HTTPError as e:
print(e.code)
print(e.reason)
fhandle=open('./test.html','wb')
fhandle.write(reponse.read())
fhandle.close()
url2='http://bbs.chinaunix.net/forum-327-1.html'
reponse2=urllib.request.urlopen(url)
fhandle2=open('./test2.html','wb')
fhandle2.write(reponse2.read())
fhandle2.close()
运行完后,此时我们再打开test2.html文件,我们会发现此时会保持我们的登录信息,为已登录状态。
也就是说,对应的登录状态已经通过Cookie保存。