簡單說是:用<ul>表示該頁的所有訂單,<ul>下面的每一個<li>表示一個具體訂單,<li>下面的類型為user-info的<div>表示該訂單的用戶信息,<div>下面是姓名電話等信息。
因此定位過程如下:先用find_elements方法找到<ul>下面的所有<li>;然后遍歷每一個<li>,定位用戶信息;后再從用戶信息中定位姓名電話等。這里用到了層級定位。
1 # 抓取當前頁面的所有訂單,并調(diào)用saveOrderIntoDict將每個訂單信息都存入self.orderDict
2 def searchOrderListInCurrentPage(self):
3 # 這里采用CSS定位,但是使用了find_elements,一次定位所有的訂單
4 orders = self.driver.find_elements_by_css_selector('ul.order-list.J-order-list > li')
5
6 # 遍歷每一個訂單,提取其中的用戶信息,這里用到了層級定位
7 for one in orders:
8 # 先定位用戶信息
9 uesrinfo = one.find_element_by_css_selector('div.user-info')
10 # 再定位具體每項信息
11 name = uesrinfo.find_element_by_css_selector('span.b-title.user-name').text
12 # 有的用戶沒有寫名字
13 if name == '':
14 name = u'無名氏'
15 tel = uesrinfo.find_element_by_css_selector('span.b-title.user-phone.J-search-phone').text
16 address = uesrinfo.find_element_by_css_selector('div > span.fl.J-search-address').text
17 # 信息存入self.orderDict
18 self.saveOrderIntoDict(tel, name, address)
19 return
8、判斷是否還有下一頁訂單
這里使用頁面低端的翻頁符號來定位,如下圖所示。
實現(xiàn)思路可參考 使用selenium實現(xiàn)簡單網(wǎng)絡爬蟲抓取MM圖片 ,檢查是否到達頁面底部的方法:
1 # 判斷是否還有下一頁
2 # 通過符號>>的上級標簽<li>的class屬性來判斷,當還存在下一頁(>>可點擊)時,<li>的class屬性值為空;當不存在下一頁時,<li>的class屬性值為disabled
3 # 因此,當我們找到符號>>及其父元素<li class="disabled">時,即可認為不存在下一頁,否則存在下一頁
4 def hasNextPage(self):
5 try:
6 # 注意這里的選擇器一定要包含a[aria-label="Next"],不能只用li.disabled,因為上一頁的符號也可能存在li.disabled,必須使用父子元素同時定位
7 self.driver.find_element_by_css_selector('ul.J-pagination.pagination.pagination-md.pull-right > li.disabled > a[aria-label="Next"]')
8 # 如果沒拋出異常,說明找到了元素<li class="disabled">和子元素<a aria-label="Next">,沒有下一頁了
9 return False
10 except NoSuchElementException as e:
11 # 拋出異常說明還存在下一頁
12 return True
9、切換到下一頁訂單
切換很簡單,直接定位翻頁符號點擊即可:
1 # 切換到下一頁
2 # 這個比較簡單,直接采用類似上面的定位器即可
3 def enterNextPage(self):
4 self.driver.find_element_by_css_selector('ul.J-pagination.pagination.pagination-md.pull-right a[aria-label="Next"] > span').click()
5 return
10、抓取設置日期范圍內(nèi)的所有訂單
上面的方法都是些內(nèi)部實現(xiàn),無需直接調(diào)用,而該方法是供我們直接調(diào)用的,這里只是對上面那些方法的組合以及簡單處理:
1 # 抓取設定日期范圍內(nèi)的所有訂單,抓取訂單時直接調(diào)用該接口即可
2 def getAllOrders(self, startdate, enddate):
3 # 設置訂單的時間范圍
4 self.setDate(startdate, enddate)
5
6 # 登錄
7 self.login()
8
9 # 切換到歷史訂單頁面
10 self.switchToHistoryOrder()
11
12 # 遍歷處理dateList中的所有日期對
13 for date in self.dateList:
14 # 選擇date所標示的時間范圍
15 self.selectDate(startDate=date[0], endDate=date[1])
16
17 # 依次處理篩選出來的每一頁訂單
18 while True:
19 # 處理當前頁面的訂單
20 self.searchOrderListInCurrentPage()
21 # 是否還有下一頁
22 if self.hasNextPage():
23 self.enterNextPage()
24 else:
25 break
26
27 # 退出
28 self.logout()
29 return
11、篩選出點餐次數(shù)TOP N的顧客
調(diào)用第10步的方法后,所有的訂單信息都在self.orderDict中了,這里只需將dict轉換為list,然后按照cnt降序排序,再輸出前10的信息即可。
1 # 篩選出點餐次數(shù)排名前N的顧客
2 def getTopN(self, n=10):
3 # 先將orderDict轉換為list
4 # {'tel': ['name', 'address', cnt]} -> [('name', 'tel', 'address', cnt)]
5 orderList = [(v[0], k, v[1], v[2]) for (k, v) in self.orderDict.iteritems()]
6
7 # 按照list中每個元素的cnt排序
8 orderList.sort(key=lambda x: x[3], reverse=True)
9
10 # 輸出TOP N
11 num = len(orderList)
12 if num < n:
13 n = num
14 for i in range(n):
15 print orderList[i][0]
16 print orderList[i][1]
17 print orderList[i][2]
18 print orderList[i][3]
現(xiàn)在測試一下整個代碼:
1 if __name__ == '__main__':
2 order = Order('url', 'username', 'password')
3 # 抓取制定時間范圍內(nèi)的所有訂單
4 order.getAllOrders('2016-05-23', '2016-05-25')
5 # 輸出TOPN
6 order.getTopN(n=10)
輸出形式如下:
1 姓名1
2 13512345678
3 地址1
4 6
5 姓名2
6 13612345678
7 地址2
8 3
9 姓名3
10 13712345678
11 地址3
12 1