1. 程式人生 > >使用selenium和pyquery來爬取淘寶ipad商品資訊

使用selenium和pyquery來爬取淘寶ipad商品資訊

使用selenium爬取淘寶ipad商品資訊

  • 爬取過程中的重點是實現翻頁、提取商品資訊、儲存至資料庫

訪問淘寶

爬取過程中可以通過掃描二維碼的方式來登陸淘寶,要注意的是訪問不能過於頻繁,否則ip會被限制訪問。 防止ip被限制訪問可以通過使用代理,或者降低訪問的頻率

1.獲取商品的總頁數

  1. 檢查其html原始碼 可通過
  2. 可通過CSS選擇器來選取總頁數,進而獲取其總頁數 在這裡插入圖片描述 程式碼如下:
def search(url):  # 獲取商品的總頁數
    try:
        browser.get(url)  # 訪問url
        browser.maximize_window()  # 最大化瀏覽器
        sum = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '#mainsrp-pager > div > div > div > div.total')))
        # 等待總頁數的加載出現
        return int(sum.text[1:-2]) # 擷取價格的數字部分,第二個元素至倒數第二個元素
        # 返回總頁數
    except TimeoutException:
        search(url)

2.實現翻頁操作

  1. 這裡通過頁數輸入框和確定按鈕來實現翻頁操作,而不是用下一頁按鈕。因為如果使用下一頁按鈕的話,需要記錄頁數,而且如果中間出錯的話,無法判別正確頁數是哪一個,及後續操作無法進行 在這裡插入圖片描述
  2. 同樣的,通過CSS選擇器來選取輸入框和確定按鈕
input = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,'#mainsrp-pager > div > div > div > div.form > input')))
            # 等待輸入框加載出現,並選取
submit = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,'#mainsrp-pager > div > div > div > div.form > span.btn.J_Submit')))
            # 等待確定按鈕加載出現(element_to_be_clickable可點選元素,來確定是按鈕元素),並選取
  1. 翻頁時,首先清空輸入框中的內容,再輸入目標頁,單擊確定按鈕,實現翻頁
input.clear()
# 清除輸入框內容
input.send_keys(page)
# 將要跳轉的頁數輸入到輸入框中
submit.click()
# 點選確定按鈕
  1. 翻頁之後還需要判斷該頁是否與我們的目標頁是同一頁 選取高亮的頁碼數,與目標頁數比較
wait.until(EC.text_to_be_present_in_element((By.CSS_SELECTOR, '#mainsrp-pager > div > div > div > ul > li.item.active > span'), str(page)))
# 選擇高亮的頁碼數,判斷它是否等於我們所跳轉的頁數(str(page))

接著,在分析原始碼的時候我們發現,所有的資訊都在class值為item的標籤之中,所以首先要等在這些原始碼載入成功,進而在其內通過pyquery提取資訊 這裡有五個item,內含五個商品的資訊(item與之後的內容間隔一個空格,所以選擇的時候class屬性直接指定為item) 在這裡插入圖片描述 內部資訊如下: 在這裡插入圖片描述 在這裡插入圖片描述 提取資訊的程式碼如下:

def get_products():
    # 用pyquery解析網頁
    html = browser.page_source  # 獲取原始碼
    doc = pq(html)  # 生成pyquery物件
    items = doc('#mainsrp-itemlist .items .item').items()  # items()得到一個可遍歷的生成器
    for item in items:
        product = {
            'image': item('.pic').find('img').attr('data-src'),  # 提取image
            'price': item('.price').text(),  # 提取價格
            'deal': item('.deal-cnt').text()[:-3],   # 擷取第一個字元至倒數第三個字元
            'location': item('.location').text()  # 提取店鋪位置
        }
        print(product)  # 列印資訊
        save_to_mongo(product)  # 將提取到的資訊儲存到MongoDB資料庫中

3.將資料儲存到MongoDB資料庫中

使用pymongo庫與MongoDB進行互動 程式碼如下:

import pymongo

