Python網路爬蟲 - Phantomjs, selenium/Chromedirver使用

LarryHai6發表於2019-01-22

json模組

   什麼是json?

      javascript中的物件和陣列

      物件 :{key:value}  取值:物件名.key

      陣列 :[...,...] 取值:陣列[索引值]

    作用

      json格式的字串 和 Python資料型別 之間的轉換

    常用方法

      json.loads() : json格式 --> Python資料型別

        json      python

      物件      字典

      陣列      列表

 

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)

 

 

    json.dumps() : Python資料型別 --> json格式

        python       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)

 

      注意

          json.dumps()預設使用ascii編碼

        新增引數ensure_ascii=False,禁用ascii編碼

 

動態網站資料抓取 - Ajax

    特點 :滾動滑鼠滑輪時載入

豆瓣電影排行榜資料抓取

    抓取目標 :豆瓣電影 - 排行榜 - 劇情 

                  電影名稱 、評分

 

import json
import requests
import csv


def get_movie(typ, number):
    url = "https://movie.douban.com/j/chart/top_list?"
    headers = {"Users-Agent": "Mozilla/5.0"}
    params = {
        "type": typ,
        "interval_id": "100:90",
        "action": "",
        "start": "0",
        "limit": number
    }

    res = requests.get(url, params=params, headers=headers)
    res.encoding = "utf-8"
    # html 為json陣列 [{}, {}, {}...]
    html = res.text
    # 陣列 -> 列表
    html = json.loads(html)
    # 用for迴圈遍歷每一個電影資訊{}
    for film in html:
        L = [film["title"], film["rating"][0]]
        # {"rating":["9.6","50"],...}
        with open("douban.csv", "a", newline="") as f:
            writer = csv.writer(f)
            writer.writerow(L)


dic = {
    "劇情": "11",
    "喜劇": "24",
    "動作": "5",
    "愛情": "13",
    "動畫": "25",
    "驚悚": "19",
    "科幻": "17",
}
cmd = input("請輸入電影型別:")
try:
    cmd = cmd.strip()
    get_movie(dic[cmd], input("請輸入數量:"))
except KeyError:
    print("型別不存在")
else:
    print("爬取成功呢")

 

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

    selenium

    定義 :Web自動化測試工具,應用於Web自動化測試

    特點

      可以執行在瀏覽器,根據指定命令操作瀏覽器,讓瀏覽器自動載入頁面

      只是工具,不支援瀏覽器功能,需要與第三方瀏覽器結合使用

    phantomjs

      定義 :無介面瀏覽器(無頭瀏覽器)

      特點

        把網站載入到記憶體進行頁面載入

        執行高效

      安裝

      Windows

        將下載的可執行檔案放到Python安裝目錄的Scripts目錄下

  C:\Python36\Scripts

      Ubuntu

        將下載的phantomjs放到一個路徑下

新增環境變數:

  vi .bashrc 新增

  export PHANTOM_JS=/home/.../phantomjs-2.1.1-...

  export PATH=$PHANTOM_JS/bin:$PATH

  終端:source .bashrc

  終端:phantomjs

# 匯入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()



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()

 

  常用方法

    driver.get(url)

    driver.page_source : 獲取響應的html原始碼

    driver.page_source.find("字串")

      作用 :從html原始碼中搜尋指定字串

         -1 :查詢失敗

 非-1   :查詢成功

 

driver = webdriver.PhantomJS()
driver.get("http://www.baidu.com/")
r = driver.page_source.find("ABCDEFG")

 

  單元素查詢

      1、driver.find_element_by_id("").text

      2、driver.find_element_by_class_name("")

      3、driver.find_element_by_xpath('xpath表示式')

      4、如果匹配到多個節點,則只返回第1個節點物件

      多元素查詢

        driver.find_elements_by_....

        注意

          如果結果1個,則返回節點物件,不是列表

如果結果N個,則返回列表

 

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()

 

      物件名.send_keys("內容")

      物件名.click()

    案例1 :登入豆瓣網站

 

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("賬號")
# 密碼
pwd = driver.find_element_by_name("form_password")
pwd.send_keys("密碼")
# 驗證碼
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()

 

  操作鍵盤

      導模組

      from selenium.webdrier.common.keys import Keys

      常用方法

 

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()

 

鬥魚直播網站主播資訊抓取(JS分頁載入)

      抓取目標 :主播名稱 、觀眾人數

        主播 :class -> dy-name ellipsis fl

        //div[@id="live-list-content"]//span[@class="dy-name ellipsis fl"]

 

        人數 :class -> dy-num fr

        //div[@id="live-list-content"]//span[@class="dy-num fr"]

 

      下一頁按鈕(能點) :class -> shark-pager-next

      下一頁按鈕(不能點)

        class -> shark-pager-next shark-pager-disable shark-pager-disable-next

 

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)

 

  Chromdriver如何設定無介面模式

 

    1、opt = webdriver.ChromeOptions()
    2、opt.set_headless()
    3、driver = webdriver.Chrome(options=opt)
    4、driver.get(url)


 

京東商品爬取

    1、目標

      1、商品名稱

      2、商品價格

      3、評論數量

      4、商家名稱

 

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
    # 點選下一頁

 

相關文章