import?time
from?urllib.parse?import?parse_qs
import?requests
from?bs4?import?BeautifulSoup
from?selenium?import?webdriver
from?selenium.common.exceptions?import?*
from?selenium.webdriver.support.wait?import?WebDriverWait
#?額外抽取的授權模塊
from?utils?import?auth
class?QMM(object):
"""借助券媽媽平臺褥京東京豆"""
def?__init__(self,?sleep=3,?months=None,?days=None):
self.timeout,?self.months,?self.days?=?sleep,?None,?None
#?爬取規則
if?months:
month_interval?=?months.split('-')
start_month,?end_month?=?int(month_interval[0]),?int(month_interval[-1])
self.months?=?list(map(lambda?m:?'{}月'.format(m),?range(start_month,?end_month?+?1)))
if?days:
day_interval?=?days.split('-')
start_day,?end_day?=?int(day_interval[0]),?int(day_interval[-1])
self.days?=?list(map(lambda?d:?'{}日'.format(d),?range(start_day,?end_day?+?1)))
#?手機店鋪(用作提醒輸出,可復制鏈接到手機端領取)
self.m_shop?=?[]
#?統計京豆總數
self.jing_dou?=?0
def?_crawl_url(self):
"""?抓取京豆更新頁,?獲得店鋪京豆領取地址"""
#?日期更新頁
qmm_collect?=?'http://www.quanmama.com/zhidemai/2459063.html'
bs?=?BeautifulSoup(requests.get(qmm_collect).text,?'html.parser')
for?link?in?bs.tbody.find_all('a'):
text?=?link.text
if?self.months:
if?not?list(filter(lambda?m:?m?in?text,?self.months)):?continue
if?self.days:
if?not?list(filter(lambda?d:?d?in?text,?self.days)):?continue
qmm_detail?=?link.get('href')
#?店鋪領取頁
resp?=?requests.get(qmm_detail)
bs?=?BeautifulSoup(resp.text,?'html.parser')
for?body?in?bs.find_all('tbody'):
for?mall?in?body.find_all('a'):
url?=?self._parse_url(mall.get('href'))
if?'shop.m.jd.com'?in?url:
self.m_shop.append(url)
else:
yield?url
@staticmethod
def?_parse_url(url):
"""提取URL中的url參數"""
mall_url?=?parse_qs(url).get('url')
return?mall_url.pop()?if?mall_url?else?url
def?start(self):
"""?登錄京東,領取店鋪羊毛"""
malls?=?set(self._crawl_url())
print('共有?%d?個可褥羊毛PC端店鋪頁面'?%?len(malls))
m_malls?=?self.m_shop
print('共有?%d?個可褥羊毛手機端店鋪頁面'?%?len(m_malls))
for?m_mall?in?m_malls:
print(m_mall)
if?malls:
#?登陸京東(Chrome、PhantomJS?or?FireFox)
driver?=?webdriver.Chrome()??#?driver?=?webdriver.PhantomJS()
jd_login?=?'https://passport.jd.com/new/login.aspx'
driver.get(jd_login)
#?窗口最大化
driver.maximize_window()
#?QQ授權登錄
driver.find_element_by_xpath('//*[@id="kbCoagent"]/ul/li[1]/a').click()
auth.qq(driver)
time.sleep(self.timeout)
#?開始褥羊毛
for?i,?detail?in?enumerate(malls):
driver.get(detail)
print('%d.店鋪:?%s'?%?(i?+?1,?detail),?end='')
try:
#?查找"領取"按鈕
btn?=?WebDriverWait(driver,?self.timeout).until(
lambda?d:?d.find_element_by_css_selector("[class='J_drawGift?d-btn']"))
except?TimeoutException:
#?失敗大多數情況下是無羊毛可褥(券媽媽平臺只是簡單匯總但不一定就有羊毛)
print('?領取失敗,?TimeoutException?')
else:
try:
#?輸出羊毛戰績
items?=?WebDriverWait(driver,?self.timeout).until(
lambda?d:?d.find_elements_by_css_selector("[class='d-item']"))
for?item?in?items:
item_type?=?item.find_element_by_css_selector("[class='d-type']").text
item_num?=?item.find_element_by_css_selector("[class='d-num']").text
if?item_type?==?'京豆':?self.jing_dou?+=?item_num
print('?{}{}?'.format(item_type,?item_num),?end='')
except:
#?此處異常不太重要,?忽略
pass
finally:
btn.click()
print('?領取成功')
#?以下附加功能可選
self._print_jing_dou()
self._un_subscribe(driver)
self._finance_sign(driver)
def?_print_jing_dou(self):
print('O(∩_∩)O哈哈~,?共褥到了{}個京豆,相當于RMB{}元',?self.jing_dou,?self.jing_dou?/?100)
def?_un_subscribe(self,?driver):
"""批量取消店鋪關注"""
#?進入關注店鋪
subscribe_shop?=?'https://t.jd.com/vender/followVenderList.action'
driver.get(subscribe_shop)
try:
#?批量操作
batch_btn?=?WebDriverWait(driver,?self.timeout).until(
lambda?d:?d.find_element_by_xpath('//*[@id="main"]/div/div[2]/div[1]/div[2]/div[2]/div/a'))
batch_btn.click()
#?全選店鋪
all_btn?=?WebDriverWait(driver,?self.timeout).until(
lambda?d:?d.find_element_by_xpath('//*[@id="main"]/div/div[2]/div[1]/div[2]/div[2]/div/div/span[1]'))
all_btn.click()
#?取消關注
cancel_btn?=?WebDriverWait(driver,?self.timeout).until(
lambda?d:?d.find_element_by_xpath('//*[@id="main"]/div/div[2]/div[1]/div[2]/div[2]/div/div/span[2]'))
cancel_btn.click()
#?彈框確認
confirm_btn?=?WebDriverWait(driver,?self.timeout).until(
lambda?d:?d.find_element_by_xpath("/html/body/div[7]/div[3]/a[1]"))
except?TimeoutException:
print('?批量取關店鋪失敗,?TimeoutException?')
else:
confirm_btn.click()
print('?已批量取消關注店鋪')
def?_finance_sign(self,?driver):
"""京東金融簽到領鋼镚"""
#?進入京東金融
jr_login?=?'https://jr.jd.com/'
driver.get(jr_login)
try:
#?點擊簽到按鈕
sign_btn?=?WebDriverWait(driver,?self.timeout).until(
lambda?d:?d.find_element_by_xpath('//*[@id="primeWrap"]/div[1]/div[3]/div[1]/a'))
except?TimeoutException:
print('?京東金融簽到失敗,?TimeoutException?')
else:
sign_btn.click()
print('?京東金融簽到成功')
if?__name__?==?'__main__':
qmm?=?QMM(sleep=3,?months='7-8',?days='16-31')
qmm.start()