天天看點

使用Selenium+firefox抓取網頁指定firefox_profile後的問題摘要:一、環境二、代碼情況參考資料:

摘要:

在使用selenium和firefox抓取網頁指定firefox_profile後遇到問題,生成的日志檔案太大直接導緻C槽資源耗盡,火狐浏覽器直接就停止工作了。

一、環境

windows2008 server(尴尬,C槽空間還劇小)

python 3.4

selenium + firefox

二、代碼情況

利用selenium 調用Firefox核心爬取網站

sFirefoxProfile ='C:\\Users\\username\\AppData\\Roaming\\Mozilla\\Firefox\\Profiles\\2alxrl56.default' # firefox 配置檔案路徑
fProfile= FirefoxProfile(sFirefoxProfile) # Firefox配置檔案,如果不設定這個也可能會被認為是爬蟲
driver = webdriver.Firefox(fProfile)
           

抓取一段時間之後發現爬蟲不再抓取網頁,火狐停止工作,發現是C槽使用者路徑下面生成了大量的臨時檔案,其中日志檔案特别大。

C:\Users\username\AppData\Local\Temp\3\tmpuuvium\webdriver-py-profilecopy

爬蟲每次啟動之後都會從指定的Firefox配置檔案路徑複制到臨時目錄中,并且開始生成日志檔案。

一開始我希望能夠不讓爬蟲啟動的時候都重新生成臨時目錄,直接使用上次複制後得到的配置檔案,但是經過檢索并沒有發現可行的辦法。在檢索過程中發現了selenium.webdriver.firefox.firefox_profile 的<a target=_blank href="https://selenium.googlecode.com/git/docs/api/py/_modules/selenium/webdriver/firefox/firefox_profile.html" target="_blank" rel="external nofollow" >源代碼</a>。發現并沒有類似的方法,而且找到了每次生成臨時目錄的相關代碼。

class FirefoxProfile(object):
    ANONYMOUS_PROFILE_NAME = "WEBDRIVER_ANONYMOUS_PROFILE"
    DEFAULT_PREFERENCES = None

    def __init__(self, profile_directory=None):
        """
        Initialises a new instance of a Firefox Profile

        :args:
         - profile_directory: Directory of profile that you want to use.
           This defaults to None and will create a new
           directory when object is created.
        """
        if not FirefoxProfile.DEFAULT_PREFERENCES:
            with open(os.path.join(os.path.dirname(__file__),
                                   WEBDRIVER_PREFERENCES)) as default_prefs:
                FirefoxProfile.DEFAULT_PREFERENCES = json.load(default_prefs)

        self.default_preferences = copy.deepcopy(
            FirefoxProfile.DEFAULT_PREFERENCES['mutable'])
        self.native_events_enabled = True
        self.profile_dir = profile_directory
        self.tempfolder = None
        if self.profile_dir is None:
            self.profile_dir = self._create_tempfolder()
        else:
            self.tempfolder = tempfile.mkdtemp()
            newprof = os.path.join(self.tempfolder, "webdriver-py-profilecopy")
            shutil.copytree(self.profile_dir, newprof,
                            ignore=shutil.ignore_patterns("parent.lock", "lock", ".parentlock"))
            self.profile_dir = newprof
            self._read_existing_userjs(os.path.join(self.profile_dir, "user.js"))
        self.extensionsDir = os.path.join(self.profile_dir, "extensions")
        self.userPrefs = os.path.join(self.profile_dir, "user.js")
           

可以發現在設定FirefoxProfile的過程就會生成臨時目錄,并且會完成一次拷貝。而生成臨時目錄是通過tempfile的mkdtemp()實作的。

我去看了一下tempfile的mkdtemp()方法:

tempfile.mkstemp([suffix=''[, prefix='tmp'[, dir=None[, text=False]]]])

在未指定dir的情況下,将根據系統環境變量TMPDIR, TEMP或者TMP的設定來儲存臨時檔案。由于不能在FireProfile的代碼上改動,是以問題變成設定環境變量TMPDIR。

# 設定環境變量
os.environ['TMPDIR']=os.path.join(os.path.abspath('.'), 'profile')
           

這樣,每次爬蟲每次啟動都會在目前目錄的profile目錄下生成臨時檔案。盡管解決方案不夠理想,但是足夠讓爬蟲繼續運作下去了。

也許直接在Selenium的源代碼直接修改後重新編譯會更省事,留待以後嘗試吧。

注:

python環境變量的設定

1、os.environ['環境變量名稱']='環境變量值' #其中key和value均為string類型

2、os.putenv('環境變量名稱', '環境變量值')

擷取系統環境變量

1、os.environ['環境變量名稱']

2、os.getenv('環境變量名稱')

以上方法,推薦用os.environ,因為使用os.putenv()并不會真正改變os.environ字典裡面的環境變量,即某些平台無效,但是使用os.environ有一個潛在的隐患:在一些平台上,包括FreeBSD和Mac OS X,修改environ會導緻記憶體洩露。設定的環境變量隻存在于目前的python shell中(設定成功後用print os.environ['環境變量名稱']或printos.getenv('環境變量名稱') 檢視)。

參考資料:

1. FireProfile源代碼:

https://selenium.googlecode.com/git/docs/api/py/_modules/selenium/webdriver/firefox/firefox_profile.html

2. tempfile的相關方法:

http://www.cnblogs.com/captain_jack/archive/2011/01/19/1939555.html

3. python設定擷取環境變量的方法:

http://aurorawu.lofter.com/post/18f005_6fd653