外观
爬虫
Python提供了很多爬取网页的模块,如Python自带的urllib模块和urllib升级版的urllib3。除此外,还有requests模块和Scrapy模块也可以爬取网页。这里简要介绍一下requests模块。
requests模块基础
requests模块是由一位民间大神开发出来的一个极为强大的爬虫模块,使用此模块之前要先安装它。
使用requests模块爬取网页非常简单,只需要导入模块,然后再向服务器中发送get或post请求,然后处理响应即可。
例:
import requests
response = requests.get('https://www.baidu.com')
print(response.content.decode('utf8'))运行结果:
<!DOCTYPE html>
<!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/bdorz/baidu.min.css><title>百度一下,你就知道</title></head> <body link=#0000cc> <div id=wrapper> <div id=head> <div class=head_wrapper> <div class=s_form> <div class=s_form_wrapper> <div id=lg> <img hidefocus=true src=//www.baidu.com/img/bd_logo1.png width=270 height=129> </div> <form id=form name=f action=//www.baidu.com/s class=fm> <input type=hidden name=bdorz_come value=1> <input type=hidden name=ie value=utf-8> <input type=hidden name=f value=8> <input type=hidden name=rsv_bp value=1> <input type=hidden name=rsv_idx value=1> <input type=hidden name=tn value=baidu><span class="bg s_ipt_wr"><input id=kw name=wd class=s_ipt value maxlength=255 autocomplete=off autofocus=autofocus></span><span class="bg s_btn_wr"><input type=submit id=su value=百度一下 class="bg s_btn" autofocus></span> </form> </div> </div> <div id=u1> <a href=http://news.baidu.com name=tj_trnews class=mnav>新闻</a> <a href=https://www.hao123.com name=tj_trhao123 class=mnav>hao123</a> <a href=http://map.baidu.com name=tj_trmap class=mnav>地图</a> <a href=http://v.baidu.com name=tj_trvideo class=mnav>视频</a> <a href=http://tieba.baidu.com name=tj_trtieba class=mnav>贴吧</a> <noscript> <a href=http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2f%3fbdorz_come%3d1 name=tj_login class=lb>登录</a> </noscript> <script>document.write('<a href="http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u='+ encodeURIComponent(window.location.href+ (window.location.search === "" ? "?" : "&")+ "bdorz_come=1")+ '" name="tj_login" class="lb">登录</a>');
</script> <a href=//www.baidu.com/more/ name=tj_briicon class=bri style="display: block;">更多产品</a> </div> </div> </div> <div id=ftCon> <div id=ftConw> <p id=lh> <a href=http://home.baidu.com>关于百度</a> <a href=http://ir.baidu.com>About Baidu</a> </p> <p id=cp>©2017 Baidu <a href=http://www.baidu.com/duty/>使用百度前必读</a> <a href=http://jianyi.baidu.com/ class=cp-feedback>意见反馈</a> 京ICP证030173号 <img src=//www.baidu.com/img/gs.gif> </p> </div> </div> </div> </body> </html>设置头部信息
如在爬取网页的时候返回的响应为403,就代表网页设置了访问机制,拒绝爬虫发送的请求立了,这种情况我们可以通过设置头部信息模拟该请求是由浏览器发出的而不是由爬虫发出的,网页就可以返回正常响应了。
例:
import requests
url = 'https://movie.douban.com'
response = requests.get(url)
print(response.content)
# 创建头部信息
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.5112.102 Safari/537.36 Edg/104.0.1293.70'}
response = requests.get(url, headers=headers)
print(response.content.decode('utf8'))由于运行成功,但返回的HTML代码过长,因此这里不写结果。
设置代理
代理服务在爬取被屏蔽的网站时确实是一个解决方案。通常,你可以通过使用代理服务器来隐藏你的真实 IP 地址,从而避免被服务器屏蔽。
要使用代理服务,你需要首先获取代理服务器的 IP 地址和端口号。例如,如果代理服务器的 IP 地址是 122.114.31.177,端口号是 808,那么完整的代理地址可能是 http://122.114.31.177:808 或 https://122.114.31.177:808。
在使用代理服务时,需要格外注意代理 IP 的有效性。如果代理 IP 过时或失效,可能会导致爬取失败。因此,最好在使用代理服务时添加异常处理机制,以便及时处理代理 IP 失效的情况。
例:
import requests
proxy = {
'http': 'http://http://61.154.21.249:16824',
'https': 'https://https://61.154.21.249:16824'}
response = requests.get('https://www.baidu.com/', proxies=proxy)
print(response.content.decode('utf8'))
# 查找免费代理ip的步骤这里不再详述了设置超时时间
若爬虫爬取时间过长不想再等待就可以设置超时。
例:
# 网络超时
import requests
time = 0.05 # 设置超时时间为0.05秒 具体要依据网页的大小和网速合理调整
url = 'https://www.baidu.com'
for i in range(0, 50):
try:
response = requests.get(url, timeout=time)
print('第%s次尝试: %s' % (i, response.status_code))
except Exception as e:
print('发生超时: ', str(e))
# 另外 requests模块还提供了以下三个常用异常类
from requests import ReadTimeout, HTTPError, requestsException
try:
pass
except ReadTimeout: # 超时异常
pass
except HTTPError: # HTTP 异常
pass
except requestsException: # 请求异常
pass运行结果:
发生超时: HTTPSConnectionPool(host='www.baidu.com', port=443): Read timed out. (read timeout=0.05)
第1次尝试: 200
发生超时: HTTPSConnectionPool(host='www.baidu.com', port=443): Read timed out. (read timeout=0.05)
发生超时: HTTPSConnectionPool(host='www.baidu.com', port=443): Read timed out. (read timeout=0.05)
发生超时: HTTPSConnectionPool(host='www.baidu.com', port=443): Read timed out. (read timeout=0.05)
第5次尝试: 200
发生超时: HTTPSConnectionPool(host='www.baidu.com', port=443): Read timed out. (read timeout=0.05)
发生超时: HTTPSConnectionPool(host='www.baidu.com', port=443): Read timed out. (read timeout=0.05)
第8次尝试: 200
第9次尝试: 200
发生超时: HTTPSConnectionPool(host='www.baidu.com', port=443): Read timed out. (read timeout=0.05)
第11次尝试: 200
第12次尝试: 200
第13次尝试: 200
第14次尝试: 200
发生超时: HTTPSConnectionPool(host='www.baidu.com', port=443): Read timed out. (read timeout=0.05)
发生超时: HTTPSConnectionPool(host='www.baidu.com', port=443): Read timed out. (read timeout=0.05)
发生超时: HTTPSConnectionPool(host='www.baidu.com', port=443): Read timed out. (read timeout=0.05)
第18次尝试: 200
第19次尝试: 200
发生超时: HTTPSConnectionPool(host='www.baidu.com', port=443): Read timed out. (read timeout=0.05)
第21次尝试: 200
第22次尝试: 200
发生超时: HTTPSConnectionPool(host='www.baidu.com', port=443): Read timed out. (read timeout=0.05)
发生超时: HTTPSConnectionPool(host='www.baidu.com', port=443): Read timed out. (read timeout=0.05)
发生超时: HTTPSConnectionPool(host='www.baidu.com', port=443): Read timed out. (read timeout=0.05)
发生超时: HTTPSConnectionPool(host='www.baidu.com', port=443): Read timed out. (read timeout=0.05)
第27次尝试: 200
发生超时: HTTPSConnectionPool(host='www.baidu.com', port=443): Read timed out. (read timeout=0.05)
...