1. 程式人生 > >Python爬蟲 西刺代理IP的獲取 代理IP

Python爬蟲 西刺代理IP的獲取 代理IP

首先介紹一下爬蟲為什麼要使用代理IP

在爬蟲的過程中,我們經常會遇見很多網站採取了防爬取技術,或者說因為自己採集網站資訊的強度和採集速度太大,給對方伺服器帶去了太多的壓力。 如果你一直用同一個代理ip爬取這個網頁,很有可能ip會被禁止訪問網頁,所以基本上做爬蟲的都躲不過去ip的問題。 所以我們在爬取網頁內容的過程中需要使用代理ip,在這裡介紹一種獲取代理ip方式,從西刺網站獲取代理ip。

具體獲取步驟如下

使用方式:將需要獲取頁數傳入主函式即可。 在這裡使用的是requests方式獲取網頁內容,使用BeautifulSoup提取網頁內容。並將提取到的代理ip分類儲存到txt檔案中。

1、導包

import
requests import chardet import random import time from bs4 import BeautifulSoup from telnetlib import Telnet import progressbar

2、 準備瀏覽器頭部

說明一下,使用requests獲取西刺網頁程式碼的時候需要設定瀏覽器頭部否則獲取不到網頁內容。

  user_agent = [
       "Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)",
       "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AcooBrowser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)"
, "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Acoo Browser; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506)", "Mozilla/4.0 (compatible; MSIE 7.0; AOL 9.5; AOLBuild 4337.35; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)", "Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)"
, "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 2.0.50727; Media Center PC 6.0)", "Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 1.0.3705; .NET CLR 1.1.4322)", "Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.0.04506.30)", "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.3 (Change: 287 c9dfb30)", "Mozilla/5.0 (X11; U; Linux; en-US) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.6", "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.2pre) Gecko/20070215 K-Ninja/2.1.1", "Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9) Gecko/20080705 Firefox/3.0 Kapiko/3.0", "Mozilla/5.0 (X11; Linux i686; U;) Gecko/20070322 Kazehakase/0.4.5", "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.8) Gecko Fedora/1.9.0.8-1.fc10 Kazehakase/0.5.6", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/535.20 (KHTML, like Gecko) Chrome/19.0.1036.7 Safari/535.20", "Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; fr) Presto/2.9.168 Version/11.52" ]

3、定義獲取網頁程式碼函式

def getHtmlWithHeader(url):
	# 嘗試獲取網頁內容,當獲取失敗的時候重新獲取網頁程式碼
	# 當失敗次數過多時停止獲取 並輸出提示資訊
    try:
        # 獲取響應內容
        response = requests.get(
            url,
            headers={"User-Agent": random.choice(user_agent)}
        )
        # 獲取編碼
        code = chardet.detect(response.content)["encoding"]
        # 指定編碼
        response.encoding = code
        # 輸出文字
        # print(response.text)
        return response.text
    except:
        time.sleep(1)
        global _times_count
        _times_count += 1
        if _times_count > 5:
            print("ip獲取失敗,請稍後重試")
            return
        print("第", _times_count, "次嘗試抓取")
        return getHtmlWithHeader(url)

4、從獲取到的網頁程式碼中提取代理IP

def getIP(num):
    # 準備資料列表
    datalist = []
    # 準備 url
    for num1 in range(num):
        url = 'http://www.xicidaili.com/nn/' + str(num1 + 1)
        # 獲取返回資料
        html = getHtmlWithHeader(url)
        soup = BeautifulSoup(html, 'html.parser')
        parent = soup.find(id="ip_list")
        lis = parent.find_all('tr')
        # 刪除第一條資料
        lis.pop(0)
        print("爬取ip地址及相關資訊")
        for i in lis:
            ip = i.find_all('td')[1].get_text()
            dk = i.find_all('td')[2].get_text()
            nm = i.find_all('td')[4].get_text()
            ty = i.find_all('td')[5].get_text()
            tm = i.find_all('td')[8].get_text()
            datalist.append((ip, dk, nm, ty, tm))
    print("共爬取到", len(datalist), "條資料\n")
    # 將獲取到的資料返回
    return datalist

5、過濾代理IP,將生存時間短的以及不可用的IP過濾掉

def filtrateIP(datalist):
    datalist1 = []
    # 對生存時間短的資料進行過濾
    print('過濾存活時間短的\n')
    for i in datalist:
        if "分鐘" not in i[4]:
            datalist1.append(i)
            # print(i)
    print("共過濾掉", len(datalist) - len(datalist1), "條生存時間短的資料")
    print("還剩", len(datalist1), "條資料\n")

    # 對得到的資料進行測試,看是否可用
    print('測試不可用的ip並將其過濾')
    datalist.clear()
    v = 1
    p = progressbar.ProgressBar()
    for i in p(datalist1):
        # print("正在檢測第"+str(v)+"條資料")
        v += 1
        try:
            Telnet(i[0], i[1], timeout=1)
        except:
            pass
        else:
            datalist.append(i)

    print('過濾不可用的ip')
    print("共過濾掉", len(datalist1) - len(datalist), "條不可用資料")
    print("還剩", len(datalist), "條資料")
    # 將過濾後的資料返回
    return datalist

6、將過濾後的ip按HTTP/HTTPS分類並儲存

def saveIP(datalist):
    # 對得到的資料進行分類 http/https
    httplist = []
    httpslist = []
    for i in datalist:
        if i[3] == 'HTTP':
            httplist.append('http://' + i[0] + ':' + i[1])
        else:

            httpslist.append('https://' + i[0] + ':' + i[1])
    # 將顯示結果顯示到螢幕上
    print("HTTP共" + str(len(httplist)) + "條資料")
    print(httplist)
    print("")
    print("HTTPS共" + str(len(httpslist)) + "條資料")
    print(httpslist)
    print("")
    print("寫入檔案")

    # 開啟檔案
    f = open('ip地址.txt', 'w', encoding="utf-8")
    # 寫入檔案
    f.write("HTTP\n")
    f.write(str(httplist) + "\n\n")
    f.write("HTTPS\n")
    f.write(str(httpslist))
    # 關閉檔案
    f.close()

7、最後呼叫這些函式即可

# num 為爬取的頁數
def main(num):
	datalist = getIP(num)
    IPlist = filtrateIP(datalist )
    saveIP(IPlist)


if __name__ == '__main__':
    main(1)