隨機切換IP和UA


  在爬蟲爬取過程中,網站會根據我們的IP和UA去確認到底是瀏覽器操作還是爬蟲在操作,所以,為了讓爬蟲不被網站禁止,隨機切換Ip 和UA是很重要的,因為這個類在各個爬蟲中經常要用到,所以可以自已維護一份隨機切換IP和UA的代碼,

  可以在爬蟲工程目錄中加入tools這個目錄,這個目錄中存放着這個爬蟲所用到的一些工具,

    目錄結構如下:

  

  get_ip.py 代碼如下:

  

import requests
import pymysql


class GetIp(object):
    """從數據庫中取出可用的IP給爬蟲使用"""
    conn = pymysql.connect(host="127.0.0.1", user="root", password="root", db="outback")
    cursor = conn.cursor()

    def get_random_ip(self):
        select_sql = "select ip,port,type from ip_proxy ORDER  by rand() limit 1"

        result = self.cursor.execute(select_sql)
        for ip_info in self.cursor.fetchall():
            ip = ip_info[0]
            port = ip_info[1]
            type = ip_info[2].lower()
            judge_result = self.judge_ip(type, ip, port, )
            if judge_result:
                # 這里不能關閉連接,因為每一個請求都會雲獲取一個IP,如果關了,就只能獲取一個
                # self.cursor.close()
                # self.conn.close()

                return "{0}://{1}:{2}".format(type, ip, port)
            else:
                self.get_random_ip()

    def judge_ip(self, type, ip, port):
    """驗證IP是否可用,如果可以用,則返回,不可用,則刪除數據庫中的該IP""" baidu
= "https://www.baidu.com" proxy_url = "{0}://{1}:{2}".format(type, ip, port) try: proxy_dict = {type:proxy_url,} response = requests.get(baidu, proxies=proxy_dict) except Exception as e: print("invalid in or port ") self.delete_ip(ip) return False else: code = response.status_code if code >= 200 and code < 300: print("effective ip,the ip is",proxy_url) return True else: print("invalid iP ") self.delete_ip(ip) return False def delete_ip(self, ip): delete_sql = """delete FROM ip_proxy where ip='{0}'""".format(ip) try: self.cursor.execute(delete_sql) self.conn.commit() except Exception as e: print(e) if __name__ == "__main__": get_ip = GetIp() ip = get_ip.get_random_ip() print(ip)

之后在middlewares.py 中進行設置,

middlewares.py代碼如下:

from taobao.tools.get_ip import GetIp

class RandomProxyMiddleware(object):
    #動態設置ip代理
    def process_request(self, request, spider):
        get_ip = GetIP()
        request.meta["proxy"] = get_ip.get_random_ip()

這樣就可以使scrapy 動態的隨機更換IP

 

二 隨機更換UA,

  自己可以在settings中維護一個ua池,然后隨機切換,但是這樣有個不好的地方是,自已維護UA池很麻煩,還在定期查看這些UA是否可用,網上有個開源的庫 fake-useragent

這個庫動態的管理着很多UA,可以使用。

用法如下:

from scrapy import signals
from fake_useragent import UserAgent

class RandomUserAgentMiddleware(object):
    """使用爬蟲使用隨機的Ip 和 UA"""

    def __init__(self, crawler):
        self.ua = UserAgent()
        self.ua_type = crawler.settings.get("USER_AGENT_TYPE", "random")
        super(RandomIpAndUserAgentMiddleware, self).__init__()

    @classmethod
    def from_crawler(cls, crawler):
        return cls(crawler)

    def process_request(self, request, spider):
        def get_ua():
            return getattr(self.ua, self.ua_type)

        request.headers.setdefault('User-Agent', get_ua())

其實上邊兩個類可寫成一個類,這個在settings中只設置一個類就行了,代碼如下:

from scrapy import signals
from fake_useragent import UserAgent
from taobao.tools.get_ip import GetIp

    def process_request(self, request, spider):
        def get_ua():
            return getattr(self.ua, self.ua_type)
        request.headers.setdefault('User-Agent', get_ua())
        get_ip = GetIP()
        request.meta["proxy"] = get_ip.get_random_ip()

 

上面代碼中有幾個非常重要的,也是很容易出錯的地了,

一、老師,前輩們經常會說,文件打開記得關閉,數據庫連接后記得斷開連接,但是在GetIp這個類中不能斷開數據庫(我在這里也卡了),因為scrapy是隨機取IP,也就意味着scrapy對每次請求(也可能是每幾次請求)就會去數據庫中取IP,所以如果在GetIp這個類中就斷開連接后,也就是只能取一次,下次就不能取了,所以GetIp這個類中不能斷開連接,可以使用scrapy 信號,當爬蟲關閉的時候斷開連接。所以GetIp類不連接數據而沒有斷開連接是沒有錯的。

二,西刺的IP很慢,所以還是珍惜自已的IP,友好爬取,

 

 

GitHub https://github.com/573320328/tools

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM