1. 程式人生 > >python 基礎 網路爬蟲 day05

python 基礎 網路爬蟲 day05

目錄

day04

  1. lxml解析庫
    1. 使用流程
      1. from lxml import etree
      2. parseHtml = etree.HTML(html)
      3. parseHtml.xpath('xpath表示式')
    2. xpath匹配規則
      1. 獲取節點物件://div[@class="Tiger"]
      2. 獲取節點屬性值://div[@class="T"]//a/@src
      3. 函式://div[contains(@class,"a")]//a/@href
    3. xpath高階
      1. 基準xpath表示式(節點物件列表)
      2. for r in [節點物件列表]:     username = parseHtml.xpath('./xpath表示式')     ... ...

day05

1.json模組

  1. 什麼是json? javascript中的物件和陣列 物件:{key:value}  取值:物件名.key 陣列:[...,...]           取值:陣列[索引值]
  2. 作用 json格式的字串 和 python資料型別 之間的轉換
  3. 常用方法
    1. json.loads():json格式  -->  Python資料型別 json               python 物件              字典 陣列              列表
      '''01_json.loads示例.py'''
      import json
      
      # json格式的陣列
      jsarray = '[1,2,3,4]'
      # 陣列 -> 列表
      L = json.loads(jsarray)
      print(type(L),L)
      
      # json格式物件
      jsobj = '{"city":"天地會","name":"步驚雲"}'
      # 物件 -> 字典
      D = json.loads(jsobj)
      print(type(D),D)
    2. json.dumps():Python資料型別 --> json格式 python           json 字典               物件 列表               陣列 元組               陣列
      '''02_json.dunps示例.py'''
      import json
      
      L = [1,2,3,4]
      T = (1,2,3,4)
      D = {"city":"天地會","name":"聶風"}
      # python格式 -> json格式
      jsarray1 = json.dumps(L)
      print(type(jsarray1),jsarray1)
      
      jsarray2 = json.dumps(T)
      print(type(jsarray2),jsarray2)
      
      jsobj = json.dumps(D,ensure_ascii=False)
      print(type(jsobj),jsobj)
      ##注意:
      1. json.dumps()預設使用的是ascii編碼
      2. 新增引數ensure_ascii=False,禁用ascii編碼

2.動態網站資料抓取 - Ajax

  1. 特點:滾動滑鼠滑輪時載入
  2. 案例:豆瓣電影排行榜資料抓取
    1. 抓取目標:豆瓣電影 - 排行榜 - 劇情                   電影名稱,評分
    2. 程式碼實現
      '''03_豆瓣電影抓取-Ajax.py'''
      import requests
      import json
      import csv
      num=input('請輸入要爬取的數量:')
      url='https://movie.douban.com/j/chart/top_list'
      headers={
              'User-Agent':'Mozilla/5.0',
              }
      params={
              "type":"11",
              "interval_id":"100:90",
              "action":'',
              "start":"0",
              "limit":num,
              }
      res=requests.get(url,params=params,headers=headers)
      res.encoding='utf-8'
      # html為json格式的陣列[{電影1資訊},{},{}]
      html=res.text
      html=json.loads(html)
      #print(html)
      #用for迴圈遍歷每一個電影資訊
      
      with open('豆瓣電影.csv','a',newline='') as f:
          writer=csv.writer(f)
          for film in html:
              name=film['title']
              score=film['rating'][0]
              L=[name,score]
              writer.writerow(L)
      稍微高階點
      '''03_豆瓣電影抓取-Ajax.py'''
      import requests
      import json
      import csv
      
      # url要寫抓到的GET :URL
      url = "https://movie.douban.com/j/chart/top_list?"
      headers = {"User-Agent":"Mozilla/5.0"}
      L = ["劇情","喜劇","動作"]
      tp_list = [{"劇情":"11"},{"喜劇":"24"},{"動作":"5"}]
      tp = input("請輸入電影型別:")
      
      if tp in L:
          num = input("請輸入要爬取的數量:")
          for film_dict in tp_list:
              for key,value in film_dict.items():
                  if tp == key:
                      params = {
                              "type":value,
                              "interval_id":"100:90",
                              "action":"",	
                              "start":"0",
                              "limit":num
                          }
                      
                      res = requests.get(url,params=params,headers=headers)
                      res.encoding = "utf-8"
                      # html為json格式的陣列[{電影1資訊},{},{}]
                      html = res.text
                      # 陣列 -> 列表
                      html = json.loads(html)
                      # 用for迴圈遍歷每一個電影資訊{}
                      for film in html:
                          name = film['title']
                          score = film["rating"][0]
                          #{"rating":["9.6","50"],...}
                          with open("豆瓣電影.csv","a",newline="") as f:
                              writer = csv.writer(f)
                              L = [name,score]
                              writer.writerow(L)
      else:
          print("您輸入的型別不存在!")
       

3.selenium + phantomjs 強大的網路爬蟲組合

  1. selenium
    1. 定義:Web自動化測試工具,應用於Web自動化測試
    2. 特點
      1. 可以執行在瀏覽器,根據指定命令操作瀏覽器,讓瀏覽器自動載入頁面
      2. 只是工具,不支援瀏覽器功能,需要與第三方瀏覽器結合使用
  2. phantomjs
    1. 定義:無介面瀏覽器(無頭瀏覽器)
    2. 特點
      1. 把網站載入到記憶體進行頁面載入
      2. 執行高效
    3. 安裝
      1. windows
        1. 將下載的可執行檔案放到Python安裝目錄的Scripts目錄下 在cmd下搜尋 where python 然後找到python地址,放到Scripts目錄  
      2. Ubuntu
        1. 將下載的phantomjs放到一個路徑下
        2. 新增環境變數 vi .bashrc 新增 export PHANTOM_JS=/home/.../phantomjs-2.1.1-... export PATH=$PHANTOM_JS/bin:$PATH 終端:source .bashrc 終端:phantomjs
  3. 示例程式碼
    1. 示例程式碼1:
      '''05_phantomjs+selenium示例1.py'''
      # 匯入selenium庫中的webdriver介面
      from selenium import webdriver
      
      # 建立phantomjs瀏覽器物件
      driver = webdriver.PhantomJS()
      # 發請求 get()
      driver.get("http://www.baidu.com/")
      print(driver.page_source)
      ## 獲取網頁截圖
      #driver.save_screenshot("百度.png")
      #print("圖片儲存成功")
      ## 關閉
      #driver.quit()
    2. 示例程式碼2:
      '''06_phantomjs+selenium示例2.py'''
      from selenium import webdriver
      import time
      
      # 建立瀏覽器物件
      driver = webdriver.PhantomJS()
      # 開啟頁面
      driver.get("http://www.baidu.com/")
      # 傳送文字到搜尋框
      kw = driver.find_element_by_id("kw")
      kw.send_keys("美女")
      # 點選 "百度一下"
      su = driver.find_element_by_id("su")
      su.click()
      time.sleep(1)
      # 獲取截圖
      driver.save_screenshot("美女.png")
      # 關閉瀏覽器
      driver.quit()
  4. 常用方法
    1. driver.get(url) 開啟網站
    2. driver.page_source:獲取響應的html原始碼
    3. driver.page_source.find('字串')
      1. 作用:從html原始碼中搜索指定字串 -1:查詢失敗 非-1:查詢成功
    4. 單元素查詢
      1. driver.find_element_by_id(" ").text
      2. driver.find_element_by_class_name(" ")
      3. driver.find_element_by_xpath('xpath表示式')
      4. 如果匹配到多個節點,則只返回第一個節點物件
    5. 多元素查詢
      1. driver.find_elements_by_...
      2. 注意
        1. 如果結果1個,則返回節點物件,不是列表
        2. 如果結果n個,則返回列表
      3. 示例
        '''08_driver.find查詢元素示例.py'''
        from selenium import webdriver
        
        driver = webdriver.Chrome()
        driver.get("https://www.qiushibaike.com/")
        
        # 查詢單個節點 element
        r_One = driver.find_element_by_class_name("content")
        print(r_One.text)
        
        # 查詢多個節點 elements
        r_Many = driver.find_elements_by_class_name("content")
        for r in r_Many:
            print(r.text)
            print()
        
        driver.quit()
    6. 物件名.send_keys("內容")
    7. 物件名.click()
  5. 案例1:登入豆瓣網站
    '''09_selenium+Chrome登陸豆瓣案例.py'''
    from selenium import webdriver
    import time
    
    # 建立瀏覽器物件,發請求
    driver = webdriver.Chrome()
    driver.get("https://www.douban.com/")
    time.sleep(0.5)
    # 獲取截圖(驗證碼)
    driver.save_screenshot("驗證碼.png")
    # 找 使用者名稱、密碼、驗證、登陸豆瓣按鈕
    uname = driver.find_element_by_name("form_email")
    uname.send_keys("19921510089")
    # 密碼
    pwd = driver.find_element_by_name("form_password")
    pwd.send_keys("zhanshen001")
    # 驗證碼
    key = input("請輸入驗證碼:")
    yzm = driver.find_element_by_id("captcha_field")
    yzm.send_keys(key)
    driver.save_screenshot("完成.png")
    # 點選登陸按鈕
    login = driver.find_element_by_class_name("bn-submit")
    login.click()
    time.sleep(1)
    driver.save_screenshot("登陸成功.png")
    # 關閉瀏覽器
    driver.quit()
  6. 操作鍵盤
    1. 導模組 from selenium.webdrier.common.keys import Keys
    2. 常用方法
      '''10_driver操作鍵盤示例.py'''
      from selenium import webdriver
      # 操作鍵盤
      from selenium.webdriver.common.keys import Keys
      import time
      
      # 建立瀏覽器物件,發請求
      driver = webdriver.Chrome()
      driver.get("http://www.baidu.com/")
      # 百度搜索框輸入python
      kw = driver.find_element_by_id("kw")
      kw.send_keys("python")
      driver.save_screenshot("01_python.png")
      
      # 全選 :Ctrl + a
      kw = driver.find_element_by_id("kw")
      kw.send_keys(Keys.CONTROL,'a')
      driver.save_screenshot("02_CtrlA.png")
      
      # 剪下 :Ctrl + x
      kw = driver.find_element_by_id("kw")
      kw.send_keys(Keys.CONTROL,'x')
      driver.save_screenshot("03_CtrlX.png")
      
      # 貼上 :Ctrl + v
      kw = driver.find_element_by_id("kw")
      kw.send_keys(Keys.CONTROL,'v')
      driver.save_screenshot("04_CtrlV.png")
      
      # 清空搜尋框 : 物件名.clear()
      kw = driver.find_element_by_id("kw")
      kw.clear()
      driver.save_screenshot("05_Clear.png")
      
      # 輸入 :達內科技
      kw = driver.find_element_by_id("kw")
      kw.send_keys("達內科技")
      driver.save_screenshot("06_Tarena.png")
      
      # 輸入 :回車
      kw = driver.find_element_by_id("kw")
      kw.send_keys(Keys.ENTER)
      time.sleep(1)
      driver.save_screenshot("07_Enter.png")
      
      # 關閉瀏覽器
      driver.quit()
  7. 案例2:鬥魚直播網站主播資訊抓取
    1. 抓取目標:主播名稱,觀眾人數
      1. 主播:class --  dy-name ellipsis fl //div[@id="live-list-content"]//span[@class="dy-name ellipsis fl"]
      2. 人數:class --  dy-num fr //div[@id="live-list-content"]//span[@class="dy-num fr"]
      3. 下一頁按鈕(能點的按鈕):class -> shark-pager-next
      4. 下一頁按鈕(不能點的按鈕):
    2. 程式碼實現
      '''11_鬥魚直播抓取案例.py'''
      from selenium import webdriver
      from lxml import etree
      import time
      
      # 把Chrome設定無介面瀏覽器
      opt = webdriver.ChromeOptions()
      opt.set_headless()
      # 建立瀏覽器物件,發請求
      driver = webdriver.Chrome(options=opt)
      driver.get("https://www.douyu.com/directory/all")
      i = 1
      
      # 迴圈
      while True:
          # 解析(driver.page_source)
          # 獲取主播名稱 和 觀眾人數
          parseHtml = etree.HTML(driver.page_source)
          names = parseHtml.xpath('//div[@id="live-list-content"]//span[@class="dy-name ellipsis fl"]')
          numbers = parseHtml.xpath('//div[@id="live-list-content"]//span[@class="dy-num fr"]')
          
          for name,number in zip(names,numbers):
              print("\t主播名稱:%s \t觀眾人數:%s" %
                    (name.text.strip(),number.text.strip()))
              #for name,number in [("主播1","20萬"),("主播2","15萬")]
          print("第%d頁爬取成功" % i)
          i += 1
          # 判斷是否需要點選下一頁
          # 能點 :點選,繼續迴圈
          if driver.page_source.find("shark-pager-disable-next") == -1:
              driver.find_element_by_class_name("shark-pager-next").click()
              time.sleep(1)
          else:
              break
          # 不能點 :break
      
      print("一共爬取了%d頁" % i)
  8. Chromdriver如何設定無介面模式     1、opt = webdriver.ChromeOptions()     2、opt.set_headless()     3、driver = webdriver.Chrome(options=opt)     4、driver.get(url)
  9. 案例3:京東商品爬取
    1. 目標
      1. 商品名稱
      2. 商品價格
      3. 評論數量
      4. 商家名稱
    2. 程式碼實現
      '''12_京東商品爬取.py'''
      from selenium import webdriver
      import time
      import csv
      
      # 接受使用者輸入,訪問京東
      pro = input("請輸入要爬取的商品:")
      driver = webdriver.Chrome()
      driver.get("https://www.jd.com/")
      i = 1
      # 傳送文字到搜尋框,點選搜尋
      text = driver.find_element_by_class_name("text")
      text.send_keys(pro)
      
      button = driver.find_element_by_class_name("button")
      button.click()
      time.sleep(1)
      
      while True:
          # 動態載入-->全部載入
          # 執行指令碼,進度條拉到底部
          driver.execute_script(
             'window.scrollTo(0,\
              document.body.scrollHeight)')
          time.sleep(2) 
          # 正常解析爬取
          r_list = driver.find_elements_by_xpath\
                ('//div[@id="J_goodsList"]//li')
      
          # r為每一個商品的節點物件
          for r in r_list:
              m = r.text.split('\n')
              # ["¥52.80","Python...","200+",]
              price = m[0]
              name = m[1]
              commit = m[2]
              market = m[3]
              
              with open("商品.csv","a",newline="",encoding="gb18030") as f:
                  writer = csv.writer(f)
                  L = [name.strip(),price.strip(),
                       commit.strip(),market.strip()]
                  writer.writerow(L)
          
          print("第%d頁爬取成功" % i)
          i += 1
          # 點選下一頁
          #未寫迴圈
    3. 小提示:

      JS控制滾動條的位置: window.scrollTo(x,y);

      豎向滾動條置頂(window.scrollTo(0,0); 豎向滾動條置底 window.scrollTo(0,document.body.scrollHeight) 當前視窗driver.execute_script('window.scrollTo(0,document.body.scrollHeight)')  

今日示例