爬蟲---實現爬取京東商品(手辦)

效果圖:

在這裏插入圖片描述

源代碼:

from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
import selenium.common.exceptions
import urllib
import json
import csv
import time

class JdSpider():
    def open_file(self):
        self.fm = input('請輸入文件保存格式(txt、json、csv):')
        while self.fm!='txt' and self.fm!='json' and self.fm!='csv':
            self.fm = input('輸入錯誤,請重新輸入文件保存格式(txt、json、csv):')
        if self.fm=='txt' :
            self.fd = open('Jd.txt','w',encoding='utf-8')
        elif self.fm=='json' :
            self.fd = open('Jd.json','w',encoding='utf-8')
        elif self.fm=='csv' :
            self.fd = open('Jd.csv','w',encoding='utf-8',newline='')

    def open_browser(self):  #打開瀏覽器
        self.browser = webdriver.Chrome()  #打開Chrome
        self.browser.implicitly_wait(10)  #隱式等待10秒
        self.wait = WebDriverWait(self.browser,10)  #超出最長時間(10s),拋出異常

    def init_variable(self):
        self.data = zip()
        self.isLast = False

    def parse_page(self):  #解析頁面
        try:
            skus = self.wait.until(EC.presence_of_all_elements_located((By.XPATH,'//li[@class="gl-item"]')))
            skus = [item.get_attribute('data-sku') for item in skus]  #先存儲到 item 中
            links = ['https://item.jd.com/{sku}.html'.format(sku=item) for item in skus]
            prices = self.wait.until(EC.presence_of_all_elements_located((By.XPATH,'//div[@class="gl-i-wrap"]/div[2]/strong/i')))
            prices = [item.text for item in prices]
            names = self.wait.until(EC.presence_of_all_elements_located((By.XPATH,'//div[@class="gl-i-wrap"]/div[3]/a/em')))
            names = [item.text for item in names]
            comments = self.wait.until(EC.presence_of_all_elements_located((By.XPATH,'//div[@class="gl-i-wrap"]/div[4]/strong')))
            comments = [item.text for item in comments]
            self.data = zip(links,prices,names,comments)
        except selenium.common.exceptions.TimeoutException:  #異常超時
            print('parse_page: TimeoutException')
            self.parse_page()  #再來一遍
        except selenium.common.exceptions.StaleElementReferenceException:  #參考元素'過時'? 這個我不理解
            print('parse_page: StaleElementReferenceException')
            self.browser.refresh()  #總之刷新就對了

    def turn_page(self):
        try:
            self.wait.until(EC.element_to_be_clickable((By.XPATH,'//a[@class="pn-next"]'))).click()  #點擊下一頁
            time.sleep(1)
            self.browser.execute_script("window.scrollTo(0,document.body.scrollHeight)")  #向下拖動網頁
            time.sleep(2)
        except selenium.common.exceptions.NoSuchElementException:  #定位不到元素(即'下一頁'沒有了,已經爬完了)
            self.isLast = True
        except selenium.common.exceptions.TimeoutException:  #異常超時
            print('turn_page: TimeoutException')
            self.turn_page()  #再來一遍
        except selenium.common.exceptions.StaleElementReferenceException:  #參考元素'過時'? 這個我不理解
            print('turn_page: StaleElementReferenceException')
            self.browser.refresh()  #總之刷新就對了

    def write_to_file(self):
        if self.fm == 'txt':
            for item in self.data:
                self.fd.write('----------------------------------------\n')
                self.fd.write('link:' + str(item[0]) + '\n')
                self.fd.write('price:' + str(item[1]) + '\n')
                self.fd.write('name:' + str(item[2]) + '\n')
                self.fd.write('comment:' + str(item[3]) + '\n')
        if self.fm == 'json':
            temp = ('link','price','name','comment')
            for item in self.data:
                json.dump(dict(zip(temp,item)),self.fd,ensure_ascii=False)
        if self.fm == 'csv':
            writer = csv.writer(self.fd)
            for item in self.data:
                writer.writerow(item)

    def close_file(self):
        self.fd.close()

    def close_browser(self):
        self.browser.quit()

    def crawl(self):
        kw = input('請京東商品的名字:')
        self.open_file()
        self.open_browser()
        self.init_variable()
        print('開始爬取')
        self.browser.get('https://search.jd.com/Search?keyword='+ urllib.parse.quote(kw) +'&enc=utf-8')  #京東商品搜索
        time.sleep(1)
        self.browser.execute_script("window.scrollTo(0,document.body.scrollHeight)")  #模擬滾動條滾動到底部
        time.sleep(2)
        count = 0
        while not self.isLast:  #看能否檢測到'下一頁',檢測到就繼續
            count += 1
            print('正在爬取第 ' + str(count) + ' 頁......')
            self.parse_page()
            self.write_to_file()
            self.turn_page()
        self.close_file()
        self.close_browser()
        print('結束爬取')

if __name__ == '__main__':
    spider = JdSpider()  #賦值一個類
    spider.crawl()  #調用類的函數

講解:

一、本代碼相比以往很棒的一點就是函數不用帶參數

從源代碼中可以看到參數全用 self 代替,要做到很簡單,只需要用一個 class 將所有的函數給包起來,只要在主函數中調用類的函數即可

二、selenium 庫

可以看到源代碼中導入了大量方法,但並不用瞭解這些,當模板用就行了

from selenium import webdriver
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
import selenium.common.exceptions

下面列舉出一些模擬瀏覽器的模板:

1、打開瀏覽器模板

def open_browser(self):
    self.browser = webdriver.Chrome()  #打開Chrome
    self.browser.implicitly_wait(10)  #隱式等待10秒
    self.wait = WebDriverWait(self.browser,10)  #超出最長時間(10s),拋出異常

2、解析頁面模板

def parse_page(self):
    try:
    	# 二次存儲數據
        a = self.wait.until(EC.presence_of_all_elements_located((By.XPATH,'--xpath--')))
        a = [item.get_attribute('data-sku') for item in a]  #先存儲到 item 中
        a2 = ['--URL{a1}--'.format(a1=item) for item in a]
        
        # 普通存儲數據
        b = self.wait.until(EC.presence_of_all_elements_located((By.XPATH,'--xpath--')))
        b = [item.text for item in b]
        
        self.data = zip(a,b)
        
    # 拋出異常
    except selenium.common.exceptions.TimeoutException:  #異常超時
        print('parse_page: TimeoutException')
        self.parse_page()  #調用自身
    except selenium.common.exceptions.StaleElementReferenceException:  #參考元素'過時'
        print('parse_page: StaleElementReferenceException')
        self.browser.refresh()  #刷新

語句 try...expect... 是異常處理方法,當滿足 expect 跟着的內容 纔會執行下面語句

3、其他內容

# 點擊某個內容
self.wait.until(EC.element_to_be_clickable((By.XPATH,'--xpath--'))).click()
# 向下拖動網頁
self.browser.execute_script("window.scrollTo(0,document.body.scrollHeight)")

# 定位不到元素,常用於檢測異常,常用於 try expect 語句中
selenium.common.exceptions.NoSuchElementException:

4、關閉瀏覽器

def close_browser(self):
    self.browser.quit()

參考代碼:
selenium的常見異常
webdriver中的等待——主要講解WebDriverWait()
爬蟲系列(十二) selenium的基本使用
爬蟲系列(十三) 用selenium爬取京東商品

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章