整合營銷服務(wù)商

          電腦端+手機端+微信端=數(shù)據(jù)同步管理

          免費咨詢熱線:

          Python爬蟲的第二種姿勢,Selenium框架案例講解

          章目錄

          • selenium模塊
          • selenium基本概念
          • 基本使用
          • 代碼

          . 為什么使用selenium

          前面爬蟲大多使用的是urllib 庫, 另外還有requests 庫。urllib 可以解決好多問題,包括代理、自定義請求體、cookie 設(shè)置等。 這些庫都是模擬瀏覽器進行訪問,畢竟是模擬,有些網(wǎng)站針對反爬會造成爬取的數(shù)據(jù)不準確。

          這時候就需要引入selenium, selenuim 是真實的驅(qū)動瀏覽器,然后模擬人工操作去進行一系列的操作。

          ? 舉個簡單的例子: 京東官網(wǎng) https://www.jd.com/ 首頁,如果通過網(wǎng)頁訪問我們能拿到秒殺模塊; 如果是通過urllib 訪問拿到首頁源碼,發(fā)現(xiàn)沒有該模塊。該模塊所在區(qū)域的xpath 選擇器是: //*[@id='J_seckill']

          2. selenium 安裝以及簡單測試

          1. 下載瀏覽器驅(qū)動

          ? selenium 是驅(qū)動瀏覽器,然后去進行一系列的操作,所以我們需要下載對應(yīng)的驅(qū)動。

          ? chrome 驅(qū)動: http://chromedriver.storage.googleapis.com/index.html 根據(jù)自己的chrome 版本下載對應(yīng)的驅(qū)動, 大版本一致即可,windows 安裝包32 位也可以的。

          ? 驅(qū)動下載完成后將解壓后的exe驅(qū)動程序拷貝到運行程序同級目錄,或者就放到python 目錄然后加入到path 換變量中也可以。需要程序能找到該exe。

          2. pycharm 安裝selenium

          File→Settings→Project:項目名稱→python Interpreter->添加selenium

          pycharm 安裝完成后可以到項目的venv\lib 目錄查看現(xiàn)有的模塊

          3. 本地安裝selenium

          如果是想python 跑對應(yīng)腳本,需要本地安裝selenium

          pip install selenium
          

          測試可以在python 窗口輸入:

          from selenium import webdriver
          

          4. 簡單測試

          from selenium import webdriver
          
          browser = webdriver.Chrome("chromedriver.exe")
          browser.get("https://www.jd.com/")
          
          # 獲取網(wǎng)頁源碼
          content = browser.page_source
          print(content)
          # 打印url
          print(browser.current_url)
          
          # 保存為圖片(注意這里只能保存為png,不支持jpg)
          browser.save_screenshot("jd.png")
          
          # 打印title
          print(browser.title)
          # 窗口最大化
          browser.maximize_window()
          
          # 關(guān)閉
          browser.close()
          

          ? 會自動打開瀏覽器,然后訪問京東的首頁。然后打印網(wǎng)頁源碼(從源碼可以搜索到id 為 J_seckill 的div)。最后將網(wǎng)頁保存為圖片后關(guān)閉瀏覽器。

          3. selenium 解析以及獲取

          1. 獲取元素

          獲取元素主要有下面六個API:當(dāng)然返回的元素還可以繼續(xù)調(diào)用find_element 元素向下查找。

          from selenium import webdriver
          from selenium.webdriver.common.by import By
          
          browser = webdriver.Chrome("chromedriver.exe")
          browser.get("https://www.baidu.com/")
          
          # 獲取網(wǎng)頁源碼
          # content = browser.page_source
          # print(content)
          
          '''
          元素定位(改版后主要有兩個方法)。 
          兩個方法參數(shù)一樣
          第一個指定模式: 參考 selenium.webdriver.common.by.By; 
          class By:
              """
              Set of supported locator strategies.
              """
          
              ID = "id"
              XPATH = "xpath"
              LINK_TEXT = "link text"
              PARTIAL_LINK_TEXT = "partial link text"
              NAME = "name"
              TAG_NAME = "tag name"
              CLASS_NAME = "class name"
              CSS_SELECTOR = "css selector"
          第二個指定屬性的值 
          find_element(by=By.ID, value=None)    查找單個元素,WebElement。 內(nèi)部調(diào)用查找集合方法,然后返回第一個元素
          find_elements(by=By.ID, value=None)     查找集合, WebElement 集合
          '''
          
          # 根據(jù)ID查找 (百度首頁的百度一下按鈕)
          # button = browser.find_element(by=By.ID, value="su")
          # print(button)
          
          # 根據(jù)name屬性查找 (查找百度首頁的輸入框)
          # input = browser.find_element(by=By.NAME, value="wd")
          # print(input)
          
          # 根據(jù)xpath 語法查找 (查找百度首頁的輸入框)
          # input = browser.find_element(by=By.XPATH, value="//input[@name='wd']")
          # print(input)
          
          # 根據(jù)標簽的名字查找
          # inputs = browser.find_elements(by=By.TAG_NAME, value="input")
          # print(len(inputs))
          
          # 根據(jù)link 內(nèi)容查找 也就是根據(jù)<a>測試</a> 內(nèi)部的text 屬性查找
          # a = browser.find_element(by=By.LINK_TEXT, value="新聞")
          # print(a.text)
          
          # css 選擇器查找(找百度首頁輸入框)
          a = browser.find_element(by=By.CSS_SELECTOR, value="#kw")
          print(a.get_attribute("name"))
          
          # 關(guān)閉
          browser.close()
          
          1. 訪問元素信息
          from selenium import webdriver
          from selenium.webdriver.common.by import By
          
          browser = webdriver.Chrome("chromedriver.exe")
          browser.get("https://www.baidu.com/")
          
          # 根據(jù)link 內(nèi)容查找 也就是根據(jù)<a>測試</a> 內(nèi)部的text 屬性查找
          a = browser.find_element(by=By.LINK_TEXT, value="新聞")
          # 獲取屬性
          print(a.get_attribute("href"))
          # 獲取text
          print(a.text)
          # 獲取tag
          print(a.tag_name)
          
          # 關(guān)閉
          browser.close()
          
          1. 交互
          點擊: click()
          輸入: send_keys()
          清空輸入: clear()
          后退:browser.back()
          快進:browser.forward()
          模擬JS滾動: js = 'document.body.scrollTop=100000'
          		js = 'document.documentElement.scrollTop=100000'
          		browser.execute_script(js) # 執(zhí)行JS代碼
          獲取網(wǎng)頁源碼: browser.page_source		
          

          4. selenium 爬取百度

          一個簡單的例子,過程如下:

          1.打開百度首頁,睡眠2s

          2.輸入java,睡眠2s

          3.點擊百度一下按鈕,睡眠5s

          4.滾動到底部,睡眠5s

          5.翻到第二頁,睡眠5s

          6.點擊后退回退到第一頁,睡眠5s

          7.點擊前進再回去第二頁, 睡眠5s

          8.結(jié)束

          代碼:

          import time
          
          from selenium import webdriver
          # 1.打開百度首頁,睡眠2s
          from selenium.webdriver.common.by import By
          
          browser = webdriver.Chrome("chromedriver.exe")
          browser.get("https://www.baidu.com/")
          time.sleep(2)
          
          # 2.輸入java,睡眠2s
          input = browser.find_element(value="kw")
          input.send_keys("java")
          time.sleep(2)
          
          # 3.點擊百度一下按鈕,睡眠5s
          button = browser.find_element(value="su")
          button.click()
          time.sleep(5)
          
          # 4.滾動到底部,睡眠5s
          js = 'document.body.scrollTop=100000'
          browser.execute_script(js)
          time.sleep(5)
          
          # 5.翻到第二頁,睡眠5s
          nextBtn = browser.find_element(by=By.XPATH, value="//a[@class='n']")
          nextBtn.click()
          time.sleep(5)
          
          # 6. 點擊后退回退到第一頁,睡眠5s
          browser.back()
          time.sleep(5)
          
          # 7. 點擊前進再回去第二頁, 睡眠5s
          browser.forward()
          time.sleep(5)
          
          # 8. 關(guān)閉
          browser.close()
          

          5. selenium 不啟動瀏覽器模式

          打開瀏覽器再啟動會浪費時間,對爬蟲的性能也是個影響,還有一種就是不打開瀏覽器。

          如下參數(shù)是針對chrome 的全局參數(shù),不能自定義參數(shù)。

          from selenium import webdriver
          
          # 還有一些其他的參數(shù)
          '''
          # 添加UA
          options.add_argument('user-agent="MQQBrowser/26 Mozilla/5.0 (Linux; U; Android 2.3.7; zh-cn; MB200 Build/GRJ22; CyanogenMod-7) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1"')
          
          # 設(shè)置代理
          options.add_argument("--proxy-server=http://110.52.235.176:9999") # 設(shè)置代理,請求頭等,以列表的形式傳入多個參數(shù)
          
          # 設(shè)置編碼格式
          options.add_argument('lang=zh_CN.UTF-8') # 設(shè)置編碼格式
          
           # 啟動時最大化窗口
          options.add_argument('--start-maximized')
          
          # 指定瀏覽器分辨率
          options.add_argument('window-size=1920x3000') 
          
          # 谷歌文檔提到需要加上這個屬性來規(guī)避bug
          options.add_argument('--disable-gpu') 
          
           # 隱藏滾動條, 應(yīng)對一些特殊頁面
          options.add_argument('--hide-scrollbars')
          
          # 不加載圖片, 提升速度
          options.add_argument('blink-settings=imagesEnabled=false') 
          
          # 瀏覽器不提供可視化頁面. linux下如果系統(tǒng)不支持可視化不加這條會啟動失敗
          options.add_argument('--headless') 
          
          # 以最高權(quán)限運行
          options.add_argument('--no-sandbox')
          
          # 手動指定使用的瀏覽器位置
          options.binary_location = r"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" 
          
          #添加crx插件
          option.add_extension('d:\crx\AdBlock_v2.17.crx') 
          
          # 禁用JavaScript
          option.add_argument("--disable-javascript") 
          
          # 設(shè)置開發(fā)者模式啟動,該模式下webdriver屬性為正常值
          options.add_experimental_option('excludeSwitches', ['enable-automation']) 
          
          # 禁用瀏覽器彈窗
          prefs = {  
              'profile.default_content_setting_values' :  {  
                  'notifications' : 2  
               }  
          }  
          options.add_experimental_option('prefs',prefs)
          '''
          
          option = webdriver.ChromeOptions()
          # 瀏覽器不提供可視化頁面. linux下如果系統(tǒng)不支持可視化不加這條會啟動失敗
          option.add_argument("--headless")
          # 谷歌文檔提到需要加上這個屬性來規(guī)避bug
          option.add_argument('--disable-gpu')
          browser = webdriver.Chrome(executable_path="chromedriver.exe", options=option)
          browser.get("https://www.jd.com/")
          
          # 獲取網(wǎng)頁源碼
          print(browser.title)
          
          # 關(guān)閉
          browser.close()
          

          6. 以不打開瀏覽器的方式設(shè)置代理獲取當(dāng)前的IP信息

          from selenium import webdriver
          from selenium.webdriver.common.by import By
          
          option = webdriver.ChromeOptions()
          # 瀏覽器不提供可視化頁面. linux下如果系統(tǒng)不支持可視化不加這條會啟動失敗
          option.add_argument("--headless")
          # 谷歌文檔提到需要加上這個屬性來規(guī)避bug
          option.add_argument('--disable-gpu')
          # 添加代理
          option.add_argument("--proxy-server=http://221.11.233.111:4315")  # 設(shè)置代理,請求頭等,以列表的形式傳入多個參數(shù)
          
          browser = webdriver.Chrome(executable_path="chromedriver.exe", options=option)
          browser.get("http://www.ipdizhichaxun.com/")
          
          # 獲取網(wǎng)頁源碼
          result = browser.find_element(by=By.XPATH, value='//*[@class="result"]')
          print(result.text)
          
          # 關(guān)閉
          browser.close()
          

          結(jié)果:

          IP地址查詢結(jié)果:221.11.233.111,IP地址位置:寧夏石嘴山市(聯(lián)通)
          

          7. 傳cookie

          import time
          
          from selenium import webdriver
          
          browser = webdriver.Chrome(executable_path="chromedriver.exe")
          # 刪除原來的cookie
          browser.delete_all_cookies()
          # 注意需要訪問一次才能添加cookie。 selenium的默認域名為data,cookie中帶域名,在設(shè)置cookie時發(fā)現(xiàn)當(dāng)前域名不包含在cookie中,所以設(shè)置失敗,一直都是data的這個頁面
          browser.get("http://127.0.0.1:8088/inner/t4")
          # 攜帶cookie打開
          browser.add_cookie({'name': 'ABC', 'value': 'DEF'})
          browser.get("http://127.0.0.1:8088/inner/t4")
          browser.refresh()
          
          browser.close()
          time.sleep(10)
          

          8. 設(shè)置等待時間

          ? 如果不設(shè)置等待時間,find_element會立即查找元素,找不到就會立即報錯。一般會設(shè)置下時間,讓JS渲染完成再找元素。

          from selenium import webdriver
          from selenium.webdriver.common.by import By
          
          browser = webdriver.Chrome("chromedriver.exe")
          # 設(shè)置等待時間,最長等待20 s。 不設(shè)置等待事件, find_element 找不到元素會拋出異常,設(shè)置完成之后不會報異常,會阻塞直到拿取到對應(yīng)的元素或者達到指定時間
          browser.implicitly_wait(20)
          browser.get("http://baidu.com")
          print(browser.find_element(by=By.XPATH, value='//div[@class="content"]//img'))
          
          # 關(guān)閉
          browser.close()
          

          繼續(xù)改進,找不到元素返回None 或者其他處理:

          from selenium import webdriver
          from selenium.webdriver.common.by import By
          
          browser = webdriver.Chrome("chromedriver.exe")
          # 設(shè)置等待時間,最長等待20 s。 不設(shè)置等待事件, find_element 找不到元素會拋出異常,設(shè)置完成之后不會報異常,會阻塞直到拿取到對應(yīng)的元素或者達到指定時間
          browser.implicitly_wait(20)
          browser.get("http://baidu.com")
          
          try:
              print(browser.find_element(by=By.XPATH, value='//div[@class="content"]//img'))
          except Exception as e:
              # ignore
              print("沒有元素")
          
          # 關(guān)閉
          browser.close()
          

          9. selenuim 雙擊等事件

          可以用ActionChains, 最后調(diào)用其perform() 方法就是提交事件

                  # 找到第一個節(jié)點然后擴展
                  node1 = browser.find_element(by=By.XPATH,value=' //*[name()="svg"]//*[name()="g"]/*[@class="node"][1]')
                  # 調(diào)用ActionChains方法,生成一個動作
                  # 創(chuàng)建一個ActionChains, 然后可以進行一系列事件、包括右鍵、雙擊、單擊、拖拽、鍵盤按下、鍵盤抬起等事件
                  action = ActionChains(browser)
                  # 單擊
                  action.click(node1)
                  # 雙擊
                  # action.double_click(node1)
                  # 右擊
                  action.context_click(node1)
                  action.perform()
          

          補充:
          (1). 測試過程中發(fā)現(xiàn)browser 關(guān)閉之后,驅(qū)動程序不會關(guān)系,需要自己cmd 關(guān)閉下:

          taskkill -im chromedriver.exe -f
          

          (2). selenium 可以獲取元素大小location、size、rect
          這里需要注意獲取到的元素的坐標是相對于瀏覽器內(nèi)容區(qū)域左上角為原點,也就是
          不包含頭部瀏覽器菜單欄高度。

          from selenium import webdriver
          from selenium.webdriver.common.by import By
          
          browser = webdriver.Chrome("chromedriver.exe")
          browser.maximize_window()
          browser.get("https://www.baidu.com/")
          
          # css 選擇器查找(找百度首頁輸入框)
          a = browser.find_element(by=By.CSS_SELECTOR, value="#kw")
          print(a.get_attribute("name"))
          print(a.location)
          print(a.size)
          # rect = location + size
          print(a.rect)
          
          # 關(guān)閉
          browser.close()
          

          結(jié)果:

          wd
          {'x': 633, 'y': 222}
          {'height': 44, 'width': 550}
          {'height': 44, 'width': 550, 'x': 633, 'y': 222}
          

          (3) 上面提到獲取的元素的location是相對于瀏覽器可視區(qū)域的左上角為原點,也就是不包括菜單欄的高度。所以當(dāng)和pyautogui 結(jié)合,自動進行鼠標操作的時候需要加上菜單欄高度:

              @staticmethod
              def middle_location(element: WebElement):
                  ele_location = element.location
                  ele_size = element.size
                  middle_x = ele_location.get('x') + ele_size.get('width') / 2
                  middle_y = ele_location.get('y') + ele_size.get('height') / 2 + ChromeBrowserContext.browser_bar_height()
                  return middle_x, middle_y
          
              @staticmethod
              def browser_bar_height():
                  '''
                  獲取當(dāng)前broswer菜單欄高度
                  
                  :return: 
                  '''
                  # 執(zhí)行js 并且拿到結(jié)果
                  innerHeight = ChromeBrowserContext.__browser.execute_script("return window.innerHeight")
                  outerHeight = ChromeBrowserContext.__browser.execute_script("return window.outerHeight")
                  return outerHeight - innerHeight
          

          (4) 結(jié)合pyautogui 實現(xiàn)拖拽方法

              @staticmethod
              def dragToByXpath(xpath1: str, xpath2: str, time: int):
                  '''
                  拖拽元素
          
                  :param xpath1: 元素1
                  :param xpath2:  元素2
                  :param time:    時間
                  :return:
                  '''
                  browser = ChromeBrowserContext.getBrowser()
                  xpath1Element = browser.find_element(by=By.XPATH, value=xpath1)
                  x, y = ChromeBrowserContext.middle_location(xpath1Element)
                  pyautogui.moveTo(x, y)
                  xpath2Element = browser.find_element(by=By.XPATH, value=xpath2)
                  x, y = ChromeBrowserContext.middle_location(xpath2Element)
                  pyautogui.dragTo(x, y, time)
          
              @staticmethod
              def dragToByElement(element1: WebElement, element2: WebElement, time: int):
                  '''
                  拖拽元素
          
                  :param element1: 元素1
                  :param element2:  元素2
                  :param time: 時間
                  :return:
                  '''
                  x, y = ChromeBrowserContext.middle_location(element1)
                  pyautogui.moveTo(x, y)
                  x, y = ChromeBrowserContext.middle_location(element2)
                  pyautogui.dragTo(x, y, time)
          

          在自己的測試過程中發(fā)現(xiàn),selenium不支持動態(tài)修改header , 而且好像不能自定義header 進行請求。可以通過插件或者其他機制實現(xiàn)。

          =selenium-wire 簡單使用=

          官網(wǎng): https://github.com/wkeeling/selenium-wire 強烈建議直接使用這個庫

          ? selenium-wire 對selenium 做了擴展,讓程序有能力拿到requests 對象,然后獲取請求和響應(yīng)信息,并且可以修改請求頭(包括自定義的頭)、修改請求參數(shù)(包括param和請求體中的JSON數(shù)據(jù))、獲取修改響應(yīng)頭等信息。

          下面演示增加自己的header:(請求攔截器與響應(yīng)攔截器用法)

          from seleniumwire import webdriver
          
          
          # 攔截request
          def interceptor_request(request):
              del request.headers['mykey']  # Remember to delete the header first
              request.headers['mykey'] = 'mykey-value'  # Spoof the referer
          
          
          # 攔截response
          def interceptor_response(request, response):
              if request.url == 'http://localhost:8088/inner/t4':
                  response.headers['New-Header'] = 'Some Value'
          
          
          browser = webdriver.Chrome("chromedriver.exe")
          browser.request_interceptor = interceptor_request
          browser.response_interceptor = interceptor_response
          browser.get("http://localhost:8088/inner/t4")
          
          for request in browser.requests:
              if request.response:
                  print(
                      request.url,
                      request.response.status_code,
                      request.response.headers
                  )
          
          

          需要注意,進程結(jié)束之后browser 也是close 狀態(tài)的,無法進行后續(xù)頁面刷新或請求數(shù)據(jù)。

          補充:

          1. selenium open新窗口或跳轉(zhuǎn)頁面無法定位元素
            因為窗口句柄還停留在上一個頁面,所以導(dǎo)致無法定位元素。報錯 “元素不可交互”。
            因此要解決的問題就是先定位到當(dāng)前頁面(也就是跳轉(zhuǎn)后的頁面)然后再進行元素的定位。

          .selenium抓取動態(tài)網(wǎng)頁數(shù)據(jù)基礎(chǔ)介紹

          1.1 什么是AJAX

            AJAX(Asynchronouse JavaScript And XML:異步JavaScript和XML)通過在后臺與服務(wù)器進行少量數(shù)據(jù)交換,Ajax 可以使網(wǎng)頁實現(xiàn)異步更新,這意味著可以在不重新加載整個網(wǎng)頁的情況下,對網(wǎng)頁的某部分進行局部更新。傳統(tǒng)的網(wǎng)頁(不使用Ajax)如果需要更新內(nèi)容,必須重載整個網(wǎng)頁頁面。

            因為傳統(tǒng)的網(wǎng)頁在傳輸數(shù)據(jù)格式方面,使用的是XML語法,因此叫做AJAX,其實現(xiàn)在數(shù)據(jù)交互基本上都是使用JSON。使用AJAX加載的數(shù)據(jù),即使使用了JS將數(shù)據(jù)渲染到了瀏覽器中,在右鍵->查看網(wǎng)頁源代碼還是不能看到通過ajax加載的數(shù)據(jù),只能看到使用這個url加載的html代碼。

          1.2 獲取ajax數(shù)據(jù)的方式

            法1:直接分析ajax調(diào)用的接口。然后通過代碼請求這個接口。

            法2:使用Selenium+chromedriver模擬瀏覽器行為獲取數(shù)據(jù)。

          方式

          優(yōu)點

          缺點

          分析接口

          直接可以請求到數(shù)據(jù)。不需要做一些解析工作。代碼量少,性能高。

          分析接口比較復(fù)雜,特別是一些通過js混淆的接口,要有一定的js功底。容易被發(fā)現(xiàn)是爬蟲。

          selenium

          直接模擬瀏覽器的行為。瀏覽器能請求到的,使用selenium也能請求到。爬蟲更穩(wěn)定。

          代碼量多。性能低。

          1.3 Selenium+chromedriver獲取動態(tài)數(shù)據(jù)

            Selenium相當(dāng)于是一個機器人。可以模擬人類在瀏覽器上的一些行為,自動處理瀏覽器上的一些行為,比如點擊,填充數(shù)據(jù),刪除cookie等。chromedriver是一個驅(qū)動Chrome瀏覽器的驅(qū)動程序,使用他才可以驅(qū)動瀏覽器。當(dāng)然針對不同的瀏覽器有不同的driver。以下列出了不同瀏覽器及其對應(yīng)的driver:

          1. Chrome:https://sites.google.com/a/chromium.org/chromedriver/downloads
          2. Firefox:https://github.com/mozilla/geckodriver/releases
          3. Edge:https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/
          4. Safari:https://webkit.org/blog/6900/webdriver-support-in-safari-10/

          1.4 安裝Selenium和chromedriver

          1. 安裝SeleniumSelenium有很多語言的版本,有java、ruby、python等。我們下載python版本的就可以了。
          2. pip install selenium
          3. 安裝chromedriver:下載完成后,放到不需要權(quán)限的純英文目錄下就可以了。

          1.5 快速入門

            現(xiàn)在以一個簡單的獲取百度首頁的例子來講下Seleniumchromedriver如何快速入門:

          from selenium import webdriver
          
          
          # chromedriver的絕對路徑
          driver_path = r'D:\ProgramApp\chromedriver\chromedriver.exe'
          
          
          # 初始化一個driver,并且指定chromedriver的路徑
          driver = webdriver.Chrome(executable_path=driver_path)
          # 請求網(wǎng)頁
          driver.get("https://www.baidu.com/")
          # 通過page_source獲取網(wǎng)頁源代碼
          print(driver.page_source)

          1.6 selenium常用操作


          參考:Selenium的使用


          1.7 爬取拉鉤網(wǎng)職位信息

          直接直接分析ajax調(diào)用的接口爬取

          import requests
          from lxml import etree
          import time
          import re
          
          
          
          
          headers = {
              "Accept":"application/json, text/javascript, */*; q=0.01",
              "Accept-Encoding":"gzip, deflate, br",
              "Accept-Language":"zh-CN,zh;q=0.9",
              "Connection":"keep-alive",
              "User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36",
              "Referer":"https://www.lagou.com/jobs/list_python?labelWords=&fromSearch=true&suginput=",
              "Origin":"https://www.lagou.com",
              "Host":"www.lagou.com",
              "Content-Type":"application/x-www-form-urlencoded; charset=UTF-8",
              "Cookie":"_ga=GA1.2.1602115737.1553064534; user_trace_token=20190320144853-39b1375a-4adc-11e9-a253-525400f775ce; LGUID=20190320144853-39b13f88-4adc-11e9-a253-525400f775ce; WEBTJ-ID=20190408120043-169fb1afd63488-06179b118ca307-7a1437-2073600-169fb1afd648ed; _gid=GA1.2.1826141825.1554696044; sensorsdata2015jssdkcross=%7B%22distinct_id%22%3A%22169fb1bb2c41ea-04951e55adc96a-7a1437-2073600-169fb1bb2c58d0%22%2C%22%24device_id%22%3A%22169fb1bb2c41ea-04951e55adc96a-7a1437-2073600-169fb1bb2c58d0%22%7D; sajssdk_2015_cross_new_user=1; _putrc=4C5D2603888320CA; JSESSIONID=ABAAABAAADEAAFIB00F5DDE71D51610901CB9E0031812BA; login=true; unick=%E4%BC%8D%E6%99%93%E4%B8%BD; showExpriedIndex=1; showExpriedCompanyHome=1; showExpriedMyPublish=1; hasDeliver=49; gate_login_token=7b04a40da89145a1fbc90a3d719616d28c8b0a303344ac37; index_location_city=%E6%88%90%E9%83%BD; X_MIDDLE_TOKEN=1221e6b5040722dc86f5ceb557e11965; _gat=1; LGSID=20190408151935-a9976fbf-59ce-11e9-8cc8-5254005c3644; PRE_UTM=m_cf_cpc_baidu_pc; PRE_HOST=www.baidu.com; PRE_SITE=https%3A%2F%2Fwww.baidu.com%2Fbaidu.php%3Fsc.Ks000001qLT2daZnZWIez3ktR_jhHue3tONZubxU9mivhxeuj-Fxrjg6NnVcKTp-GYJ_YRvrc9_yOJ4uV-IEpfnPazPz7ctjve1qlDokCDfHYo9PV0uDfTmN1OunNUcCRU-sJuR8RZz60PAXzfKybAdvuCxUedbt8aWtTjAdCCuO298TwT8zN1-T5EG3kgkOweg0DHGIbvP55IZbr6.DY_NR2Ar5Od663rj6tJQrGvKD7ZZKNfYYmcgpIQC8xxKfYt_U_DY2yP5Qjo4mTT5QX1BsT8rZoG4XL6mEukmryZZjzsLTJplePXO-8zNqrw5Q9tSMj_qTr1x9tqvZul3xg1sSxW9qx-9LdoDkY4QPSl81_4pqO24rM-8dQjPakb3dS5iC0.U1Yk0ZDqs2v4VnL30ZKGm1Yk0Zfqs2v4VnL30A-V5HcsP0KM5gK1n6KdpHdBmy-bIykV0ZKGujYzr0KWpyfqnWcv0AdY5HDsnHIxnH0krNtknjc1g1nsnHNxn1msnfKopHYs0ZFY5HDLn6K-pyfq0AFG5HcsP0KVm1Y3nHDYP1fsrjuxnH0snNtkg1Dsn-ts0Z7spyfqn0Kkmv-b5H00ThIYmyTqn0K9mWYsg100ugFM5H00TZ0qPWm1PHm1rj640A4vTjYsQW0snj0snj0s0AdYTjYs0AwbUL0qn0KzpWYs0Aw-IWdsmsKhIjYs0ZKC5H00ULnqn0KBI1Ykn0K8IjYs0ZPl5fK9TdqGuAnqTZnVUhC0IZN15Hnkn1fknHT4P1DvPHR1PW61P100ThNkIjYkPHRYP10LrHTkPjTY0ZPGujd9rAwBmhuWrj0snjDzrj0Y0AP1UHYsPbm3wWTsrH0srjwarDcz0A7W5HD0TA3qn0KkUgfqn0KkUgnqn0KlIjYs0AdWgvuzUvYqn7tsg1Kxn7ts0Aw9UMNBuNqsUA78pyw15HKxn7tsg1nkrjm4nNts0ZK9I7qhUA7M5H00uAPGujYknjT1P1fkrjcY0ANYpyfqQHD0mgPsmvnqn0KdTA-8mvnqn0KkUymqn0KhmLNY5H00uMGC5H00uh7Y5H00XMK_Ignqn0K9uAu_myTqnfK_uhnqn0KEIjYs0AqzTZfqnanscznsc100mLFW5HRdPj0Y%26word%3D%25E6%258B%2589%25E5%258B%25BE%25E7%25BD%2591%26ck%3D1701.10.72.227.558.354.602.254%26shh%3Dwww.baidu.com%26sht%3D62095104_19_oem_dg%26us%3D1.0.1.0.1.301.0%26bc%3D110101; PRE_LAND=https%3A%2F%2Fwww.lagou.com%2Flp%2Fhtml%2Fcommon.html%3Futm_source%3Dm_cf_cpc_baidu_pc%26m_kw%3Dbaidu_cpc_cd_e110f9_d2162e_%25E6%258B%2589%25E5%258B%25BE%25E7%25BD%2591; Hm_lvt_4233e74dff0ae5bd0a3d81c6ccf756e6=1553064535,1554696044,1554707975; TG-TRACK-CODE=index_search; SEARCH_ID=16b25888bc6f489f981996ef505d6930; X_HTTP_TOKEN=3704e5535eab672a10080745514b2c7fac0430c282; Hm_lpvt_4233e74dff0ae5bd0a3d81c6ccf756e6=1554708001; LGRID=20190408152002-b9743b5b-59ce-11e9-9a84-525400f775ce",
              "X-Anit-Forge-Code":"0" ,
              "X-Anit-Forge-Token":'',
              "X-Requested-With":'XMLHttpRequest'
          }
          
          
          def get_detail_page_url():
              datas =[]
              url = 'https://www.lagou.com/jobs/positionAjax.json'
              form_data = {
                  "first":"faise",
                  "pn":1,
                  "kd":"python"
              }
              params = {
                  'city':'成都',
                  'needAddtionalResult':'false'
              }
              for pn in range(1,14):
                  form_data['pn'] = pn
                  response = requests.request(method='post',url=url,headers=headers,params = params,data = form_data)
                  result = response.json()
                  result_list = result['content']['positionResult']['result']
                  for position in result_list:
                      position_id = position['positionId']
                      detail_url = 'https://www.lagou.com/jobs/%s.html'%position_id
                      data = parse_detail_page(detail_url)
                      datas.append(data)
                      time.sleep(2)
              return datas
          
          
          def parse_detail_page(url):
              resonse = requests.request(method='get',url=url,headers = headers)
              text = resonse.text
              html = etree.fromstring(text,parser=etree.HTMLParser())
              position_name = html.xpath('//span[@class="name"]/text()')[0].strip()
              detail_list = html.xpath('//dd[@class="job_request"]//span')
              salary = detail_list[0].xpath('text()')[0].strip()
              city = detail_list[1].xpath('text()')[0].strip()
              city = re.sub(r'[\s/]','',city)
              work_years = detail_list[2].xpath('text()')[0].strip()
              work_years = re.sub(r'[\s/]','',work_years)
              education = detail_list[3].xpath('text()')[0].strip()
              education = re.sub(r'[\s/]','',education)
              job_details = ''.join(html.xpath('//div[@class="job-detail"]//p//text()'))
              data = {
                 "position_name":position_name,
                  "salay":salary,
                  "city":city,
                  "work_years":work_years,
                  "education":education,
                  "job_details":job_details
          
          
              }
              return data
          
          
          
          
          
          
          def main():
              datas = get_detail_page_url()
              print(datas)
          
          
          if __name__ == '__main__':
              main()

          selenium結(jié)合lxml爬取

          from selenium import webdriver
          from selenium.webdriver.support.ui import WebDriverWait
          from selenium.webdriver.support import expected_conditions as EC
          from selenium.webdriver.common.by import By
          
          
          from lxml import etree
          import re
          import time
          
          
          class Lagouspider(object):
              driver_path = r'E:\study\chromedriver\chromedriver.exe'
              def __init__(self):
                  self.driver = webdriver.Chrome(executable_path=Lagouspider.driver_path)
                  self.url = 'https://www.lagou.com/jobs/list_python?labelWords=&fromSearch=true&suginput='
                  self.positions = []
          
          
              def run(self):
                  while True:
                      self.driver.get(self.url)
                      source = self.driver.page_source
                      WebDriverWait(driver=self.driver,timeout=10).until(EC.presence_of_element_located((By.XPATH,'//div[@class="pager_container"]/span[last()]')))
                      self.parse_list_page(source)
                      next_btn = self.driver.find_element_by_xpath('//div[@class="pager_container"]/span[last()]')
                      if "pager_next_disabled"  in next_btn.get_attribute('class'):
                          break
                      else:
                          next_btn.click()
                      time.sleep(1)
          
          
              def parse_list_page(self,source):
                  html = etree.HTML(source)
                  links = html.xpath('//a[@class="position_link"]/@href')
                  for link in links:
                      self.request_detail_page(link)
                      time.sleep(1)
          
          
              def request_detail_page(self,url):
                  self.driver.execute_script("window.open('%s')"%url)
                  self.driver.switch_to.window(self.driver.window_handles[1])
                  WebDriverWait(self.driver,timeout=10).until(EC.presence_of_element_located((By.XPATH,'//span[@class="name"]')))
                  source = self.driver.page_source
                  self.parse_detail_page(source)
                  #關(guān)閉當(dāng)前詳情頁
                  self.driver.close()
                  #切換回職位列表頁
                  self.driver.switch_to.window(self.driver.window_handles[0])
          
          
              def parse_detail_page(self,source):
                  html = etree.HTML(source)
                  position_name = html.xpath('//span[@class="name"]/text()')[0].strip()
                  detail_list = html.xpath('//dd[@class="job_request"]//span')
                  salary = detail_list[0].xpath('text()')[0].strip()
                  city = detail_list[1].xpath('text()')[0].strip()
                  city = re.sub(r'[\s/]', '', city)
                  work_years = detail_list[2].xpath('text()')[0].strip()
                  work_years = re.sub(r'[\s/]', '', work_years)
                  education = detail_list[3].xpath('text()')[0].strip()
                  education = re.sub(r'[\s/]', '', education)
                  desc = ''.join(html.xpath('//dd[@class="job_bt"]//text()')).strip()
                  data = {
                      "name": position_name,
                      "salay": salary,
                      "city": city,
                      "work_years": work_years,
                      "education": education,
                      "desc": desc
                  }
                  print(data)
                  print('+'*40)
                  self.positions.append(data)
          
          
          if __name__ == '__main__':
              spider = Lagouspider()
              spider.run()


          希望本文對你有所幫助~~如果對軟件測試、接口測試、自動化測試、面試經(jīng)驗交流感興趣可以私聊我或關(guān)注公眾號“特斯汀軟件測試”。免費領(lǐng)取最新軟件測試大廠面試資料和Python自動化、接口、框架搭建學(xué)習(xí)資料!技術(shù)大牛解惑答疑,同行一起交流。


          主站蜘蛛池模板: 一区二区国产精品| 精品国产精品久久一区免费式 | 精品日本一区二区三区在线观看| 亚洲AV无码国产精品永久一区| 国产亚洲3p无码一区二区| 亚洲乱码一区二区三区国产精品| 中文国产成人精品久久一区| 冲田杏梨AV一区二区三区 | 日本一区二区高清不卡| 精品在线一区二区| 国内精品视频一区二区三区八戒| 一区二区三区电影网| 不卡一区二区在线| 国精产品一区一区三区有限公司| 成人精品视频一区二区三区不卡| 国偷自产视频一区二区久| 果冻传媒董小宛一区二区| 国产成人精品一区二三区在线观看| 国产一区二区三区小说| 麻豆精品人妻一区二区三区蜜桃| 中文字幕无线码一区2020青青| 色偷偷av一区二区三区| 日韩免费无码一区二区视频| 手机福利视频一区二区| 国产午夜精品一区二区三区小说 | 日本香蕉一区二区三区| 另类ts人妖一区二区三区| 亚洲国产精品成人一区| 久久精品国产一区二区三区日韩| 在线观看免费视频一区| 中文字幕精品一区二区| www.亚洲一区| 无码中文人妻在线一区二区三区| 亚洲综合一区二区精品导航| 中文字幕乱码一区二区免费| 一区二区三区视频在线| 成人国产精品一区二区网站公司| 色综合一区二区三区| 91久久精品午夜一区二区| 久久综合一区二区无码 | 日韩一区二区超清视频|