反爬虫:就是使用任何技术手段阻止批量获取网站信息的方式;其实咱们作的就是了解反爬虫的技术,继而反反爬虫。python
(1)不返回网页;web
(2)返回非目标网页,如返回错误页、空白页、同一页;
(3)增长获取难度,如登陆及验证码、12306登录选图片;浏览器
(1) 修改请求头
若是不修改请求头,网页默认为python-requests/xxx,因此须要修改;也能够作一个User-Agen 的池,但针对User-Agen的访问量进行封锁的很少,通常设置为正常的浏览器的user-Agen就行了。安全
# encoding:utf-8 import requests; link='http://www.santostang.com/'; r=requests.get(link); print (r.request.headers); headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'}; r=requests.get(link,headers=headers); print (r.request.headers);
headers,修改先后对比:服务器
(2)修改爬虫的间隔时间网络
t1=time.time(); print ('t1: ',t1); time.sleep(2); t2=time.time(); print ('t2: ',t2); t=t2-t1; print ('t2-t1: ',t);
加入间隔时间:
session
t1=time.time(); print ('t1: ',t1); sleep_time=random.randint(0,2)+random.random(); time.sleep(sleep_time); t2=time.time(); print ('t2: ',t2); print (sleep_time);
运行两次,两次sleep时间不同,如图dom
# encoding:utf-8 import requests; from bs4 import BeautifulSoup; import time,random; def scarp_url(link): headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'}; r=requests.get(link,headers=headers); soup=BeautifulSoup(r.text); return soup; link='http://www.santostang.com/';#主网页 soup=scarp_url(link); post_titles=soup.find_all('h1',class_='post-title'); for each in post_titles: title_link=each.a['href'];#进入到具体的博客文章中 print ("休息一下"); sleep_time=random.randint(0,2)+random.random(); time.sleep(sleep_time); t1=time.time(); print ("爬取子网页前时间:",t1); print ("开始爬取具体博客子网页"); soup_title=scarp_url(title_link); title=soup_title.find('h1',class_='view-title').text.strip(); print ("这篇博客名:",title); t2=time.time(); print ("爬取子网页后时间:",t2);
将sleep放在每个网页更改前,红框中以爬取两个但仍是出现错误ConnectionResetError: [WinError 10054] 远程主机强迫关闭了一个现有的链接。
是服务器为了维护本身的安全,对于不正常的浏览网页者作的限制。刚开始不知http://www.santostang.com/是不是网页的问题,由于该网址有网页进入不了。因此更换了一个网址(豆瓣),从新测试。函数
import requests; from bs4 import BeautifulSoup; import time,random; def scarp_url(link): headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'}; r=requests.get(link,headers=headers); soup=BeautifulSoup(r.text); return soup; link='https://book.douban.com/tag/%E5%B0%8F%E8%AF%B4';#主网页 soup=scarp_url(link); post_titles=soup.find_all('li',class_='subject-item'); for each in post_titles: info_url=each.find('div',class_='info'); title_link=info_url.a['href'];#子网页的地址 print (title_link);· print ("休息一下"); sleep_time=random.randint(0,2)+random.random(); time.sleep(sleep_time); t1=time.time(); print ("爬取子网页前时间:",t1); print ("开始爬取具体豆瓣具体书本的子网页"); soup_title=scarp_url(title_link); title=soup_title.find('span',property='v:itemreviewed').text.strip(); print ("这书本名:",title); t2=time.time(); print ("爬取子网页后时间:",t2);
爬取结果,是ok的,因此前面一个网页本身的问题哦;但目前还不知道 遇到这种网页应该怎么办。
post
def scarp_url(link): headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'}; r=requests.get(link,headers=headers); soup=BeautifulSoup(r.text); return soup; link='https://book.douban.com/tag/%E5%B0%8F%E8%AF%B4';#主网页 soup=scarp_url(link); post_titles=soup.find_all('li',class_='subject-item'); scrap_time=0; #计算爬取次数 for each in post_titles: info_url=each.find('div',class_='info'); title_link=info_url.a['href']; print (title_link); print ("开始爬取具体豆瓣具体书本的子网页"); soup_title=scarp_url(title_link); title=soup_title.find('span',property='v:itemreviewed').text.strip(); print ("这书本名:",title); t2=time.time(); print ("爬取子网页后时间:",t2); scrap_time+=1; if scrap_time % 5==0: sleep_time=10+random.random(); else: sleep_time=random.randint(0,2)+random.random(); time.sleep(sleep_time); t1=time.time(); print ("爬取子网页前时间:",t1);
增长一个scrap 次数计数。
(3)使用代理
代理是一种特殊的网络服务,容许一个网络终端(通常为客户端),经过这个服务于另外一个网络终端(通常为服务器)进行非直接的链接,其实就是信息的中转站。好比,直接访问国外的网站速度很慢,就能够用国内的代理服务器中转,数据先从国外某网站到国外的代理服务器,再到计算机,反而会比较快。
所以在爬虫过程当中,能够维护一个代理池,让本身的爬虫程序隐藏本身的真实ip。可是代理ip池较难维护,且不稳定。使用代理ip获取网页的方法,模板以下:
import requests; link='http://www.santostang.com/'; proxies={'http':'http://xxx.xxxxx.xxxxx',...};#就是多个IP地址的字典 response=requests.get(link,proxies=proxies);