1. 程式人生 > >利用selenium爬取動態渲染的頁面

利用selenium爬取動態渲染的頁面

說明

    對於有些網站來說,他的網頁不是純HTML標籤加載出來的,而是用javascript渲染出來的,對於這樣的網頁,如果單純的靠正則表示式、XPath來解析是行不通的。對於這樣的網頁,一是我們可以分析ajax請求,分析ajax引數發現其規律,自行模擬ajax請求(對於如何利用ajax引數爬取網頁資料博主前面已經提到過),二是如果通過ajax引數無法發現其規律,我們可以利用selenium來模擬瀏覽器,說白了我們通過利用selenium和chrome driver就可以通過利用程式碼來模擬使用者在瀏覽器上的各種互動了。 

分析

#!/usr/bin/env python 
# -*- coding:utf-8 -*-
import re
from urllib.parse import quote
import csv
from pyquery import PyQuery
from selenium import webdriver
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
browser=webdriver.Chrome()  #所用瀏覽器為谷歌瀏覽器
wait=WebDriverWait(browser,3)  #設定響應的最長等待時間為3秒
KEYWORD='python'   #提取出要爬取的關鍵字
#定義函式,傳入爬取頁碼進行爬取
def get_one_page(page):
    print('正在爬取第'+str(page)+'頁')
    #quote函式對中文進行url編碼,防止亂碼
    url='https://s.taobao.com/search?q='+quote(KEYWORD)
    try:
        browser.get(url)   #get方式請求網頁
        if page>1:         #如果頁碼大於1,先進行跳頁操作
            input=wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,'.form .input.J_Input'))) #獲取到跳頁輸入框
            submit=wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,'.form .btn.J_Submit')))#獲取到確定按鈕
            input.clear()  #模擬清空頁碼
            input.send_keys(page) #模擬輸入頁碼
            submit.click()  #模擬點選操作
        wait.until(EC.text_to_be_present_in_element((By.CSS_SELECTOR,'ul.items>li.item.active>span.num'),str(page))) #確認已經跳轉到目標頁碼
        wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,'.m-itemlist .items .item')))   #等待商品列表載入完成
        #解析得到商品列表
        html=browser.page_source  #獲取該頁的原始碼
        doc=PyQuery(html)         #生成PyQuery物件
        items=doc('.m-itemlist .items .item').items()   #得到商品列表的生成器
        for item in items:
            price=item.find('.price').text()   #得到每件商品的價格
            price=re.sub('¥\n','',price)       #對得到的價格進行處理
            product={
                'store':item.find('.shop').text(),
                'image':item.find('.pic .img').attr('data-src'),
                'price':price
            }                                   #把商品的店鋪,圖片url以及價格存到字典中
            print(product)
            yield product                      #將每個商品的字典新增到生成器當中
    except TimeoutException:
        get_one_page(page)     #請求超時重新呼叫該方法再一次請求

if __name__=='__main__':
    with open('result.csv','a',newline='') as csvfile:   #以追加的方式開啟本地csv檔案,newline引數用來去掉空白行
        filenames=['store','image','price']              #表頭
        csvwriter=csv.DictWriter(csvfile,filenames)
        csvwriter.writeheader()                            #寫入表頭
        for page in range(1,101):                          #迴圈100個生成器(100頁)
            products=get_one_page(page)                    #得到每頁的所有商品
            for product in products:                      #遍歷每頁的商品
                csvwriter.writerow(product)                #每個商品的資訊寫到csv當中
    print('爬取完畢')

由於本人比較懶,在程式碼段直接做了詳細的解釋了,在此不再贅述!