123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296 |
- #!/usr/bin/env python
- # -*- encoding: utf-8 -*-
- '''
- @Contact : liuyuqi.gov@msn.cn
- @Time : 2023/05/17 12:38:45
- @License : Copyright © 2017-2022 liuyuqi. All Rights Reserved.
- @Desc : order bot
- '''
- from selenium.common import exceptions
- from selenium import webdriver
- from selenium.webdriver import ActionChains
- import time
- import re
- import requests
- import json
- import sys
- from bs4 import BeautifulSoup
- class TaobaoClimber:
- '''
- 淘宝爬虫
- '''
- def __init__(self, username, password):
- ''' 初始化 '''
- self.__session = requests.Session()
- self.__username = username
- self.__password = password
- driver = None
- action = None
- # 是否登录
- __is_logined = False
- # 淘宝账户
- __username = ""
- # 登录密码
- __password = ""
- # 登陆URL
- __login_url = "https://login.taobao.com/member/login.jhtml"
- # 卖家待发货订单URL
- __orders_url = "https://trade.taobao.com/trade/itemlist/list_sold_items.htm?action=itemlist/SoldQueryAction&event_submit_do_query=1&auctionStatus=PAID&tabCode=waitSend"
- # 卖家正出售宝贝URL
- __auction_url = "https://sell.taobao.com/auction/merchandise/auction_list.htm"
- # 卖家仓库中宝贝URL
- __repository_url = "https://sell.taobao.com/auction/merchandise/auction_list.htm?type=1"
- # 卖家确认发货URL
- __deliver_url = "https://wuliu.taobao.com/user/consign.htm?trade_id="
- # 卖家退款URL
- __refunding_url = "https://trade.taobao.com/trade/itemlist/list_sold_items.htm?action=itemlist/SoldQueryAction&event_submit_do_query=1&auctionStatus=REFUNDING&tabCode=refunding"
- # 请求留言URL
- __message_url = "https://trade.taobao.com/trade/json/getMessage.htm?archive=false&biz_order_id="
- # requests会话
- __session = None
- def __login(self):
- # 1.登陆
- try:
- self.driver.get(self.__login_url)
- except exceptions.TimeoutException: # 当页面加载时间超过设定时间,JS来停止加载
- self.driver.execute_script('window.stop()')
- count = 0
- while count < 5: # 重试5次
- count += 1
- if self.__login_one() is True:
- break
- if count == 5:
- return False
- # 2.保存cookies
- # driver.switch_to_default_content() #需要返回主页面,不然获取的cookies不是登陆后cookies
- list_cookies = self.driver.get_cookies()
- cookies = {}
- for s in list_cookies:
- cookies[s['name']] = s['value']
- requests.utils.add_dict_to_cookiejar(self.__session.cookies, cookies) # 将获取的cookies设置到session
- return True
- def __login_one(self):
- try:
- # 1.点击密码登录,切换到密码登录模式 默认是二维码登录
- username_login_btn = self.driver.find_element_by_xpath("//a[@class='forget-pwd J_Quick2Static']")
- if username_login_btn.is_displayed() is True:
- username_login_btn.click()
- except exceptions.ElementNotInteractableException:
- pass
- # 2.获取账户、密码输入框
- username_input = self.driver.find_element_by_id("TPL_username_1")
- password_input = self.driver.find_element_by_id("TPL_password_1")
- # 3.为账户、密码赋值
- username_input.clear()
- username_input.send_keys(self.__username)
- password_input.send_keys(self.__password)
- # 4.滑块判断
- self.__slide_login()
- # 5.获取登陆按钮,并点击登录
- submit_btn = self.driver.find_element_by_id("J_SubmitStatic")
- submit_btn.click()
- # 6.根据提示判断是否登录成功
- try:
- message = self.driver.find_element_by_id("J_Message").find_element_by_class_name("error")
- if message.text == u"为了你的账户安全,请拖动滑块完成验证":
- self.driver.execute_script(
- "document.getElementById('J_Message').children[1].innerText='发货机器人:请滑动滑块,协助完成验证!';")
- return False
- except exceptions.NoSuchElementException:
- pass
- # 7.有时检测当前环境是否异常,此时休眠一段时间让它检测
- while True:
- try:
- self.driver.find_element_by_id("J_SiteNav")
- break
- except exceptions.NoSuchElementException:
- time.sleep(1)
- return True
- def __slide_login(self):
- # 取得滑块所在div,判断是否display 一般首次登陆不需要滑块验证
- slide_div = self.driver.find_element_by_id("nocaptcha")
- if slide_div.is_displayed() is True:
- self.driver.execute_script(
- "document.getElementById('J_Message').children[1].innerText='发货机器人:请滑动滑块,协助完成验证!';")
- while True:
- try:
- text = self.driver.find_element_by_id("nc_1__scale_text").text
- if text == '验证通过':
- break
- time.sleep(0.5)
- except exceptions.NoSuchElementException: # 此时处于刷新按钮状态
- pass
- def __get_orders_page(self):
- # 1.bs4将资源转html
- html = BeautifulSoup(self.driver.page_source, "html5lib")
- # 2.取得所有的订单div
- order_div_list = html.find_all("div", {"class": "item-mod__trade-order___2LnGB trade-order-main"})
- # 3.遍历每个订单div,获取数据
- data_array = []
- for index, order_div in enumerate(order_div_list):
- order_id = order_div.find("input", attrs={"name": "orderid"}).attrs["value"]
- order_date = order_div.find("span",
- attrs={"data-reactid": re.compile(r"\.0\.5\.3:.+\.0\.1\.0\.0\.0\.6")}).text
- order_buyer = order_div.find("a", attrs={"class": "buyer-mod__name___S9vit"}).text
- # 4.根据订单id组合url,请求订单对应留言
- order_message = json.loads(self.__session.get(self.__message_url + order_id).text)['tip']
- data_array.append((order_id, order_date, order_buyer, order_message))
- return data_array
- def climb(self):
- # FIXME 没有真实订单的模拟测试,生产环境注释即可
- # order_test = [("Test_1548615412315", "2018-08-07 15:00:03", "疯狂的石头",
- u"留言: test@qq.com http://download.csdn.net/download/lqkitten/10113904")]
- # return order_test
- # 切换回淘宝窗口
- self.driver.switch_to_window(self.driver.window_handles[0])
- result = []
- if self.__is_logined is False:
- if self.__login() is False:
- return result
- else:
- self.__is_logined = True
- # 1.进入待发货订单页面
- self.driver.get(self.__orders_url)
- while True:
- # 2.获取当前页面的订单信息
- time.sleep(2) # 两秒等待页面加载
- _orders = self.__get_orders_page()
- result.extend(_orders)
- try:
- # 3.获取下一页按钮
- next_page_li = self.driver.find_element_by_class_name("pagination-next")
- # 4.判断按钮是否可点击,否则退出循环
- next_page_li.get_attribute("class").index("pagination-disabled")
- # 到达最后一页
- break
- except ValueError:
- # 跳转到下一页
- print(next_page_li.find_element_by_tag_name("a").text)
- next_page_li.click()
- time.sleep(1)
- except exceptions.NoSuchElementException:
- pass
- return result
- def unshelve(self):
- # 切换回淘宝窗口
- self.driver.switch_to_window(self.driver.window_handles[0])
- if self.__is_logined is False:
- if self.__login() is False:
- return False
- else:
- self.__is_logined = True
- try:
- # 1.进入正出售宝贝页面
- self.driver.get(self.__auction_url)
- # 2.点击下架
- choose_checkbox = self.driver.find_element_by_xpath(
- "//*[@id='J_DataTable']/table/tbody[1]/tr[1]/td/input[1]")
- choose_checkbox.click()
- unshelve_btn = self.driver.find_element_by_xpath(
- "//*[@id='J_DataTable']/div[2]/table/thead/tr[2]/td/div/button[2]")
- unshelve_btn.click()
- return True
- except:
- return False
- def shelve(self):
- # 切换回淘宝窗口
- try:
- self.driver.switch_to_window(self.driver.window_handles[0])
- except exceptions:
- print exceptions
- if self.__is_logined is False:
- if self.__login() is False:
- return False
- else:
- self.__is_logined = True
- # 1.进入仓库宝贝页面
- self.driver.get(self.__repository_url)
- # 2.点击上架
- try:
- choose_checkbox = self.driver.find_element_by_xpath("//*[@id='J_DataTable']/table/tbody[1]/tr[1]/td/input")
- choose_checkbox.click()
- shelve_btn = self.driver.find_element_by_xpath(
- "//*[@id='J_DataTable']/div[3]/table/tbody/tr/td/div/button[2]")
- shelve_btn.click()
- except exceptions.NoSuchElementException:
- pass
- def delivered(self, orderId):
- # 切换回淘宝窗口
- self.driver.switch_to_window(self.driver.window_handles[0])
- if self.__is_logined is False:
- if self.__login() is False:
- return False
- else:
- self.__is_logined = True
- try:
- # 1.进入确认发货页面
- self.driver.get(self.__deliver_url + orderId)
- no_need_logistics_a = self.driver.find_element_by_xpath("//*[@id='dummyTab']/a")
- no_need_logistics_a.click()
- self.driver.find_element_by_id("logis:noLogis").click()
- time.sleep(1)
- return True
- except:
- return False
- def exists_refunding(self):
- # 切换回淘宝窗口
- self.driver.switch_to_window(self.driver.window_handles[0])
- if self.__is_logined is False:
- if self.__login() is False:
- return False
- else:
- self.__is_logined = True
- try:
- # 1.进入退款页面
- self.driver.get(self.__refunding_url)
- self.driver.find_element_by_class_name("item-mod__trade-order___2LnGB trade-order-main")
- return True
- except exceptions.NoSuchElementException:
- return False
- if __name__ == '__main__':
- # 初始化
- TaobaoClimber.driver = webdriver.Firefox() # 应将浏览器驱动放于python根目录下,且python已配置path环境变量
- TaobaoClimber.action = ActionChains(TaobaoClimber.driver)
- TaobaoClimber.driver.maximize_window() # 浏览器最大化
- TaobaoClimber.driver.execute_script("window.open('')")
- climber = TaobaoClimber(u"test", "123456")
- while True:
- # 循环爬取订单
- orders = climber.climb()
- for order in orders:
- print_msg("淘宝订单产生:订单号:%s\t订单日期:%s \t买家:%s\t备注:%s" % order)
- # 每30秒抓一次
- time.sleep(30)
|