urllib模块
在介绍关于防止反爬虫策略之前,先学习另一个爬虫方法。
在之前的文章中提到了最常用的爬虫方式就是调用requests模块,下面介绍另一个方法,就是调用urllib模块,然后利用里面的urlopen和read方法去获取网页信息。
下面以百度为例,利用urllib模块获取百度页面信息,具体代码如下:
"""
python3:
urllib
urllib.request
python2:
urllib
urllib2
"""
from urllib import request
from urllib import error
from urllib import parse
try:
url = 'http://www.baidu.com:80'
obj = parse.urlparse(url)
# print(obj)
response = request.urlopen(url)
print("访问的网站是: ", obj.netloc)
except error.HTTPError as e:
print(e.code, e.reason, e.headers)
except error.URLError as e:
print(e.reason)
else:
bytes_content = response.read()
print(type(bytes_content))
str_content = bytes_content.decode('utf-8')
print(type(str_content))
输出结果如下:
可见,read方法获取的页面内容为bytes类型,要转成字符串格式需要对其进行decode解码。
反爬虫
第一步:模拟浏览器(改变headers中的User-Agent)
通过模拟浏览器中的user-agent信息,可以实现防止反爬虫,让服务器认为是浏览器发出的请求,而不是python发出的,从而防止反爬虫。
首先要查看浏览器的user-agent信息:打开网页之后,然后按F12就可以查看网页信息,可以对网页进行分析。再点击上面的Network选项卡,刷新之后点击出现的第一个网址,就可以看到请求与响应信息。
如下图所示:
把这个信息复制到代码中:
"""
浏览器的模拟
应用场景:有些网页为了防止别人恶意采集其信息所以进行了一些反爬虫的设置,而我们又想进行爬取。
解决方法:设置一些Headers信息(User-Agent),模拟成浏览器去访问这些网站。
"""
from urllib import request
from urllib import error
from urllib import parse
try:
url = 'http://www.baidu.com:80'
obj = parse.urlparse(url)
headers = {
'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) '}
# 实例化请求对象, 修改请求的头部信息;
requestObj = request.Request(url, headers=headers)
# urlopen方法可以打开一个url地址, 也可以打开一个请求对象(一般为了修改请求头部)
response = request.urlopen(requestObj)
print("访问的网站是: ", obj.netloc)
except error.HTTPError as e:
print(e.code, e.reason, e.headers)
except error.URLError as e:
print(e.reason)
else:
bytes_content = response.read()
print(type(bytes_content))
str_content = bytes_content.decode('utf-8')
print(type(str_content))
# 请求对象拥有的方法:
# 相应对象拥有的方法:
# print(dir(requestObj))
# print(dir(response))
print("请求头部信息:", requestObj.headers)
print("响应头部信息: ", response.headers)
print("响应的状态码: ", response.code)
这样就模拟浏览器可以防止反爬虫,当然在调用requests模块爬虫时,在get方法中加入浏览器的user-agent信息也是一样的可以防止反爬虫。
第二步:设置代理IP
当我们使用同一个IP去爬取同一个网站上的网页时,久了之后会被该网站服务器屏蔽掉,这样是对我们很不利的。因此我们可以利用一些其他的代理IP去代替我们自己的IP,这样就算被屏蔽掉,在换一个IP就可以。在urllib中需要使用ProxyHandler类来创建新的代理,代码如下:
"""
代理服务器的设置
应用场景:使用同一个IP去爬取同一个网站上的网页,久了之后会被该网站服务器屏蔽。
解决方法:使用代理服务器。 (使用代理服务器去爬取某个网站的内容的时候,在对方的网站上,显示的不是我们真实的IP地址,而是代理服务器的IP地址)
"""
from urllib.request import ProxyHandler, build_opener, urlopen, install_opener
import random
proxyes = [
{'HTTPS': '163.204.247.157:9999'},
{'HTTP': '163.204.246.39:9999'},
{'HTTP': '163.204.243.135:9999'},
]
# url = 'http://www.baidu.com'
url = 'http://httpbin.org/get'
# 1. 调用类名创建IP代理的处理器
proxy_support = ProxyHandler(random.choice(proxyes))
# 2. build_opener === urlopen
opener = build_opener(proxy_support)
install_opener(opener)
# 3.打开url地址, 访问
response = opener.open(url)
print('>>>>>>')
content = response.read()
print(len(content))
print(content)
而利用requests模块爬取页面信息修改代理IP要简单很多,代码如下:
import requests
import random
proxies = [
{'http': '123.139.56.238:9999'},
{'http': '158.140.182.175:8080'}
]
headers = {
'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) '}
# url = 'http://www.baidu.com'
url = 'http://httpbin.org/get'
proxy = random.choice(proxies)
print(proxy)
response = requests.get(url, headers=headers, proxies=random.choice(proxies))
print(response.text)
print(response.headers)
通过上面的代码就利用设置代理IP实现了防止反爬虫。
当我们使用代理IP时,怎么才能知道该IP是否可用呢?下面的一小段代码就可以测试IP是否可用:
"""
测试代理IP是否可用?
"""
# -*- coding: utf-8 -*-
import telnetlib
print('------------------------connect---------------------------')
ip = '123.139.56.238'
try:
tn = telnetlib.Telnet(ip, port='9999', timeout=10)
except Exception as e:
print(e)
print('error')
else:
print('ok')
print('-------------------------end----------------------------')
运行结果如下:
说明该IP是可以使用的。