Python爬蟲之selenium爬蟲,模擬瀏覽器爬取天貓信息

因爲工做須要,須要提取到天貓400個指定商品頁面中指定的信息,因而有了這個爬蟲。這是一個使用 selenium 爬取天貓商品信息的爬蟲,雖然功能單一,可是也算是 selenium 爬蟲的基本用法了。html

源碼展現

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

源碼解析

這個爬蟲主要由三個步驟構成:web

  1. 讀取文本中商品ID
  2. 循環爬取每一個商品的信息
  3. 將信息保存到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... 語句,這種操做比較簡潔方便。ui

爬取頁面信息

下面截圖中紅色部分即便要提取的信息部分:url

原本想着能夠直接找到 URL 構造的規律去使用 requests 來爬的,可是最終仍是遇到了難度,因而沒有辦法,只好祭出 selenium 這個大殺器!spa

selenium 爬蟲的本質就是模擬瀏覽器的操做,因此這個爬蟲很簡單,只須要模擬瀏覽器打開如下網頁,而後找到本身要的信息,提取就好了。code

具體代碼也封裝到了一個函數中,這個函數須要傳遞一個參數,也就是一個商品ID,用來構成 URL 以便爬蟲使用。orm

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)

這個函數主要進行的操做流程爲:htm

  1. 打開瀏覽器
  2. 輸入一個 URL
  3. 等待頁面刷新以後查找信息標籤
  4. 提取指定信息,而後使用封裝好的函數寫入表格

其中最重要的步驟是提取信息的過程,這個使用了智能等待,也就是設定一個超時,而後瀏覽器會在這個超時的時間內智能的屢次查找指定的信息,直到找到信息就進行下一步,不然繼續刷新頁面查找,直到超時時間到達報錯。

保存信息到表格

信息已經提取,就須要保存起來,由於這個爬蟲是工做須要,並且量也比較小,因此最佳的保存信息的方式就是 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/

相關文章
相關標籤/搜索