Datawhale-爬蟲-Task6(學習IP相關知識)

TNTZS666發表於2019-03-06

什麼是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()

執行結果:
在這裡插入圖片描述

相關文章