Python精確指南——第三章 Selenium和爬蟲(Python第三章)

      網友投稿 1178 2022-05-30

      3?????? Selenium

      3.1???? 介紹

      網絡爬蟲在互聯網領域有著廣泛的應用。

      Selenium是一個頁面自動化控制框架。能夠模擬實際操作,自動化獲取網站提供的頁面資源信息。

      Selenium能夠自定義頁面操作的行為,按照用戶指定的跳轉路徑訪問,具有實現跟實際用戶一樣填充信息、提交表單請求的能力,適用于專門網站特定信息的獲取。比如:特定圖片網站圖片的獲取,購物網站商品信息的獲取等等。

      3.2???? 下載與安裝

      Selenium最新的版本是3.8.0,目前支持Python 2.7和3.4+版本。

      在線安裝:pip install -U selenium

      離線安裝:在PyPI網站上下載對應安裝包,參考1.4 章節Python安裝包 進行離線安裝。

      3.3???? 關鍵技術要點

      Selenium框架的開發步驟這里不做詳細介紹,可以參考如下鏈接進行開發前學習。

      開發文檔及樣例:

      http://seleniumhq.github.io/selenium/docs/api/py/

      Selenimu開發包API:

      https://seleniumhq.github.io/selenium/docs/api/py/api.html

      下面就開發中遇到的幾個關鍵技術要點進行詳解。

      3.3.1? 瀏覽器的選擇

      Selenium針對不同的瀏覽器有對應的驅動引擎,在64位系統上,一般IE是64bit。如果用32bit的IEDriverServer.exe,在第二頁就會看到web browser not get,然后運行出錯。但是如果用64bit的IEDriverServer.exe,在填表格的時候就會特別慢,原因不明。

      使用不同的瀏覽器,需要使用到不同瀏覽器的驅動Driver,下面是各個瀏覽器Selenium Client Drivers的下載頁面:

      http://seleniumhq.org/download/

      ?? Selenium的WebDriver打開IE失敗的解決辦法

      在運行IE瀏覽器時,會報下面的錯誤:

      WebDriverException: Message: u'Unexpected error launching Internet Explorer. Protected Mode must be set to the same value (enabled or disabled) for all zones.'

      兩種方法:

      1)修改IE的安全策略,就像Exception里面提示的那樣。

      2)在生成webdriver對象之前先執行這些代碼:

      from selenium.webdriver.common.desired_capabilities import DesiredCapabilities

      DesiredCapabilities.INTERNETEXPLORER['ignoreProtectedModeSettings'] = True

      firefox速度會比較快,首選firefox。

      3.3.2? XPath

      XPath是XML路徑語言,用來查找定位xml樹狀結構中的節點,同樣適用html。

      參考學習手冊:

      http://www.w3school.com.cn/xpath/index.asp

      判斷定義好的xpath規則是否找到定位節點:

      uname = self.master.html_elem.xpath("http://tr/td/form[@name = 'frmResult']")

      if len(uname) == 0:

      return False

      3.3.3? StringIO

      StringIO模塊可以將內存中的xml結構字符串保存成離線html文件,實現在線轉離線的功能:

      import StringIO

      blank _xml = StringIO.StringIO()

      root_test = etree.parse(blank_xml)

      root_test.write("test.xml")

      3.3.4? lxml

      第三方安裝包lxml比Python自帶的xml模塊具有更為強大的解析xml或html的功能,推薦使用。最新的版本是4.1.1。

      下載頁面:

      https://pypi.python.org/pypi/lxml/4.1.1

      找到對應的版本,使用pip安裝即可。

      像3.3.3 StringIO章節中介紹的保存的離線xml或者html,lxml就可以像解析在線request請求到的網頁內容一樣進行解析:

      url:

      xxx_sample? = urllib2.urlopen(url).read()

      Doc = html.fromstring(xxx_sample)

      文件:

      xxx_sample = HTML.parse('xxx_sample.htm')

      Doc = xxx_sample.getroot()

      3.3.5? 解析器的選擇

      lxml有默認的解析器,但是對于非規則的網頁處理非常不好。相當多的網站不是規則的html語法,所以需要選擇外部的解析器。

      在lxml里調用beautifulsoap。這個處理中文比較好,首選解析器。

      3.3.6? 中文字符的處理

      ?? 基本支持

      在源文件的第一行,在任何代碼和注釋前面,加入如下語句:

      #encoding=utf-8

      一般需要在寫任何中文和代碼之前加入這句話。如果先在代碼里出現了中文,然后貼這句話,或導致亂碼。

      ?? 保存中文網頁

      保存網頁數據。通常的網頁數據是unicode,在eclispe中運行的時候可以正確的保存,但是單獨運行就不行了。錯誤如下:

      使用encode("gb2312", "replace")就可以解決問題。

      代碼如下:

      file_object.write(page_text.encode("gb2312", "replace"))

      ?? Unicode字符串

      所有涉及到中文的字符串前加上u,實際上,可以在使用#encoding=utf-8之后,任何字串,包括英文字前面加上u也都是沒有問題,例子:

      text1 = u”中文字符”

      text2 = u”mystring”

      ?? 中文字符的編碼轉換

      在線request網頁:

      在讀取文本或者讀取網頁內容的時候,有時候無法判斷字符,需要使用import chardet來自動判斷字符的編碼格式,然后裝換成unicode,例子:

      content = urllib2.urlopen(url_to_fetch).read()

      xxx_encode = chardet.detect(content)

      unicode_content = unicode(content, xxx_encode["encoding"], "replace")

      離線html網頁:

      解析中文離線網頁的方法:

      parser = etree.HTMLParser(encoding = 'gb2312')

      xxx_sample = HTML.parse('xxx.htm', Parser)

      xxx_root = xxx_sample.getroot()

      ct = xxx_root.xpath('//title')

      try_name = ct[0].text

      這樣就可以得到中文title。

      ?? 中文字符的匹配

      需要使用Python內置正則表達式re模塊,例子:

      中文正則

      cn_str = u"計算機科學與技術"

      m = re.search(u"([u4e00-u9fa5]+)科學")

      t=m.group(1)

      這樣就可以得到“計算機”。

      3.1.1? 開發要點

      獲得頁面源碼

      page_text = chr_browser.page_source

      在頁面執行自定義script腳本

      平時用到的比較多的全選,復制等。

      chr_browser.execute_script('document.execcommand("selectall"))

      查找document.execcommand可以得到各種命令。

      打開多個Selenium控制的實例

      Selenium控制的實例需要指定一個端口,默認使用的是一個,所以無法啟動多個selenium的實例。如果指定了不同的端口,就能在一臺PC上控制多個瀏覽器實例。

      3.1.2? 驗證碼的識別

      在使用Selenium訪問網站時,用戶名和密碼的表單提交相對簡單,最難的是各個網站登錄時的驗證碼識別。

      Pytesseract:python封裝的tesseract

      Tesseract是圖片識別的一個開源項目,托管網址:

      https://github.com/tesseract-ocr/tesseract

      PyPI下載路徑和基本使用介紹:

      https://pypi.python.org/pypi/pytesseract

      Pytesseract的使用還依賴于PIL庫,PIL只能使用exe安裝,否則很麻煩,而且只支持32位的python,下載網址:

      http://www.pythonware.com/products/pil/

      Pytesseract其實并沒有做什么事情,把命令打印出來,就是在線程里執行如下的結果:

      ['tesseract', 'C:\Users\L00163~1\AppData\Local\Temp\tess_2.bmp', 'C:\Users\L00163~1\AppData\Local\Temp\tess_3', '-l', 'eng']

      很明顯,Pytesseract把輸入的流變成bmp文件,然后讓tesseract.exe去識別,然后從文本文件里獲得數據。

      ['tesseract', 'C:\Users\L00163~1\AppData\Local\Temp\tess_2.bmp', 'C:\Users\L00163~1\AppData\Local\Temp\tess_3', '-l', 'eng', 'batch.nochop', 'makebox']

      D:\python\sdk\tesseract\tesseract-ocr-3.01-win32-portable\Tesseract-ocr\Tesseract.exe zhilian_code1.bmp ret.txt -l eng -psm 7

      注意把tesseract的目錄加入到路徑里,必須重啟才能讓PATH生效。

      追加:加到全局path里不行,會崩潰,把執行命令找出來,在dos下執行,就會看到崩潰的真正原因。是因為找不到“./tessdata/eng.traineddata”. 實際上是有這個文件的說明還是路徑問題。干脆修改tesseract_cmd。Pytesseract本身是非常簡單的,需要修改兩處。注意只能修改Pytesseract安裝包源碼,而不是修改安裝之后的文件,是改不了的。

      在pytesseract.py里增加一個函數接口。

      def set_tesseract_cmd(tesseract_file_path):

      tesseract_cmd = tesseract_file_path

      另外在pytesseract的__init__.py里增加一句。

      from pytesseract import set_tesseract_cmd

      改完之后,重新執行setup.py build和setup.py install就可以了。

      不過為了簡單起見,直接把pytesseract.py復制到工程里就可以了,修改最方便。因為工程里import會優先找本地的文件,雖然同是也安裝了pytesseract,但是使用的是本地的pytesseract.py。

      在函數里修改文件的全局變量,需要加上global。如下面的修改

      tesseract_cmd = 'tesseract'

      def set_tesseract_cmd(tesseract_file_path):

      tesseract_cmd = tesseract_file_path

      是沒有效果的,set_tesseract_cmd的tesseract_cmd是另外一個局部變量。

      ?? 去底噪預處理

      適合于底噪不是很強烈,并且沒有單點深色噪音的識別碼。

      例如下圖,來自于火車票訂票網站。

      import Image,ImageFilter

      # load a color image

      im = Image.open('passCodeAction.do6.jpg')

      big_img = im.resize((120, 40))

      bim = big_img.filter(ImageFilter.SMOOTH)

      Lim = big_img.convert('L')

      Lim.save('fun_Level.jpg')

      Lim.show()

      # setup a converting table with constant threshold

      threshold = 160

      table = []

      for i in range(256):

      if i < threshold:

      table.append(0)

      else:

      table.append(1)

      # convert to binary image by the table

      bim = Lim.point(table, '1')

      bim.show()

      bim.save('fun_binary.tif')

      ?? 去單點強底噪的方法

      原始圖片,雖然底噪簡單,但是有不少單點的深色底噪。

      處理方法:

      im = Image.open(image_name)

      im = im.filter(ImageFilter.MedianFilter())

      enhancer = ImageEnhance.Contrast(im)

      im = enhancer.enhance(2)

      im = im.convert('1')

      im.show()

      經過以上處理,按道理及按照網絡上的資料,簡單英文和數字的識別率是很高的,實際上在用驗證碼的時候,識別率很低。而絕大部分圖形實際上是非常清楚的,比tesseract自帶樣本還要清楚。最后覺得原因可能是因為圖片太小,只有80×80的原因。

      嘗試用windows自帶的看圖軟件將識別碼圖片放大,然后截圖,另存為一個文件,結果一下子就認準了,說明就是圖片大小的問題,不是清晰度的原因。

      ?? 圖片放大方法

      def dzoom_img(pic, ratio):

      w = pic.size[0] * ratio

      h = pic.size[1] * ratio

      big_pic = pic.resize((w,h), Image.BILINEAR)

      big_pic.show()

      big_pic.save('auto_big.bmp')

      return big_pic

      ?? 圖片CROP

      手工放大后用hypersnap截圖如下,可以正常識別。

      但是用軟件自動放大之后,什么都識別不出來,連亂碼都沒有了,對比下兩個圖,沒什么區別,只是旁邊多了一些黑點,猜想是不是因為這些黑點的原因導致認不出來。用工具將黑點全部去掉,結果能正常識別。所以還需要用軟件把旁邊的黑點crop掉。

      CROP的方法

      crop_reg = (20, 20, w-20, h-20)

      big_pic = big_pic.crop(crop_reg)

      ?? 獲取驗證碼圖片

      參考多篇文章,最可靠的是截屏

      查看元素信息如下:

      截屏處理:

      用圖片軟件看截屏的圖和位置信息,可以看出,尺寸和size都是能對應上的,所以可以用crop函數精確的截取。不過同時要注意,圖片周邊的小點會產生明顯的影響,所以直接在crop階段去掉就可以了。在(515,165)處就能除掉邊界。所以截取的區域為

      (x-2, y-2,x+w-4, y+h-4)

      ?? 白名單研究:只處理數字和字母

      發現驗證碼的識別率很低,只有全數字的識別率高,嘗試只識別數字和字母

      D:\python\sdk\tesseract\tesseract-ocr-3.01-win32-portable\Tesseract-ocr\Tesseract.exe big_test4.png ret.txt -psm 7 char_digits

      新建文件:

      D:\python\sdk\tesseract\tesseract-ocr-3.01-win32-portable\Tesseract-ocr\tessdata\configs\char_digits

      內容如下,限制只能識別這些字符

      tessedit_char_whitelist 0123456789ABCDEFGHIJKLMNOPQRSTYVWXKZ

      3.1.1? 打包部署問題

      Selenium工程開發完成后,在需要在不同機器上進行部署搭建,不能依賴開發環境,在打包完成后遇到有下面的問題,最終也是通過修改源碼的方式完美解決。

      Python打包的部分在后面的章節會詳細介紹,這里只討論IE瀏覽器和firefox瀏覽器的selenium工程打包部署過程中遇到問題的解決。以下打包過程使用PyInstaller工具。

      ?? Firefox瀏覽器

      webdriver里使用firefox打包報錯如下,找不到webdriver.xpi和webdriver_prefs.json兩個文件:

      解決方法:

      用的2.48 selenium,修改兩處firefox_profile.py源碼文件。

      然后把這兩個文件復制到單文件的exe同路徑下就可以用了。

      2.48 selenium代碼修改, 都是改了路徑為當前路徑。

      修改為:

      '''with open(os.path.join(os.path.dirname(__file__),

      WEBDRIVER_PREFERENCES)) as default_prefs:

      FirefoxProfile.DEFAULT_PREFERENCES = json.load(default_prefs)'''

      if os.path.exists(WEBDRIVER_PREFERENCES):

      with open(WEBDRIVER_PREFERENCES) as default_prefs:

      FirefoxProfile.DEFAULT_PREFERENCES = json.load(default_prefs)

      else:

      with open(os.path.join(os.path.dirname(__file__),

      WEBDRIVER_PREFERENCES)) as default_prefs:

      FirefoxProfile.DEFAULT_PREFERENCES = json.load(default_prefs)

      修改為:

      '''if addon == WEBDRIVER_EXT:

      = os.path.join(os.path.dirname(__file__), WEBDRIVER_EXT)'''

      if addon == WEBDRIVER_EXT:

      if os.path.exists(WEBDRIVER_PREFERENCES):

      addon = os.path.join(WEBDRIVER_EXT)

      else:

      addon = os.path.join(os.path.dirname(__file__), WEBDRIVER_EXT)

      ?? IE瀏覽器

      webdriver里使用ie打包的結果

      這些是包含的文件

      打包報錯如下:

      無論如何找不到dll,pyinstaller的各種方法都已經試過了,就是不行。

      最后根據運行的提示信息,找到browser_man_lib.py的44行,點擊進去找到webdriver.py,發現是這么一行代碼:

      try:

      self.iedriver = CDLL(os.path.join(os.path.dirname(__file__),"win32", "IEDriver.dll"))

      except WindowsError:

      try:

      self.iedriver = CDLL(os.path.join(os.path.dirname(__file__),"x64", "IEDriver.dll"))

      except WindowsError:

      raise WebDriverException("Unable to load the IEDriver.dll component")

      肯定是CDLL(os.path.join(os.path.dirname(__file__),"x64", "IEDriver.dll"))執行不成功,猜測CDLL 只是要load一個dll而已,并不是要求確定的路由,因為輸入參數顯然就是全路徑的dll。所以先把這個路徑打印出來。代碼如下:

      dll_test_path = os.path.join(os.path.dirname(__file__),"win32", "IEDriver.dll")

      print dll_test_path

      try:

      self.iedriver = CDLL(dll_test_path)

      Python精確指南——第三章 Selenium和爬蟲(Python第三章)

      except WindowsError:

      try:

      self.iedriver = CDLL(os.path.join(os.path.dirname(__file__),"x64", "IEDriver.dll"))

      except WindowsError:

      raise WebDriverException("Unable to load the IEDriver.dll component")

      最后在執行的時候發現打印如下:

      E:\project\ryan_soft\py_depot\xxx_reaper_browser\src\build\pyi.win32\xxx_reape

      r\outPYZ1.pyz\win32\IEDriver.dll

      Traceback (most recent call last):

      File "", line 352, in

      File "", line 336, in main

      File "", line 243, in __init__

      File "E:\project\ryan_soft\py_depot\xxx_reaper_browser\src\build\pyi.win32\xxx_reaper\outPYZ1.pyz/browser_man_lib", line 44, in __init__

      File "E:\project\ryan_soft\py_depot\rsm_reaper_browser\src\build\pyi.win32\xxx_reaper\outPYZ1.pyz/selenium.webdriver.ie.webdriver", line 61, in __init__

      selenium.common.exceptions.WebDriverException: Message: 'Unable to load the E:\\

      project\\ryan_soft\\py_depot\\xxx_reaper_browser\\src\\build\\pyi.win32\\xxx_r

      eaper\\outPYZ1.pyz\\win32\\IEDriver.dll'

      說明執行程序試圖找到outPYZ1.pyz\\win32\\IEDriver.dll,這顯然是不可能的。所以需要修改一下路徑,先嘗試用絕對路徑,代碼修改如下,并且將

      D:\Python27\Lib\site-packages\selenium-2.20.0-py2.7.egg\selenium\webdriver\ie\win32\ IEDriver.dll

      復制到d:\\IEDriver.dll。重新編譯打包。

      dll_tmp_path = os.path.join("d:\\IEDriver.dll")

      try:

      self.iedriver = CDLL(dll_tmp_path)

      except WindowsError:

      try:

      self.iedriver = CDLL(os.path.join(os.path.dirname(__file__),"x64", "IEDriver.dll"))

      except WindowsError:

      raise WebDriverException("Unable to load the IEDriver.dll component")

      這下問題解決了。當時使用相對路徑肯定是不行的,所以采用相對路徑測試。

      將代碼改為

      dll_tmp_path = os.path.join("IEDriver.dll")

      try:

      self.iedriver = CDLL(dll_tmp_path)

      except WindowsError:

      try:

      self.iedriver = CDLL(os.path.join(os.path.dirname(__file__),"x64", "IEDriver.dll"))

      except WindowsError:

      raise WebDriverException("Unable to load the IEDriver.dll component")

      然后將IEDriver.dll復制到調用打包后exe的路徑,而不是exe的路徑。區別在于,如果是命令行在其他目錄調用exe,那么IEDriver.dll需要復制到那個路徑。如果windows下雙擊,當然IEDriver.dll就是需要和exe同一個目錄下。最干脆的解決方法是放到一個系統path能找到的地方,不管如何執行exe都沒有問題。

      3.1???? 注意事項

      使用Selenium應用獲取網站信息的時候,最好與網站官方有合作關系,否則在訪問頻率上需要格外注意。如果網站沒有健全的后臺系統,無節制的快速訪問,有可能致使網站崩潰,或者IP地址及賬戶被官方記錄,列入訪問黑名單。

      3.2???? 其他爬蟲框架

      下面簡單介紹幾種其他Python中常用的爬蟲框架。

      3.2.1? 內置模塊

      Python內置的urllib和urllib2可以實現簡單的request請求,獲取服務器的反饋數據。

      Post網頁:

      import urllib

      import urllib2

      postdata=urllib.urlencode({

      'username':'psstby',

      'password':'by201109'

      })

      req = urllib2.Request(

      url = 'http://hwrd.zhaopin.com/loginmgr/loginproc.asp',

      data = postdata

      )

      urllib2.urlopen(req).read()

      3.2.2? Scrapy

      Scrapy是一個為了爬取網站數據,提取結構性數據而編寫的應用框架。 可以應用在包括數據挖掘,信息處理或存儲歷史數據等一系列的程序中。

      Scrapy 使用 Twisted這個異步網絡庫來處理網絡通訊,架構清晰,并且包含了各種中間件接口,可以靈活的完成各種需求。

      官網地址:

      https://scrapy.org/

      3.2.3? PySpider

      PySpider 是一個非常方便并且功能強大的爬蟲框架,支持多線程爬取、JS動態解析,提供了可操作界面、出錯重試、定時爬取等等的功能,使用非常人性化。

      官網地址:

      http://www.pyspider.cn/

      開源托管地址:

      https://github.com/binux/pyspider/

      附件: Python精確指南-第三章selenium和爬蟲.pdf 1.11M 下載次數:11次

      編程語言 python Selenium

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:上下文菜單網頁顯示技術研究
      下一篇:excel表格設置漸變色背景的方法步驟(excel表格里如何把背景變成漸變色)
      相關文章
      久久精品国产亚洲av麻豆蜜芽 | 老子影院午夜伦不卡亚洲| 亚洲黄色免费网站| 亚洲精品无码国产| 亚洲AV综合色区无码另类小说| 亚洲高清无码综合性爱视频| 婷婷亚洲综合五月天小说在线 | 亚洲AV永久无码精品| 亚洲成AV人片在线观看无| 日韩va亚洲va欧洲va国产| 国产AV无码专区亚洲精品| 亚洲愉拍99热成人精品热久久| 国产亚洲成人久久| 亚洲欧洲日产国码无码久久99| 亚洲永久精品ww47| 精品国产_亚洲人成在线高清| 亚洲国产精品无码专区影院 | 亚洲高清有码中文字| 亚洲午夜在线播放| 亚洲日本一线产区和二线产区对比| 中文字幕乱码亚洲精品一区| 中文字幕亚洲精品无码| 亚洲欧美国产国产综合一区| 亚洲AV无码成人网站在线观看| 国产亚洲精品美女久久久久久下载| 国产亚洲男人的天堂在线观看| 亚洲午夜激情视频| 国产精品亚洲精品日韩已满| 亚洲VA中文字幕无码一二三区| 亚洲无删减国产精品一区| 337p欧洲亚洲大胆艺术| 亚洲AV无码一区二区三区在线| 亚洲熟妇AV一区二区三区宅男| 亚洲av日韩av永久无码电影| 无码国产亚洲日韩国精品视频一区二区三区| 色偷偷亚洲第一综合网| 国产精品亚洲w码日韩中文| 亚洲国产精品无码专区| 亚洲第一精品电影网| 亚洲综合欧美色五月俺也去| 小说区亚洲自拍另类|