聽說你的爬蟲被封了?

一隻寫程式的猿發表於2019-04-23

如果你在爬蟲過程中有遇到“您的請求太過頻繁,請稍後再試”,或者說程式碼完全正確,可是爬蟲過程中突然就訪問不了,那麼恭喜你,你的爬蟲被對方識破了,輕則給予友好提示警告,嚴重的可能會對你的ip進行封禁,所以代理ip那就尤為重要了。今天我們就來談一下代理IP,去解決爬蟲被封的問題。

網上有許多代理ip,免費的、付費的。大多數公司爬蟲會買這些專業版,對於普通人來說,免費的基本滿足我們需要了,不過免費有一個弊端,時效性不強,不穩定,所以我們就需要對採集的ip進行一個簡單的驗證。

1.目標採集

本文主要針對西刺代理,這個網站很早之前用過,不過那個時候它還提供免費的api,現在api暫不提供了,我們就寫個簡單的爬蟲去採集。

開啟西刺代理,有幾個頁面,果斷選擇高匿代理。

聽說你的爬蟲被封了?

Chrome瀏覽器右鍵檢查檢視network,不難發現,每個ip地址都在td標籤中,對於我們來說就簡單許多了,初步的想法就是獲取所有的ip,然後校驗可用性,不可用就剔除。

image.png

  • 定義匹配規則
import re

ip_compile = re.compile(r'<td>(\d+\.\d+\.\d+\.\d+)</td>')  # 匹配IP
port_compile = re.compile(r'<td>(\d+)</td>')  # 匹配埠
複製程式碼

2.校驗 這裡我使用淘寶ip地址庫檢驗可用性

2.1、關於淘寶IP地址庫

目前提供的服務包括: 1. 根據使用者提供的IP地址,快速查詢出該IP地址所在的地理資訊和地理相關的資訊,包括國家、省、市和運營商。 2. 使用者可以根據自己所在的位置和使用的IP地址更新我們的服務內容。 我們的優勢: 1. 提供國家、省、市、縣、運營商全方位資訊,資訊維度廣,格式規範。 2. 提供完善的統計分析報表,省準確度超過99.8%,市準確度超過96.8%,資料質量有保障。

2.2、介面說明

  1. 請求介面(GET): ip.taobao.com/service/get… 例:http://ip.taobao.com/service/getIpInfo2.php?ip=111.177.181.44
  2. 響應資訊: (json格式的)國家 、省(自治區或直轄市)、市(縣)、運營商
  3. 返回資料格式:
{"code":0,"data":{"ip":"210.75.225.254","country":"\u4e2d\u56fd","area":"\u534e\u5317",
"region":"\u5317\u4eac\u5e02","city":"\u5317\u4eac\u5e02","county":"","isp":"\u7535\u4fe1",
"country_id":"86","area_id":"100000","region_id":"110000","city_id":"110000",
"county_id":"-1","isp_id":"100017"}}
複製程式碼

其中code的值的含義為,0:成功,1:失敗。

注意:為了保障服務正常執行,每個使用者的訪問頻率需小於10qps。 我們先通過瀏覽器測試一下

  • 輸入地址http://ip.taobao.com/service/getIpInfo2.php?ip=111.177.181.44

    聽說你的爬蟲被封了?

  • 再次輸入一個地址http://ip.taobao.com/service/getIpInfo2.php?ip=112.85.168.98

    聽說你的爬蟲被封了?

  • 程式碼操作

import requests

check_api = "http://ip.taobao.com/service/getIpInfo2.php?ip="
api = check_api + ip
try:
    response = requests.get(url=api, headers=api_headers, timeout=2)
    print("ip:%s 可用" % ip)
except Exception as e:
    print("此ip %s 已失效:%s" % (ip, e))
複製程式碼

3.程式碼

程式碼中加入了異常處理,其實自己手寫的demo寫不寫異常處理都可以,但是為了方便其他人除錯,建議在可能出現異常的地方加入異常處理。

import requests
import re
import random

from bs4 import BeautifulSoup

ua_list = [
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36",
    "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.75 Safari/537.36",
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.119 Safari/537.36",
    "Mozilla / 5.0(Windows NT 6.1;WOW64) AppleWebKit / 537.36(KHTML, likeGecko) Chrome / 45.0.2454.101Safari / 537.36"
    ]


def ip_parse_xici(page):
    """

    :param page: 採集的頁數
    :return:
    """
    ip_list = []
    for pg in range(1, int(page)):
        url = 'http://www.xicidaili.com/nn/' + str(pg)
        user_agent = random.choice(ua_list)
        my_headers = {
            'Accept': 'text/html, application/xhtml+xml, application/xml;',
            'Accept-Encoding': 'gzip, deflate, sdch',
            'Accept-Language': 'zh-CN,zh;q=0.8',
            'Referer': 'http: // www.xicidaili.com/nn',
            'User-Agent': user_agent
        }
        try:
            r = requests.get(url, headers=my_headers)
            soup = BeautifulSoup(r.text, 'html.parser')
        except requests.exceptions.ConnectionError:
            print('ConnectionError')
        else:
            data = soup.find_all('td')
            # 定義IP和埠Pattern規則
            ip_compile = re.compile(r'<td>(\d+\.\d+\.\d+\.\d+)</td>')  # 匹配IP
            port_compile = re.compile(r'<td>(\d+)</td>')  # 匹配埠
            ips = re.findall(ip_compile, str(data))  # 獲取所有IP

            ports = re.findall(port_compile, str(data))  # 獲取所有埠
            check_api = "http://ip.taobao.com/service/getIpInfo2.php?ip="

            for i in range(len(ips)):
                if i < len(ips):
                    ip = ips[i]
                    api = check_api + ip
                    api_headers = {
                        'User-Agent': user_agent
                    }
                    try:
                        response = requests.get(url=api, headers=api_headers, timeout=2)
                        print("ip:%s 可用" % ip)
                    except Exception as e:
                        print("此ip %s 已失效:%s" % (ip, e))
                        del ips[i]
                        del ports[i]
            ips_usable = ips
            ip_list += [':'.join(n) for n in zip(ips_usable, ports)]  # 列表生成式
            print('第{}頁ip採集完成'.format(pg))
    print(ip_list)


if __name__ == '__main__':
    xici_pg = input("請輸入需要採集的頁數:")
    ip_parse_xici(page=xici_pg)
複製程式碼

執行程式碼:

日誌

4.為你的爬蟲加入代理ip

建議大家可以把採集的ip存入資料庫,這樣每次爬蟲的時候直接呼叫即可,順便提一下程式碼中怎麼加入代理ip。

import requests

url = 'www.baidu.com'
headers = {
    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.119 Safari/537.36",
}
proxies = {
    "http": "http://111.177.181.44:9999",
    # "https": "https://111.177.181.44:9999",
}

res = requests.get(url=url, headers=headers, proxies=proxies)
複製程式碼

好了,媽媽再也不擔心我爬蟲被封了

相關文章