由於工作需要,需要提取到天貓400個指定商品頁面中指定的信息,於是有了這個爬蟲。這是一個使用 selenium 爬取天貓商品信息的爬蟲,雖然功能單一,但是也算是 selenium 爬蟲的基本用法了。
源碼展示
1 from selenium import webdriver 2 from selenium.webdriver.common.by import By 3 from selenium.webdriver.support.ui import WebDriverWait 4 from selenium.webdriver.support import expected_conditions as EC 5 from selenium.common.exceptions import TimeoutException 6 import csv 7 import time 8 9 class TM_itemdetail(object): 10 def __init__(self,readname='ids.txt',savename='info.csv'): 11 '''傳入2個參數,分別是讀取ID的文本名稱和保存信息的表格名稱,給予默認值''' 12 self.readname = readname 13 self.savename = savename 14 self.driver = webdriver.Chrome() 15 self.driver.maximize_window() 16 # 設置一個智能等待 17 self.waiter = WebDriverWait(self.driver,5) 18 self.get_csv() 19 20 def get_csv(self): 21 '''創建一個表格,並且給表格添加標題行''' 22 with open(self.savename,'w',newline='') as f: 23 fieldnames = ['id','info'] 24 writer = csv.DictWriter(f,fieldnames=fieldnames) 25 writer.writeheader() 26 27 def write_info(self,info_dic): 28 '''寫入單個信息,傳入的參數是一個字典,字典的key跟表格的標題對應''' 29 with open(self.savename,'a',newline='') as f: 30 fieldnames = ['id', 'info'] 31 writer = csv.DictWriter(f, fieldnames=fieldnames) 32 writer.writerow(info_dic) 33 34 def get_ids(self): 35 '''讀取文本的ID,形成一個列表''' 36 with open(self.readname,'r') as f: 37 lines = f.readlines() 38 ids = [k.replace('\n','').strip() for k in lines] 39 return ids 40 41 def get_info(self,id): 42 '''爬蟲的主要操作,模擬打開瀏覽器,找到信息的標簽,提取后寫入表格''' 43 dic = {} 44 url = 'https://detail.tmall.com/item.htm?id={}'.format(id) 45 self.driver.get(url) 46 # html = self.driver.page_source 47 # print(html) 48 try: 49 location = self.waiter.until( 50 EC.presence_of_element_located((By.XPATH,'//li[@class="J_step4Time"]')) 51 ) 52 info = location.text.strip() 53 dic['id'] = id 54 dic['info'] = info if info else '信息為空白' 55 self.write_info(dic) 56 except TimeoutException as e: 57 print(e) 58 dic['id'] = id 59 dic['info'] = '{}超時,未找到信息'.format(e).strip() 60 self.write_info(dic) 61 62 def main(self): 63 '''主函數,循環爬取,並打印相應的操作過程''' 64 ids = self.get_ids() 65 counter = len(ids) 66 i = 1 67 for id in ids: 68 self.get_info(id) 69 print('總計{}個,已經爬取{}個'.format(counter,i)) 70 i += 1 71 72 73 if __name__ == '__main__': 74 start = time.time() 75 tm = TM_itemdetail() 76 tm.main() 77 tm.driver.close() 78 end = time.time() 79 print('運行結束,總耗時:{:.2f}秒'.format(end-start))
源碼解析
這個爬蟲主要由三個步驟構成:
- 讀取文本中商品ID
- 循環爬取每個商品的信息
- 將信息保存到csv表格中
讀取文本中的信息
由於是爬取給定的商品ID的寶貝的信息,所以需要一份包含商品ID的文本,文本中每行放入一個商品ID即可。
然后使用 Python 內置的方法,讀取所有的商品ID並形成一個列表返回即可,這個過程可以封裝到一個函數中,也即是下面這個:
def get_ids(self): '''讀取文本的ID,形成一個列表''' with open(self.readname,'r') as f: lines = f.readlines() ids = [k.replace('\n','').strip() for k in lines] return ids
這個函數看似沒有傳入參數,實際上因為是類的函數,所以有個參數是使用的類的屬性,也就是文本的名稱 self.readname
。文件的讀寫可以使用 with...as... 語句,這種操作比較簡潔方便。
爬取頁面信息
下面截圖中紅色部分即使要提取的信息部分:
本來想着可以直接找到 URL 構造的規律去使用 requests
來爬的,但是最終還是遇到了難度,於是沒有辦法,只好祭出 selenium
這個大殺器!
selenium 爬蟲的本質就是模擬瀏覽器的操作,所以這個爬蟲很簡單,只需要模擬瀏覽器打開以下網頁,然后找到自己要的信息,提取就行了。
具體代碼也封裝到了一個函數中,這個函數需要傳遞一個參數,也就是一個商品ID,用來構成 URL 以便爬蟲使用。
def get_info(self,id): '''爬蟲的主要操作,模擬打開瀏覽器,找到信息的標簽,提取后寫入表格''' dic = {} url = 'https://detail.tmall.com/item.htm?id={}'.format(id) self.driver.get(url) # html = self.driver.page_source # print(html) try: location = self.waiter.until( EC.presence_of_element_located((By.XPATH,'//li[@class="J_step4Time"]')) ) info = location.text.strip() dic['id'] = id dic['info'] = info if info else '信息為空白' self.write_info(dic) except TimeoutException as e: print(e) dic['id'] = id dic['info'] = '{}超時,未找到信息'.format(e).strip() self.write_info(dic)
這個函數主要進行的操作流程為:
- 打開瀏覽器
- 輸入一個 URL
- 等待頁面刷新之后查找信息標簽
- 提取指定信息,然后使用封裝好的函數寫入表格
其中最重要的步驟是提取信息的過程,這個使用了智能等待,也就是設定一個超時,然后瀏覽器會在這個超時的時間內智能的多次查找指定的信息,直到找到信息就進行下一步,否則繼續刷新頁面查找,直到超時時間到達報錯。
保存信息到表格
信息已經提取,就需要保存起來,因為這個爬蟲是工作需要,而且量也比較小,所以最佳的保存信息的方式就是 CSV 的表格形式了,直接使用 Python 自帶的 csv 模塊就可以。
信息保存分為2個部分:
- 在程序運行的最初,創建一個表格,並且給表格寫入標題
- 在每次爬完一個頁面,就在表格中寫入一條信息
所以,寫入表格的代碼其實就是分成2個部分來的。
第一部分:
def get_csv(self): '''創建一個表格,並且給表格添加標題行''' with open(self.savename,'w',newline='') as f: fieldnames = ['id','info'] writer = csv.DictWriter(f,fieldnames=fieldnames) writer.writeheader()
這個部分創建了一個表格,並且可以看到,在爬蟲類的的初始化中,已經運行了這個函數,也就是說,在爬蟲創建的時候,就創建了一個表格。
self.get_csv()
第二部分:
1 def write_info(self,info_dic): 2 '''寫入單個信息,傳入的參數是一個字典,字典的key跟表格的標題對應''' 3 with open(self.savename,'a',newline='') as f: 4 fieldnames = ['id', 'info'] 5 writer = csv.DictWriter(f, fieldnames=fieldnames) 6 writer.writerow(info_dic)
這個函數就是封裝的寫入信息,需要傳入一個參數,也就是已經提取到的信息,這個信息需要寫成字典的格式,因為在表格中已經創建了標題,所以可以直接使用標題的值來作為字典的 key。
循環爬取
最后,將整個爬蟲的邏輯封裝到一個主函數 main()
中即可,並且,為了可以及時看到爬蟲的運行進度,可以在控制台中打印爬蟲的進度信息。
1 def main(self): 2 '''主函數,循環爬取,並打印相應的操作過程''' 3 ids = self.get_ids() 4 counter = len(ids) 5 i = 1 6 for id in ids: 7 self.get_info(id) 8 print('總計{}個,已經爬取{}個'.format(counter,i)) 9 i += 1
后記:不得不說,Python真的是個神器,很多需要花大量的時間去重復操作的一個事情,只需要花一點點時間寫一個爬蟲代碼就能做到。
所以,那句話怎么說來着,人生苦短,快用 Python !
原創文章,裝載請注明出處,文章內容來自 http://www.stopfollow.com/article/selenium-crawler-get-tmall-information/