Datawhale-爬虫-Task6(学习IP相关知识)

什么是IP(Internet Protocol)

定义

互联网协议地址(Internet Protocol Address,又译为网际协议地址),缩写为IP地址(IP Address),是分配给用户上网使用的网际协议(IP)的设备的数字标签。常见的IP地址分为IPv4与IPv6两大类,但是也有其他不常用的小分类。

基本原理

网络互连设备,如以太网、分组交换网等,它们相互之间不能互通,不能互通的主要原因是因为它们所传送数据的基本单元(技术上称之为“帧”)的格式不同。IP协议实际上是一套由软件、程序组成的协议软件,它把各种不同“帧”统一转换成“网协数据包”格式,这种转换是因特网的一个最重要的特点,使所有各种计算机都能在因特网上实现互通,即具有“开放性”的特点。

IP地址

  • IP地址由32位二进制数组成,为便于使用,常以XXX.XXX.XXX.XXX形式表现,每组XXX代表小于或等于255的10进制数。例如维基媒体的一个IP地址是208.80.152.2。地址可分为A、B、C、D、E五大类,其中E类属于特殊保留地址。
  • 随着互联网的快速成长,IPv4的42亿个地址的分配最终于2011年2月3日用尽。相应的科研组织已研究出128位的IPv6,其IP地址数量最高可达3.402823669 × 1038个,届时每个人家居中的每件电器,每件对象,甚至地球上每一粒沙子都可以拥有自己的IP地址。
  • 在A类、B类、C类IP地址中,如果主机号是全1,那么这个地址为直接广播地址,它是用来使路由器将一个分组以广播形式发送给特定网络上的所有主机。32位全为1的IP地址“255.255.255.255”为受限广播地址(“limited broadcast” destination address),用来将一个分组以广播方式发送给本网络中的所有主机,路由器则阻挡该分组通过,将其广播功能限制在本网内部。
  • 更多关于IPv4以及IPv6的介绍:IP地址

IP封锁

定义

IP封锁是指防火墙维护一张IP黑名单,一旦发现发往黑名单中地址的请求数据包,就直接将其丢弃,这将导致源主机得不到目标主机的及时响应而引发超时,从而达到屏蔽对目标主机的访问的目的。

IP被封的原因

  • 1.服务器在国内被封,无法正常访问。
  • 2.服务商更换服务器(不常见)。
  • 3.当计算机或系统受到外部攻击时,管理员可以通过屏蔽攻击源IP地址来抵御攻击。通过防火墙和路由器配置,可以封锁某个IP,禁止与其连接,从而达到抵御攻击的作用。

如何应对IP被封

在编写爬虫爬取数据的时候,因为很多网站都有反爬虫措施,所以很容易被封IP,就不能继续爬了。以下给出一些应对措施,可以单独使用,也可以同时使用,效果更好。

  • 伪造User-Agent
    在请求头中把User-Agent设置成浏览器中的User-Agent。来伪造浏览器访问。
    随机获取headers代码:
import random
def get_headers():
   # 随机获取一个headers 
    user_agents =  ['Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1','Mozilla/5.0 (Windows; U; Windows NT 6.1; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50','Opera/9.80 (Windows NT 6.1; U; en) Presto/2.8.131 Version/11.11']
    headers = {'User-Agent':random.choice(user_agents)}
    return headers

注:更详细的User-Agent介绍:User-Agent结构介绍及主流浏览器User-Agent大全

  • 伪造cookies
    若从浏览器中可以正常访问一个页面,则可以将浏览器中的cookies复制过来使用,比如:
cookies = dict(uuid='b18f0e70-8705-470d-bc4b-09a8da617e15',UM_distinctid='15d188be71d50-013c49b12ec14a-3f73035d-100200-15d188be71ffd')
resp = requests.get(url,cookies = cookies)
# 把浏览器的cookies字符串转成字典
def cookies2dict(cookies):
    items = cookies.split(';')
    d = {}
    for item in items:
        kv = item.split('=',1)
        k = kv[0]
        v = kv[1]
        d[k] = v
    return d

注:用浏览器cookies发起请求后,如果请求频率过于频繁仍会被封IP,这时可以在浏览器上进行相应的手工验证(比如点击验证图片等),然后就可以继续正常使用该cookies发起请求。

  • 使用代理
    可以换着用多个代理IP来进行访问,防止同一个IP发起过多请求而被封IP,比如:
proxies = {'http':'http://10.10.10.10:8765','https':'https://10.10.10.10:8765'}
resp = requests.get(url,proxies = proxies)

注:免费的代理IP可以在这个网站上获取:http://www.xicidaili.com/nn/

案例:抓取西刺代理,并构建自己的代理池。

西刺链接:西刺免费代理IP

  • 分析网站结构,通过F12查看网页信息,发现ip地址,端口,类型这些信息都保存在<tr>标签内,并且有两个不同的tr标签。在这里插入图片描述
  • 使用正则表达式,利用相隔的html结构先把整个内容匹配下来,再把重要信息匹配下来,最后就把他弄成{‘https’: ‘https://ip:端口’}这个样子存入列表即可
#匹配整体数据的正则
root_pattren = 'alt="Cn" /></td>([\d\D]*?)</tr>'
#再次匹配数据的正则
key = re.findall('<td>([\d\D]*?)</td>',s)
  • 最后就随机获取一个ip,然后可以先判断是否有用,再拿来做你此时项目的代理ip,判断是否用的方法就是随便拿一个百度获取别的网站,加上代理ip发送get请求,看看status_code()的返回码是不是200,即可。

案例代码:

import requests
import chardet
import traceback
from bs4 import BeautifulSoup as bs
 
class Downloader(object):
    def __init__(self):
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36'
        }
 
    def download(self, url):
        print('正在下载页面:{}'.format(url))
        try:
            resp = requests.get(url, headers=self.headers)
            #resp.encoding = chardet.detect(resp.content)['encoding']
 
            if resp.status_code == 200:
                return resp.text
            else:
                raise ConnectionError
        except Exception:
            print('下载页面出错:{}'.format(url))
            traceback.print_exc()
 
    def get_ip_list(self,resp):
        try:
            #page = bs(resp,'lxml')
            root_pattren = 'alt="Cn" /></td>([\d\D]*?)</tr>'
            root = re.findall(root_pattren,resp)
            list_ip = []
            #再次匹配数据的正则
            for i in range(len(root)):
                key = re.findall('<td>([\d\D]*?)</td>',root[i])
                list_ip.append(key[3].lower()+'://'+key[0]+':'+key[1])
            return list_ip
        except Exception:
            print('解析IP地址出错')
            traceback.print_exc()
            
def main():
    url ='https://www.xicidaili.com/' 
    resp = Downloader().download(url)
    info = Downloader().get_ip_list(resp)
    for i in info:
        print(i)
        
if __name__ == '__main__':
    main()

运行结果:
在这里插入图片描述

发布了67 篇原创文章 · 获赞 113 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/TNTZS666/article/details/88244490