MONGO_URL = 'localhost'  # 指定ip地址,localhost本地地址
MONGO_DB = 'taobao'  # 指定資料庫名
MONGO_TABLE = 'iPad'  # 指定資料表名(在mongodb中叫做集合)
client = pymongo.MongoClient(MONGO_URL)  # 建立一個MONGODB連線物件
db = client[MONGO_DB]  # 連線到MONGO_DB資料庫
def save_to_mongo(result):  # 將資料匯入到資料庫中
    try:
        if db[MONGO_TABLE].insert(result):   # 如果在MONGO_DB中插入資料成功,執行print語句
            print('儲存成功')
    except Exception:
        print('儲存失敗')

END…

全部程式碼如下:

from selenium import webdriver
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from pyquery import PyQuery as pq
import time
import pymongo  # 匯入pymongo庫,與mongodb互動


browser = webdriver.Firefox()  # 建立火狐瀏覽器物件
wait = WebDriverWait(browser, 10)  # 建立等待物件,最大等待時間10s,超過10s丟擲TimeOutException異常
MONGO_URL = 'localhost'  # 指定ip地址,localhost本地地址
MONGO_DB = 'taobao'  # 指定資料庫名
MONGO_TABLE = 'iPad'  # 指定資料表名(在mongodb中叫做集合)


def search(url):  # 獲取商品的總頁數
    try:
        browser.get(url)  # 訪問url
        browser.maximize_window()  # 最大化瀏覽器
        sum = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '#mainsrp-pager > div > div > div > div.total')))
        # 等待總頁數的加載出現
        return int(sum.text[1:-2])
        # 返回總頁數
    except TimeoutException:
        search(url)


def index_page(page):  # 換頁,跳轉正第page頁
    try:
        if page > 1:
            input = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,'#mainsrp-pager > div > div > div > div.form > input')))
            # 等待輸入框加載出現,並選取
            submit = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR,'#mainsrp-pager > div > div > div > div.form > span.btn.J_Submit')))
            # 等待確定按鈕加載出現(element_to_be_clickable可點選元素,來確定是按鈕元素)
            input.clear()
            # 清除輸入框內容
            input.send_keys(page)
            # 將要跳轉的頁數輸入到輸入框中
            submit.click()
            # 點選確定按鈕
        wait.until(EC.text_to_be_present_in_element((By.CSS_SELECTOR, '#mainsrp-pager > div > div > div > ul > li.item.active > span'), str(page)))
        # 選擇高亮的頁碼數,判斷它是否等於我們所跳轉的頁數
        wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '#mainsrp-itemlist .items .item')))
        # 等待商品資訊的載入
        get_products()  # 獲取商品資訊
    except TimeoutException:
        index_page(page)


def get_products():
    # 用pyquery解析網頁
    html = browser.page_source
    doc = pq(html)
    items = doc('#mainsrp-itemlist .items .item').items()  # items()得到一個可遍歷的生成器
    for item in items:
        product = {
            'image': item('.pic').find('img').attr('data-src'),
            'price': item('.price').text(),
            'deal': item('.deal-cnt').text()[:-3],   # 擷取第一個字元至倒數第三個字元
            'location': item('.location').text()
        }
        print(product)
        save_to_mongo(product)  # 將提取到的資訊儲存到MongoDB資料庫中


client = pymongo.MongoClient(MONGO_URL)  # 建立一個MONGODB連線物件
db = client[MONGO_DB]  # 連線到MONGO_DB資料庫


# 資料匯入資料庫中
def save_to_mongo(result):
    try:
        if db[MONGO_TABLE].insert(result):   # 如果在MONGO_DB中插入資料成功,執行print語句
            print('儲存成功')
    except Exception:
        print('儲存失敗')


def main():
    try:
        url = 'https://s.taobao.com/search?q=iPad'
        total = search(url)
        for i in range(1, total + 1):
            index_page(i)
    except Exception:   # Exception 異常的父類
        print('error!')


if __name__ == '__main__':
    main()