一 浏览网页是所要经历的过程
-
浏览器 (请求request)-> 输入URL地址(http://www.baidu.com/index.html file:///mnt ftp://172.25.254.250/pub …)
-
http协议确定, www.baidu.com访问的域名确定 -> DNS服务器解析到IP地址
-
确定要访问的网页内容 -> 将获取到的页面内容返回给浏览器(响应过程)
二 爬取网页
- 基本方法:
使用 urllib.request 中的 urlopen 去爬取
from urllib import request
respose = request.urlopen('http://www.baidu.com')
content = respose.read().decode('utf-8')
print(content)
执行结果:
- 使用Resuest对象(可以添加其他的头部信息)
from urllib import request
url = 'http://www.cbrc.gov.cn/chinese/jrjg/index.html'
headers = {'User-Agent':' Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Firefox/45.0'}
# 实例化request对象, 可以自定义请求的头部信息;
req = request.Request(url, headers=headers)
# urlopen不仅可以传递url地址, 也可以传递request对象;
content = request.urlopen(req).read().decode('utf-8')
print(content)
执行结果:
# 也可以后续添加信息
from urllib import request
url = 'http://www.cbrc.gov.cn/chinese/jrjg/index.html'
user_agent = 'Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Firefox/45.0'
# 实例化request对象, 可以自定义请求的头部信息;
req = request.Request(url)
req.add_header('User-Agent',user_agent)
# urlopen不仅可以传递url地址, 也可以传递request对象;
content = request.urlopen(req).read().decode('utf-8')
print(content)
执行结果:
- 反爬虫策略
1). 伪装浏览器
前面提到过,如果一些网站做了反爬虫策略,是禁止脚本进行访问的,但是浏览器却是可以的,因此这里要做的就是伪装成浏览器进行访问
那么,先来看看浏览器是如何进行访问的
可以看到 liunx 系统在访问的时候的信息,其中有一项很重要的就是 User-Agent ,表明了访问时的身份
下面是一些浏览器在访问时的信息:
1.Android
Mozilla/5.0 (Linux; Android 4.1.1; Nexus 7 Build/JRO03D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Safari/535.19
Mozilla/5.0 (Linux; U; Android 4.0.4; en-gb; GT-I9300 Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30
Mozilla/5.0 (Linux; U; Android 2.2; en-gb; GT-P1000 Build/FROYO) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1
2.Firefox
Mozilla/5.0 (Windows NT 6.2; WOW64; rv:21.0) Gecko/20100101 Firefox/21.0
Mozilla/5.0 (Android; Mobile; rv:14.0) Gecko/14.0 Firefox/14.0
3.Google Chrome
Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.94 Safari/537.36
Mozilla/5.0 (Linux; Android 4.0.4; Galaxy Nexus Build/IMM76B) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.133 Mobile Safari/535.19
4.iOS
Mozilla/5.0 (iPad; CPU OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A334 Safari/7534.48.3
2). 代理IP
当抓取网站时, 程序的运行速度很快, 如果通过爬虫去访问, 一个固定的ip访问频率很高,网站如果做反爬虫策略, 那么就会封掉ip
(1)如何解决此问题呢?
1> 可以设置延迟
time.sleep(random.randint(1,5))
但是这样就违背了爬虫的原则
2> 就是使用代理IP
让其它的IP代替你去访问
(2)如何获取代理IP呢?
这里推荐一个西刺代理(http://www.xicidaili.com/),当然百度搜索也是可以的
(3)如何实现步骤?
1> 调用urllib.request.ProxyHandler(proxies=None); — 类似理解为Request对象
2> 调用Opener— 类似与urlopen, 这个是定制的
3> 安装Opener
4> 代理IP的选择
from urllib import request
url = 'https://www.whatismyip.com/'
# url = 'https://httpbin.org/get'
proxy = {'https':'171.221.239.11:808', 'http':'218.14.115.211:3128'}
user_agent = 'Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Firefox/45.0'
# 1).调用urllib.request.ProxyHandler(proxies=None); --- 类似理解为Request对象
proxy_support = request.ProxyHandler(proxy)
# 2).调用Opener - -- 类似与urlopen, 这个是定制的
opener = request.build_opener(proxy_support)
# 伪装浏览器
opener.addheaders = [('User-Agent',user_agent)]
# 3).安装Opener
request.install_opener(opener)
# 4).代理IP的选择
response = request.urlopen(url)
content = response.read().decode('utf-8')
print(content)
执行结果:
上面可以看到访问的网页为:(https://www.whatismyip.com/)
之所以选择这个,是因为这个网页正如其名那样,可以直接看到你的访问IP是多少
可以看到正是代理IP
三 cookie信息
- cookie信息是什么
cookie:某些网站为了辨别用户身份, 只有登陆之后才能访问某个页面;
进行一个会话跟踪, 将用户的相关信息包括用户名等保存到本地终端
比如:CSDN在登陆后就保存有cookie信息
具体的内容:
BAIDUID=16C759B4BFCD1D2F65C8144247B56307:FG=1;
BIDUPSID=16C759B4BFCD1D2F65C8144247B56307;
PSTM=1531714425;
MCITY=-233%3A;
BDORZ=B490B5EBF6F3CD402E515D22BCDA1598;
pgv_pvi=2556628992; delPer=0;
H_PS_PSSID=22778_1446_21105_18560_26350_20927;
PSINO=1; pgv_si=s9417027584
- 如何查看cookie信息
from urllib.request import HTTPCookieProcessor
from urllib import request
from http import cookiejar
# 如何读取cookie信息
# 1). 声明一个CookieJar
cookie=cookiejar.CookieJar()
# 2). 利用urllib.request里面的HTTPCookieProcessor创建一个cookie处理器
handler=HTTPCookieProcessor(cookie)
# 3). 通过CookieHandler创建opener
opener=request.build_opener(handler)
# 4). 打开url页面
response=opener.open('https://www.csdn.net/')
# response=opener.open('https://www.baidu.com/')
# 5). 打印该页面的cookie信息
print(cookie)
for item in cookie:
print(item)
执行结果:
- 如何将cookie保存到文件中
# 如何将cookie保存到文件中
# 1). 设置保存cookie的文件名
cookiefilename='cookie.txt'
# 2). 声明一个MozillaCookie,用来保存cookie信息并写入
cookie=cookiejar.MozillaCookieJar()
# 3). 利用urllib.request里面的HTTPCookieProcessor创建一个cookie处理器
handler=HTTPCookieProcessor(cookie)
# 4). 通过CookieHandler创建opener
opener=request.build_opener(handler)
# 5). 打开url页面
response=opener.open('https://www.csdn.net/')
# response=opener.open('https://www.baidu.com/')
# 6). 打印该页面的cookie信息
print(cookie)
cookie.save(cookiefilename,ignore_discard=True,ignore_expires=True)
执行结果:
文件中的具体内容:
# Netscape HTTP Cookie File
# http://curl.haxx.se/rfc/cookie_spec.html
# This is a generated file! Do not edit.
.csdn.net TRUE / FALSE 1735689600 dc_session_id 10_1539760133007.977319
.csdn.net TRUE / FALSE 1855120121 uuid_tt_dd 5423497709313904182_20181017
- 如何从文件中读取cookie,并访问
# 如何从文件中读取cookie,并访问
# 1). 指定cookie文件地址
cookiefilename='cookie.txt'
# 2). 声明一个MozillaCookie,用来读取cookie信息
cookie=cookiejar.MozillaCookieJar()
# 3). 读取cookie信息
cookie.load(filename=cookiefilename)
# 4). 利用urllib.request里面的HTTPCookieProcessor创建一个cookie处理器
handler=HTTPCookieProcessor(cookie)
# 5). 通过CookieHandler创建opener
opener=request.build_opener(handler)
# 6). 打开url页面
response=opener.open('https://www.csdn.net/')
# 7). 打印信息
print(response.read().decode('utf-8'))
执行结果:
这样就可以在下次访问的时候直接通过读取cookie信息进行访问
四 urllib常见异常处理
常见的异常:(URLError、HTTPError、ContentTooShortError…)
如果这时不确定是否会爬取成功时,不妨先用 try 作异常处理
from urllib import request, error
try:
url = 'https://www.baidu.com/hello.html'
response = request.urlopen(url)
print(response.read().decode('utf-8'))
except error.HTTPError as e:
print(e.reason, e.code, e.headers, sep='\n')
except error.URLError as e:
print(e.reason)
else:
print("成功")
执行结果:
超时异常处理:
from urllib import request, error
import socket
#
try:
url = 'https://www.baidu.com'
response = request.urlopen(url, timeout=0.01)
print(response.read().decode('utf-8'))
except error.HTTPError as e:
print(e.reason, e.code, e.headers, sep='\n')
except error.URLError as e:
print(e.reason)
if isinstance(e.reason, socket.timeout):
print("超时")
else:
print("成功")
执行结果:
五 url解析
- 在 urllib.parse 中有一个 urlparse 可以将url进行分解
网址的解析:
from urllib.parse import urlparse
url='http://www.google.com/search?hl=en&q=urlparse&btnG=Google+Search'
parse_info=urlparse(url)
print(parse_info)
print(parse_info.netloc)
print(parse_info.path)
执行结果:
- 在 urllib.parse 中同样有一个 urlencode 可以将url进行组合
网址的组合:
from urllib.parse import urlencode
params={
'name':'westos',
'age':20
}
base_url='https://www.baidu.com'
url=base_url + urlencode(params)
print(url)
执行结果:
- 应用
要求:
获取网页的协议与网址,并按一定要求构成新的网址
from urllib.parse import urlparse, urlencode
url1='https://movie.douban.com/subject/4864908/comments?start=20&limit=20&sort=new_score&status=P'
parse_news=urlparse(url1)
print(parse_news.scheme)
print(parse_news.netloc)
params2={
'start':20,
'limit':20,
'sort':'new_score',
'status':'P'
}
base_url2='https://movie.douban.com/subject/4864908/comments'
url2=base_url2 + urlencode(params2)
print(url2)
执行结果: