order_bot.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. #!/usr/bin/env python
  2. # -*- encoding: utf-8 -*-
  3. '''
  4. @Contact : liuyuqi.gov@msn.cn
  5. @Time : 2023/05/17 12:38:45
  6. @License : Copyright © 2017-2022 liuyuqi. All Rights Reserved.
  7. @Desc : order bot
  8. '''
  9. from selenium.common import exceptions
  10. from selenium import webdriver
  11. from selenium.webdriver import ActionChains
  12. import time
  13. import re
  14. import requests
  15. import json
  16. import sys
  17. from bs4 import BeautifulSoup
  18. class TaobaoClimber:
  19. '''
  20. 淘宝爬虫
  21. '''
  22. def __init__(self, username, password):
  23. ''' 初始化 '''
  24. self.__session = requests.Session()
  25. self.__username = username
  26. self.__password = password
  27. driver = None
  28. action = None
  29. # 是否登录
  30. __is_logined = False
  31. # 淘宝账户
  32. __username = ""
  33. # 登录密码
  34. __password = ""
  35. # 登陆URL
  36. __login_url = "https://login.taobao.com/member/login.jhtml"
  37. # 卖家待发货订单URL
  38. __orders_url = "https://trade.taobao.com/trade/itemlist/list_sold_items.htm?action=itemlist/SoldQueryAction&event_submit_do_query=1&auctionStatus=PAID&tabCode=waitSend"
  39. # 卖家正出售宝贝URL
  40. __auction_url = "https://sell.taobao.com/auction/merchandise/auction_list.htm"
  41. # 卖家仓库中宝贝URL
  42. __repository_url = "https://sell.taobao.com/auction/merchandise/auction_list.htm?type=1"
  43. # 卖家确认发货URL
  44. __deliver_url = "https://wuliu.taobao.com/user/consign.htm?trade_id="
  45. # 卖家退款URL
  46. __refunding_url = "https://trade.taobao.com/trade/itemlist/list_sold_items.htm?action=itemlist/SoldQueryAction&event_submit_do_query=1&auctionStatus=REFUNDING&tabCode=refunding"
  47. # 请求留言URL
  48. __message_url = "https://trade.taobao.com/trade/json/getMessage.htm?archive=false&biz_order_id="
  49. # requests会话
  50. __session = None
  51. def __login(self):
  52. # 1.登陆
  53. try:
  54. self.driver.get(self.__login_url)
  55. except exceptions.TimeoutException: # 当页面加载时间超过设定时间,JS来停止加载
  56. self.driver.execute_script('window.stop()')
  57. count = 0
  58. while count < 5: # 重试5次
  59. count += 1
  60. if self.__login_one() is True:
  61. break
  62. if count == 5:
  63. return False
  64. # 2.保存cookies
  65. # driver.switch_to_default_content() #需要返回主页面,不然获取的cookies不是登陆后cookies
  66. list_cookies = self.driver.get_cookies()
  67. cookies = {}
  68. for s in list_cookies:
  69. cookies[s['name']] = s['value']
  70. requests.utils.add_dict_to_cookiejar(self.__session.cookies, cookies) # 将获取的cookies设置到session
  71. return True
  72. def __login_one(self):
  73. try:
  74. # 1.点击密码登录,切换到密码登录模式 默认是二维码登录
  75. username_login_btn = self.driver.find_element_by_xpath("//a[@class='forget-pwd J_Quick2Static']")
  76. if username_login_btn.is_displayed() is True:
  77. username_login_btn.click()
  78. except exceptions.ElementNotInteractableException:
  79. pass
  80. # 2.获取账户、密码输入框
  81. username_input = self.driver.find_element_by_id("TPL_username_1")
  82. password_input = self.driver.find_element_by_id("TPL_password_1")
  83. # 3.为账户、密码赋值
  84. username_input.clear()
  85. username_input.send_keys(self.__username)
  86. password_input.send_keys(self.__password)
  87. # 4.滑块判断
  88. self.__slide_login()
  89. # 5.获取登陆按钮,并点击登录
  90. submit_btn = self.driver.find_element_by_id("J_SubmitStatic")
  91. submit_btn.click()
  92. # 6.根据提示判断是否登录成功
  93. try:
  94. message = self.driver.find_element_by_id("J_Message").find_element_by_class_name("error")
  95. if message.text == u"为了你的账户安全,请拖动滑块完成验证":
  96. self.driver.execute_script(
  97. "document.getElementById('J_Message').children[1].innerText='发货机器人:请滑动滑块,协助完成验证!';")
  98. return False
  99. except exceptions.NoSuchElementException:
  100. pass
  101. # 7.有时检测当前环境是否异常,此时休眠一段时间让它检测
  102. while True:
  103. try:
  104. self.driver.find_element_by_id("J_SiteNav")
  105. break
  106. except exceptions.NoSuchElementException:
  107. time.sleep(1)
  108. return True
  109. def __slide_login(self):
  110. # 取得滑块所在div,判断是否display 一般首次登陆不需要滑块验证
  111. slide_div = self.driver.find_element_by_id("nocaptcha")
  112. if slide_div.is_displayed() is True:
  113. self.driver.execute_script(
  114. "document.getElementById('J_Message').children[1].innerText='发货机器人:请滑动滑块,协助完成验证!';")
  115. while True:
  116. try:
  117. text = self.driver.find_element_by_id("nc_1__scale_text").text
  118. if text == '验证通过':
  119. break
  120. time.sleep(0.5)
  121. except exceptions.NoSuchElementException: # 此时处于刷新按钮状态
  122. pass
  123. def __get_orders_page(self):
  124. # 1.bs4将资源转html
  125. html = BeautifulSoup(self.driver.page_source, "html5lib")
  126. # 2.取得所有的订单div
  127. order_div_list = html.find_all("div", {"class": "item-mod__trade-order___2LnGB trade-order-main"})
  128. # 3.遍历每个订单div,获取数据
  129. data_array = []
  130. for index, order_div in enumerate(order_div_list):
  131. order_id = order_div.find("input", attrs={"name": "orderid"}).attrs["value"]
  132. order_date = order_div.find("span",
  133. attrs={"data-reactid": re.compile(r"\.0\.5\.3:.+\.0\.1\.0\.0\.0\.6")}).text
  134. order_buyer = order_div.find("a", attrs={"class": "buyer-mod__name___S9vit"}).text
  135. # 4.根据订单id组合url,请求订单对应留言
  136. order_message = json.loads(self.__session.get(self.__message_url + order_id).text)['tip']
  137. data_array.append((order_id, order_date, order_buyer, order_message))
  138. return data_array
  139. def climb(self):
  140. # FIXME 没有真实订单的模拟测试,生产环境注释即可
  141. # order_test = [("Test_1548615412315", "2018-08-07 15:00:03", "疯狂的石头",
  142. u"留言: test@qq.com http://download.csdn.net/download/lqkitten/10113904")]
  143. # return order_test
  144. # 切换回淘宝窗口
  145. self.driver.switch_to_window(self.driver.window_handles[0])
  146. result = []
  147. if self.__is_logined is False:
  148. if self.__login() is False:
  149. return result
  150. else:
  151. self.__is_logined = True
  152. # 1.进入待发货订单页面
  153. self.driver.get(self.__orders_url)
  154. while True:
  155. # 2.获取当前页面的订单信息
  156. time.sleep(2) # 两秒等待页面加载
  157. _orders = self.__get_orders_page()
  158. result.extend(_orders)
  159. try:
  160. # 3.获取下一页按钮
  161. next_page_li = self.driver.find_element_by_class_name("pagination-next")
  162. # 4.判断按钮是否可点击,否则退出循环
  163. next_page_li.get_attribute("class").index("pagination-disabled")
  164. # 到达最后一页
  165. break
  166. except ValueError:
  167. # 跳转到下一页
  168. print(next_page_li.find_element_by_tag_name("a").text)
  169. next_page_li.click()
  170. time.sleep(1)
  171. except exceptions.NoSuchElementException:
  172. pass
  173. return result
  174. def unshelve(self):
  175. # 切换回淘宝窗口
  176. self.driver.switch_to_window(self.driver.window_handles[0])
  177. if self.__is_logined is False:
  178. if self.__login() is False:
  179. return False
  180. else:
  181. self.__is_logined = True
  182. try:
  183. # 1.进入正出售宝贝页面
  184. self.driver.get(self.__auction_url)
  185. # 2.点击下架
  186. choose_checkbox = self.driver.find_element_by_xpath(
  187. "//*[@id='J_DataTable']/table/tbody[1]/tr[1]/td/input[1]")
  188. choose_checkbox.click()
  189. unshelve_btn = self.driver.find_element_by_xpath(
  190. "//*[@id='J_DataTable']/div[2]/table/thead/tr[2]/td/div/button[2]")
  191. unshelve_btn.click()
  192. return True
  193. except:
  194. return False
  195. def shelve(self):
  196. # 切换回淘宝窗口
  197. try:
  198. self.driver.switch_to_window(self.driver.window_handles[0])
  199. except exceptions:
  200. print exceptions
  201. if self.__is_logined is False:
  202. if self.__login() is False:
  203. return False
  204. else:
  205. self.__is_logined = True
  206. # 1.进入仓库宝贝页面
  207. self.driver.get(self.__repository_url)
  208. # 2.点击上架
  209. try:
  210. choose_checkbox = self.driver.find_element_by_xpath("//*[@id='J_DataTable']/table/tbody[1]/tr[1]/td/input")
  211. choose_checkbox.click()
  212. shelve_btn = self.driver.find_element_by_xpath(
  213. "//*[@id='J_DataTable']/div[3]/table/tbody/tr/td/div/button[2]")
  214. shelve_btn.click()
  215. except exceptions.NoSuchElementException:
  216. pass
  217. def delivered(self, orderId):
  218. # 切换回淘宝窗口
  219. self.driver.switch_to_window(self.driver.window_handles[0])
  220. if self.__is_logined is False:
  221. if self.__login() is False:
  222. return False
  223. else:
  224. self.__is_logined = True
  225. try:
  226. # 1.进入确认发货页面
  227. self.driver.get(self.__deliver_url + orderId)
  228. no_need_logistics_a = self.driver.find_element_by_xpath("//*[@id='dummyTab']/a")
  229. no_need_logistics_a.click()
  230. self.driver.find_element_by_id("logis:noLogis").click()
  231. time.sleep(1)
  232. return True
  233. except:
  234. return False
  235. def exists_refunding(self):
  236. # 切换回淘宝窗口
  237. self.driver.switch_to_window(self.driver.window_handles[0])
  238. if self.__is_logined is False:
  239. if self.__login() is False:
  240. return False
  241. else:
  242. self.__is_logined = True
  243. try:
  244. # 1.进入退款页面
  245. self.driver.get(self.__refunding_url)
  246. self.driver.find_element_by_class_name("item-mod__trade-order___2LnGB trade-order-main")
  247. return True
  248. except exceptions.NoSuchElementException:
  249. return False
  250. if __name__ == '__main__':
  251. # 初始化
  252. TaobaoClimber.driver = webdriver.Firefox() # 应将浏览器驱动放于python根目录下,且python已配置path环境变量
  253. TaobaoClimber.action = ActionChains(TaobaoClimber.driver)
  254. TaobaoClimber.driver.maximize_window() # 浏览器最大化
  255. TaobaoClimber.driver.execute_script("window.open('')")
  256. climber = TaobaoClimber(u"test", "123456")
  257. while True:
  258. # 循环爬取订单
  259. orders = climber.climb()
  260. for order in orders:
  261. print_msg("淘宝订单产生:订单号:%s\t订单日期:%s \t买家:%s\t备注:%s" % order)
  262. # 每30秒抓一次
  263. time.sleep(30)