chrome secure shell插件无法上传下载文件

Linux李魔佛 发表了文章 • 0 个评论 • 37 次浏览 • 2021-02-22 19:28 • 来自相关话题

本来挺强大的一个插件,结果因为这个小功能导致鸡肋了,或者我不知道如何在下载文件??
 
后记:
只好用scp传输啦,还好windows平台的git客户端。
本来挺强大的一个插件,结果因为这个小功能导致鸡肋了,或者我不知道如何在下载文件??
 
后记:
只好用scp传输啦,还好windows平台的git客户端。

redis启动报错

数据库李魔佛 发表了文章 • 0 个评论 • 37 次浏览 • 2021-02-21 14:50 • 来自相关话题

使用systemctl start redis-server启动redis报错:
 
Failed to start Advanced key-value store
 
csdn查出来的全是垃圾。
 
后面再stackoverflow看了下,尝试其中一个方案:
使用命令启动
/usr/bin/redis-server /etc/redis/redis-conf
 
然后一起就又正常了, 如果还是报错,把bind的ip地址后面那截改为127.0.0.1,后面那个ipv6格式的不要 查看全部
使用systemctl start redis-server启动redis报错:
 
Failed to start Advanced key-value store
 
csdn查出来的全是垃圾。
 
后面再stackoverflow看了下,尝试其中一个方案:
使用命令启动
/usr/bin/redis-server /etc/redis/redis-conf
 
然后一起就又正常了, 如果还是报错,把bind的ip地址后面那截改为127.0.0.1,后面那个ipv6格式的不要

python 转换excel数据,适配flourish数据格式

python李魔佛 发表了文章 • 0 个评论 • 53 次浏览 • 2021-02-20 00:28 • 来自相关话题

flourish可视化网站要求excel的时间是按列排的,也就是我有1000个数据,那么也就需要1000列,这个和dataframe的默认数据是转置的,也就是需要把dataframe的行变成列。
 
而在数据量很大的情况下,pandas的xlwt是不支持265行以上的,所以需要用xlsxwriter这个库,通过手动转换
 
 
import xlsxwriter #导入模块
workbook = xlsxwriter.Workbook('new_people.xlsx') #新建excel表
worksheet = workbook.add_worksheet('sheet1') #新建sheet(sheet的名称为"sheet1")
把行列重新写入。
for index,item in df.iterrows():
date=item['上市日期']
count=item['申购人数']
date=date.replace(' 00:00:00','')
worksheet.write(0,index,date)
worksheet.write(1,index,count)

workbook.close()
index就是列数,不断地写在第一行和第二行,就可以达到所要的需求了。
  查看全部
flourish可视化网站要求excel的时间是按列排的,也就是我有1000个数据,那么也就需要1000列,这个和dataframe的默认数据是转置的,也就是需要把dataframe的行变成列。
 
而在数据量很大的情况下,pandas的xlwt是不支持265行以上的,所以需要用xlsxwriter这个库,通过手动转换
 
 
import xlsxwriter   #导入模块
workbook = xlsxwriter.Workbook('new_people.xlsx') #新建excel表
worksheet = workbook.add_worksheet('sheet1') #新建sheet(sheet的名称为"sheet1")

把行列重新写入。
for index,item in df.iterrows():
date=item['上市日期']
count=item['申购人数']
date=date.replace(' 00:00:00','')
worksheet.write(0,index,date)
worksheet.write(1,index,count)

workbook.close()

index就是列数,不断地写在第一行和第二行,就可以达到所要的需求了。
 

阿里云windows配置阿里邮发送邮件

网络李魔佛 发表了文章 • 0 个评论 • 120 次浏览 • 2021-02-06 22:38 • 来自相关话题

申请的25端口不给解封,只好用企业有的80端口。
python的发邮件代码demo:
 
try:
stmp.connect(host='smtp.mxhichina.com', port=80)
stmp.login(username, password)
stmp.sendmail(username, TO_MAIL_, msg.as_string()) 查看全部
申请的25端口不给解封,只好用企业有的80端口。
python的发邮件代码demo:
 
    try:
stmp.connect(host='smtp.mxhichina.com', port=80)
stmp.login(username, password)
stmp.sendmail(username, TO_MAIL_, msg.as_string())

用appium启动微信,为了把noReset设为False,聊天记录都没了

闲聊李魔佛 发表了文章 • 0 个评论 • 158 次浏览 • 2021-02-05 09:27 • 来自相关话题

手贱下载了一个清理微信好友的python代码,人家本来noReset设为True,不知道为啥手贱,一手把它改成False,
结果启动后卡了很久,当时还以为内存消耗比较大,kill了一下,结果还是很快,原来当时是在后台删除数据。。。。。
 
启动后发现,数据不见了,要重新登录。。。。哭。。。。 查看全部
手贱下载了一个清理微信好友的python代码,人家本来noReset设为True,不知道为啥手贱,一手把它改成False,
结果启动后卡了很久,当时还以为内存消耗比较大,kill了一下,结果还是很快,原来当时是在后台删除数据。。。。。
 
启动后发现,数据不见了,要重新登录。。。。哭。。。。

chrome浏览器右下加弹出广告

网络安全李魔佛 发表了文章 • 0 个评论 • 116 次浏览 • 2021-02-02 21:46 • 来自相关话题

原因是你允许了部分网站的推送,地址栏打开chrome://settings/content/notifications
 
在提示通知里面,把所有允许的网站给移出就可以了
原因是你允许了部分网站的推送,地址栏打开chrome://settings/content/notifications
 
在提示通知里面,把所有允许的网站给移出就可以了

看到用户在b站的墨茶下的留言

闲聊李魔佛 发表了文章 • 0 个评论 • 144 次浏览 • 2021-01-30 15:26 • 来自相关话题

“梵高的愤怒 一文不值 直到他被送进了坟墓”——杨和苏
 






留言的人何尝不是。
“梵高的愤怒 一文不值 直到他被送进了坟墓”——杨和苏
 

111111.jpg


留言的人何尝不是。

安装nodejs后新增的python把原来的python版本覆盖了

python李魔佛 发表了文章 • 0 个评论 • 199 次浏览 • 2021-01-29 14:58 • 来自相关话题

如果安装nodejs最后勾选了python环境,系统默认帮你装上最新的python版本,还自动把环境变量帮你加上,真是贴心。
 解决办法:
win10: 打开环境变量,把第一个python39或者类似字样的环境变量往下移,最好移到最后。
如果安装nodejs最后勾选了python环境,系统默认帮你装上最新的python版本,还自动把环境变量帮你加上,真是贴心。
 解决办法:
win10: 打开环境变量,把第一个python39或者类似字样的环境变量往下移,最好移到最后。

交易所的基金份额更新时间

股票李魔佛 发表了文章 • 0 个评论 • 200 次浏览 • 2021-01-21 23:05 • 来自相关话题

经过测试观察,需要在第二天(T+1)才会更新T日的份额增加。
 
具体时间再T+1 收盘前,待会测试下给结果。 上午开盘前9点没见到数据更新,中午1点前已经更新了的。
 
最新的数据在11:30已经出来了
 





 
经过测试观察,需要在第二天(T+1)才会更新T日的份额增加。
 
具体时间再T+1 收盘前,待会测试下给结果。 上午开盘前9点没见到数据更新,中午1点前已经更新了的。
 
最新的数据在11:30已经出来了
 

Studio_3T_4LUVWFx1Rs.png

 

基金的份额是怎么算的

股票李魔佛 发表了文章 • 0 个评论 • 188 次浏览 • 2021-01-21 23:02 • 来自相关话题

一、卖出多少份额就是多少钱吗

从狭义上来说,基金卖出份额并不是钱,卖出份额的数量与赎回到账资金数额往往也是不相同的。
 
基金赎回金额计算公式为:基金赎回金额=基金份额*基金单位净值-赎回手续费
 
。由此可见,赎回金额的多少与基金卖出份额、基金单位净值和赎回手续费都是相关的。

基金份额可以简单理解为投资者持有的基金数量,而基金单位净值就等同于单位数量份额的价格。
 
以房子为例,某投资者拥有一套100平方米的房子,每平方市场售价为1万元/平方,那么基金份额就类似于房屋面积,基金单位净值就类似于每平方价格。

大多数基金赎回时都要根据持有天数的不同,按赎回总额收取不同比例的手续费,赎回手续费=(基金份额*基金单位净值)*赎回费率。
 
举例说明:

某投资者在2月17日赎回100份某基金,该基金2月17日的单位净值为1.2500,赎回费率为0,那么赎回金额=100*1.2500-0=125元。
二、基金份额一份等于多少钱

基金份额一份的价格就是当日基金单位净值,不过开放式基金单位净值是每日更新的,又涨也有跌,所以基金份额一份的价格也是不断变化的。

以上关于卖出多少份额就是多少钱吗的内容,希望对大家有所帮助。温馨提示,理财有风险,投资需谨慎。
 
 
基金认购后,净值为1,然后申购了多少钱,就有多少份额了。 查看全部

一、卖出多少份额就是多少钱吗

从狭义上来说,基金卖出份额并不是钱,卖出份额的数量与赎回到账资金数额往往也是不相同的。
 
基金赎回金额计算公式为:基金赎回金额=基金份额*基金单位净值-赎回手续费
 
。由此可见,赎回金额的多少与基金卖出份额、基金单位净值和赎回手续费都是相关的。

基金份额可以简单理解为投资者持有的基金数量,而基金单位净值就等同于单位数量份额的价格。
 
以房子为例,某投资者拥有一套100平方米的房子,每平方市场售价为1万元/平方,那么基金份额就类似于房屋面积,基金单位净值就类似于每平方价格。

大多数基金赎回时都要根据持有天数的不同,按赎回总额收取不同比例的手续费,赎回手续费=(基金份额*基金单位净值)*赎回费率。
 
举例说明:

某投资者在2月17日赎回100份某基金,该基金2月17日的单位净值为1.2500,赎回费率为0,那么赎回金额=100*1.2500-0=125元。
二、基金份额一份等于多少钱

基金份额一份的价格就是当日基金单位净值,不过开放式基金单位净值是每日更新的,又涨也有跌,所以基金份额一份的价格也是不断变化的。

以上关于卖出多少份额就是多少钱吗的内容,希望对大家有所帮助。温馨提示,理财有风险,投资需谨慎。
 
 
基金认购后,净值为1,然后申购了多少钱,就有多少份额了。

华美velo银行因为超过30天余额为0被关闭,无法重开

股票李魔佛 发表了文章 • 0 个评论 • 763 次浏览 • 2021-01-21 11:24 • 来自相关话题

 
只能重新注册一个新账号了。
 
如果有需要开港卡,可以联系,国内见面开户,一次性收中介费,以后无年费,管理费。
需要的联系
 
需要资料:
1.身份证复印件
2.护照复印件(如果实在没有护照的,通行证也可以)
3.开户申请表(现在一个表格就可以搞定,不用6个)
4.资产证明(余额还是要求50万以上)。

PS:资产证明:可以是银行打印的纸质流水,也可以是股票,基金,支付宝这种电子的账单也行。
如果达不到,可以代办,不影响。 查看全部

 
只能重新注册一个新账号了。
 
如果有需要开港卡,可以联系,国内见面开户,一次性收中介费,以后无年费,管理费。
需要的联系
 
需要资料:
1.身份证复印件
2.护照复印件(如果实在没有护照的,通行证也可以)
3.开户申请表(现在一个表格就可以搞定,不用6个)
4.资产证明(余额还是要求50万以上)。

PS:资产证明:可以是银行打印的纸质流水,也可以是股票,基金,支付宝这种电子的账单也行。
如果达不到,可以代办,不影响。

armdebian 修改大写键 为esc

Linux李魔佛 发表了文章 • 0 个评论 • 197 次浏览 • 2021-01-18 18:15 • 来自相关话题

一个几乎没什么用的按键,直接用软件把它映射为esc键。
 
armdebian上没有xmodmap 这个软件,但有一个xkeycaps的GUI的小应用,可以很方便地修改在图形界面上修改按键映射。
 
而且xkeycaps修改是持续有效的,如果想该回去,上面有个restore的功能,可以一键恢复默认值。
 
  查看全部
一个几乎没什么用的按键,直接用软件把它映射为esc键。
 
armdebian上没有xmodmap 这个软件,但有一个xkeycaps的GUI的小应用,可以很方便地修改在图形界面上修改按键映射。
 
而且xkeycaps修改是持续有效的,如果想该回去,上面有个restore的功能,可以一键恢复默认值。
 
 

python解析windows日志文件,查询服务器是否被人攻击

python李魔佛 发表了文章 • 0 个评论 • 275 次浏览 • 2021-01-17 23:49 • 来自相关话题

最近大致浏览了下windows server的日志记录,发现有不少的异地IP进行了登录尝试,而且有部分是登录成功的,但不确定是否本人自己登陆,所以借助python,对日志进行解析,并根据IP查询其远程物理地址。
 
最终效果:








【MD,老毛子就是天天在扫描,爆破密码,即使改了端口还是在枚举】
 
大致代码如下:import mmap
import contextlib
from Evtx.Evtx import FileHeader
from Evtx.Views import evtx_file_xml_view
from xml.dom import minidom
from ip_convertor import IP
import re

class WindowsLogger():

def __init__(self,path):
self.path = path
self.formator = 'IP:{:10}\tlocation:{:20}\tUser:{:15}\tProcess:{}'

def read_file(self):
with open(self.path,'r') as f:
with contextlib.closing(mmap.mmap(f.fileno(),0,access=mmap.ACCESS_READ)) as buf:
fh = FileHeader(buf,0)
return fh

return None

def parse_log_detail(self,filteID):
with open(self.path,'r') as f:
with contextlib.closing(mmap.mmap(f.fileno(),0,access=mmap.ACCESS_READ)) as buf:
fh = FileHeader(buf,0)
for xml, record in evtx_file_xml_view(fh):
#只输出事件ID为4624的内容
# InterestEvent(xml,4624)
for IpAddress,ip,targetUsername,ProcessName in self.filter_event(xml,filteID):
print(self.formator.format(IpAddress,ip,targetUsername,ProcessName))

# 过滤掉不需要的事件,输出感兴趣的事件
def filter_event(self,xml,EventID,use_filter=True):
xmldoc = minidom.parseString(xml)
# 获取EventID节点的事件ID
collections = xmldoc.documentElement
events=xmldoc.getElementsByTagName('Event')
for evt in events:
eventId = evt.getElementsByTagName('EventID')[0].childNodes[0].data
time_create = evt.getElementsByTagName('TimeCreated')[0].getAttribute('SystemTime')
eventData = evt.getElementsByTagName('EventData')[0]

for data in eventData.getElementsByTagName('Data'):
if data.getAttribute('Name')=='IpAddress':
IpAddress=data.childNodes[0].data

if data.getAttribute('Name')=='TargetUserName':
targetUsername = data.childNodes[0].data

if data.getAttribute('Name')=='ProcessName':
ProcessName = data.childNodes[0].data

if use_filter is True and eventId==EventID:
ip=''
if re.search('^\d+',IpAddress):
ip = IP(IpAddress).ip_address

yield IpAddress,ip,targetUsername,ProcessName

def main():
path=r'D:\share\1.evtx'
filter_id = '4624'
app = WindowsLogger(path)
app.parse_log_detail(filter_id)

if __name__ == '__main__':
main()
D:\share\1.evtx 为日志导出文件

原创文章,转载请注明出处:
http://30daydo.com/article/44130 
 
完整代码,可以通过公众号回复: windows日志解析获取
 

  查看全部
最近大致浏览了下windows server的日志记录,发现有不少的异地IP进行了登录尝试,而且有部分是登录成功的,但不确定是否本人自己登陆,所以借助python,对日志进行解析,并根据IP查询其远程物理地址。
 
最终效果:




cmd_vKiBIjQLpd.png

【MD,老毛子就是天天在扫描,爆破密码,即使改了端口还是在枚举】
 
大致代码如下:
import mmap
import contextlib
from Evtx.Evtx import FileHeader
from Evtx.Views import evtx_file_xml_view
from xml.dom import minidom
from ip_convertor import IP
import re

class WindowsLogger():

def __init__(self,path):
self.path = path
self.formator = 'IP:{:10}\tlocation:{:20}\tUser:{:15}\tProcess:{}'

def read_file(self):
with open(self.path,'r') as f:
with contextlib.closing(mmap.mmap(f.fileno(),0,access=mmap.ACCESS_READ)) as buf:
fh = FileHeader(buf,0)
return fh

return None

def parse_log_detail(self,filteID):
with open(self.path,'r') as f:
with contextlib.closing(mmap.mmap(f.fileno(),0,access=mmap.ACCESS_READ)) as buf:
fh = FileHeader(buf,0)
for xml, record in evtx_file_xml_view(fh):
#只输出事件ID为4624的内容
# InterestEvent(xml,4624)
for IpAddress,ip,targetUsername,ProcessName in self.filter_event(xml,filteID):
print(self.formator.format(IpAddress,ip,targetUsername,ProcessName))

# 过滤掉不需要的事件,输出感兴趣的事件
def filter_event(self,xml,EventID,use_filter=True):
xmldoc = minidom.parseString(xml)
# 获取EventID节点的事件ID
collections = xmldoc.documentElement
events=xmldoc.getElementsByTagName('Event')
for evt in events:
eventId = evt.getElementsByTagName('EventID')[0].childNodes[0].data
time_create = evt.getElementsByTagName('TimeCreated')[0].getAttribute('SystemTime')
eventData = evt.getElementsByTagName('EventData')[0]

for data in eventData.getElementsByTagName('Data'):
if data.getAttribute('Name')=='IpAddress':
IpAddress=data.childNodes[0].data

if data.getAttribute('Name')=='TargetUserName':
targetUsername = data.childNodes[0].data

if data.getAttribute('Name')=='ProcessName':
ProcessName = data.childNodes[0].data

if use_filter is True and eventId==EventID:
ip=''
if re.search('^\d+',IpAddress):
ip = IP(IpAddress).ip_address

yield IpAddress,ip,targetUsername,ProcessName

def main():
path=r'D:\share\1.evtx'
filter_id = '4624'
app = WindowsLogger(path)
app.parse_log_detail(filter_id)

if __name__ == '__main__':
main()

D:\share\1.evtx 为日志导出文件

原创文章,转载请注明出处:
http://30daydo.com/article/44130 
 
完整代码,可以通过公众号回复: windows日志解析获取
 

 

茅台抢购程序 京东 苏宁

python李魔佛 发表了文章 • 0 个评论 • 2503 次浏览 • 2021-01-05 22:34 • 来自相关话题

最近掀起了茅台抢购风,所以分享一个python抢购脚本。
运行环境 windows,linux,mac,python3+
 
京东小白分查询:
https://plus.m.jd.com/rights/windControl
分太低的就不要参与了,毕竟概率会小很多
 
############ 2021-01-13 更新 ======
最新的用Go重写的,搞了几瓶










 
苏宁家的:





 


============= 2021-01-11 更新 ============

感觉苏宁的抢购是耍猴的,那个按钮基本处于不可点状态,所以就放弃了,感觉官方就是没放多少量,加上苏宁公司过往的尿性,所以洗洗睡了 


main.pyimport sys

from maotai.jd_spider_requests import ProdectPurchase


if __name__ == '__main__':
tip = """
功能列表:
1.预约商品
2.秒杀抢购商品
"""
print(tip)

product = ProdectPurchase()
choice_function = input('请选择:')
if choice_function == '1':
product.reserve()
elif choice_function == '2':
product.seckill_by_proc_pool()
else:
print('没有此功能')
sys.exit(1)







jd_spider_requests.pyimport random
import time
import requests
import functools
import json
import os
import pickle

from lxml import etree

from error.exception import SKException
from maotai.jd_logger import logger
from maotai.timer import Timer
from maotai.config import global_config
from concurrent.futures import ProcessPoolExecutor
from helper.jd_helper import (
parse_json,
send_wechat,
wait_some_time,
response_status,
save_image,
open_image
)


class SpiderSession:
"""
Session相关操作
"""

def __init__(self):
self.cookies_dir_path = "./cookies/"
self.user_agent = global_config.getRaw('config', 'DEFAULT_USER_AGENT')

self.session = self._init_session()

def _init_session(self):
session = requests.session()
session.headers = self.get_headers()
return session

def get_headers(self):
return {"User-Agent": self.user_agent,
"Accept": "text/html,application/xhtml+xml,application/xml;"
"q=0.9,image/webp,image/apng,*/*;"
"q=0.8,application/signed-exchange;"
"v=b3",
"Connection": "keep-alive"}

def get_user_agent(self):
return self.user_agent

def get_session(self):
"""
获取当前Session
:return:
"""
return self.session

def get_cookies(self):
"""
获取当前Cookies
:return:
"""
return self.get_session().cookies

def set_cookies(self, cookies):
self.session.cookies.update(cookies)

def load_cookies_from_local(self):
"""
从本地加载Cookie
:return:
"""
cookies_file = ''
if not os.path.exists(self.cookies_dir_path):
return False
for name in os.listdir(self.cookies_dir_path):
if name.endswith(".cookies"):
cookies_file = '{}{}'.format(self.cookies_dir_path, name)
break
if cookies_file == '':
return False
with open(cookies_file, 'rb') as f:
local_cookies = pickle.load(f)
self.set_cookies(local_cookies)

def save_cookies_to_local(self, cookie_file_name):
"""
保存Cookie到本地
:param cookie_file_name: 存放Cookie的文件名称
:return:
"""
cookies_file = '{}{}.cookies'.format(self.cookies_dir_path, cookie_file_name)
directory = os.path.dirname(cookies_file)
if not os.path.exists(directory):
os.makedirs(directory)
with open(cookies_file, 'wb') as f:
pickle.dump(self.get_cookies(), f)


class QrLogin:
"""
扫码登录
"""

def __init__(self, spider_session: SpiderSession):
"""
初始化扫码登录
大致流程:
1、访问登录二维码页面,获取Token
2、使用Token获取票据
3、校验票据
:param spider_session:
"""
self.qrcode_img_file = 'qr_code.png'

self.spider_session = spider_session
self.session = self.spider_session.get_session()

self.is_login = False
self.refresh_login_status()

def refresh_login_status(self):
"""
刷新是否登录状态
:return:
"""
self.is_login = self._validate_cookies()

def _validate_cookies(self):
"""
验证cookies是否有效(是否登陆)
通过访问用户订单列表页进行判断:若未登录,将会重定向到登陆页面。
:return: cookies是否有效 True/False
"""
url = 'https://order.jd.com/center/list.action'
payload = {
'rid': str(int(time.time() * 1000)),
}
try:
resp = self.session.get(url=url, params=payload, allow_redirects=False)
if resp.status_code == requests.codes.OK:
return True
except Exception as e:
logger.error("验证cookies是否有效发生异常", e)
return False

def _get_login_page(self):
"""
获取PC端登录页面
阻塞,更新cookies
:return:
"""
url = "https://passport.jd.com/new/login.aspx"
page = self.session.get(url, headers=self.spider_session.get_headers())
return page

def _get_qrcode(self):
"""
缓存并展示登录二维码
:return:
"""
url = 'https://qr.m.jd.com/show'
payload = {
'appid': 133,
'size': 147,
't': str(int(time.time() * 1000)),
}
headers = {
'User-Agent': self.spider_session.get_user_agent(),
'Referer': 'https://passport.jd.com/new/login.aspx',
}
resp = self.session.get(url=url, headers=headers, params=payload)

if not response_status(resp):
logger.info('获取二维码失败')
return False

save_image(resp, self.qrcode_img_file)
logger.info('二维码获取成功,请打开京东APP扫描')
open_image(self.qrcode_img_file)
return True

def _get_qrcode_ticket(self):
"""
通过 token 获取票据 ticket
:return:
"""
url = 'https://qr.m.jd.com/check'
payload = {
'appid': '133',
'callback': 'jQuery{}'.format(random.randint(1000000, 9999999)),
'token': self.session.cookies.get('wlfstk_smdl'), # 从cookies获取值
'_': str(int(time.time() * 1000)),
}
headers = {
'User-Agent': self.spider_session.get_user_agent(),
'Referer': 'https://passport.jd.com/new/login.aspx',
}
resp = self.session.get(url=url, headers=headers, params=payload)

if not response_status(resp):
logger.error('获取二维码扫描结果异常')
return False

resp_json = parse_json(resp.text)
if resp_json['code'] != 200:
logger.info('Code: %s, Message: %s', resp_json['code'], resp_json['msg'])
return None
else:
logger.info('已完成手机客户端确认')
return resp_json['ticket']

def _validate_qrcode_ticket(self, ticket):
"""
通过已获取的票据进行校验
:param ticket: 已获取的票据
:return:
"""
url = 'https://passport.jd.com/uc/qrCodeTicketValidation'
headers = {
'User-Agent': self.spider_session.get_user_agent(),
'Referer': 'https://passport.jd.com/uc/login?ltype=logout',
}

resp = self.session.get(url=url, headers=headers, params={'t': ticket})
if not response_status(resp):
return False

resp_json = json.loads(resp.text)
if resp_json['returnCode'] == 0:
return True
else:
logger.info(resp_json)
return False

def login_by_qrcode(self):
"""
二维码登陆
:return:
"""
self._get_login_page() # 更新cookies

# download QR code
if not self._get_qrcode():
raise SKException('二维码下载失败')

# get QR code ticket
ticket = None
retry_times = 85
for _ in range(retry_times):
# 重试 拿到ticket
ticket = self._get_qrcode_ticket()
if ticket:
break
time.sleep(2)
else:
raise SKException('二维码过期,请重新获取扫描')

# validate QR code ticket
if not self._validate_qrcode_ticket(ticket):
raise SKException('二维码信息校验失败')

self.refresh_login_status()

logger.info('二维码登录成功')


class ProdectPurchase(object):
def __init__(self):
self.spider_session = SpiderSession()
self.spider_session.load_cookies_from_local()
# 共享一个session

self.qrlogin = QrLogin(self.spider_session)

# 初始化信息
self.sku_id = global_config.getRaw('config', 'sku_id')
self.seckill_num = global_config.getRaw('config', 'seckill_num')
self.work_count = global_config.getRaw('config','process_num')
self.seckill_init_info = dict()
self.seckill_url = dict()
self.seckill_order_data = dict()
self.timers = Timer()

self.session = self.spider_session.get_session()
self.user_agent = self.spider_session.user_agent
self.nick_name = None

def login_by_qrcode(self):
"""
二维码登陆
:return:
"""
if self.qrlogin.is_login:
logger.info('登录成功')
return

self.qrlogin.login_by_qrcode()

if self.qrlogin.is_login:
self.nick_name = self.get_username()
self.spider_session.save_cookies_to_local(self.nick_name)
else:
raise SKException("二维码登录失败!")

def check_login(func):
"""
用户登陆态校验装饰器。若用户未登陆,则调用扫码登陆
"""

@functools.wraps(func)
def new_func(self, *args, **kwargs):
if not self.qrlogin.is_login:
logger.info("{0} 需登陆后调用,开始扫码登陆".format(func.__name__))
self.login_by_qrcode()
return func(self, *args, **kwargs)

return new_func

@check_login
def reserve(self):
"""
预约
"""
self._reserve()

@check_login
def seckill(self):
"""
抢购
"""
self._seckill()

@check_login
def seckill_by_proc_pool(self):
"""
多进程进行抢购
work_count:进程数量
"""
with ProcessPoolExecutor() as pool:
for i in range(self.work_count):
pool.submit(self.seckill)

def _reserve(self):
"""
预约
"""
while True:
try:
self.make_reserve()
break
except Exception as e:
logger.info('预约发生异常!', e)
wait_some_time()

def _seckill(self):
"""
抢购
"""
while True:
try:
self.request_seckill_url()
while True:
self.request_seckill_checkout_page()
self.submit_seckill_order()
except Exception as e:
logger.info('抢购发生异常,稍后继续执行!', e)
wait_some_time()

def make_reserve(self):
"""商品预约"""
logger.info('商品名称:{}'.format(self.get_sku_title()))
url = 'https://yushou.jd.com/youshouinfo.action?'
payload = {
'callback': 'fetchJSON',
'sku': self.sku_id,
'_': str(int(time.time() * 1000)),
}
headers = {
'User-Agent': self.user_agent,
'Referer': 'https://item.jd.com/{}.html'.format(self.sku_id),
}
resp = self.session.get(url=url, params=payload, headers=headers)
resp_json = parse_json(resp.text)
reserve_url = resp_json.get('url')
# self.timers.start()
while True:
try:
self.session.get(url='https:' + reserve_url)
logger.info('预约成功,已获得抢购资格 / 您已成功预约过了,无需重复预约')
if global_config.getRaw('messenger', 'enable') == 'true':
success_message = "预约成功,已获得抢购资格 / 您已成功预约过了,无需重复预约"
send_wechat(success_message)
break
except Exception as e:
logger.error('预约失败正在重试...')

def get_username(self):
"""获取用户信息"""
url = 'https://passport.jd.com/user/petName/getUserInfoForMiniJd.action'
payload = {
'callback': 'jQuery{}'.format(random.randint(1000000, 9999999)),
'_': str(int(time.time() * 1000)),
}
headers = {
'User-Agent': self.user_agent,
'Referer': 'https://order.jd.com/center/list.action',
}

resp = self.session.get(url=url, params=payload, headers=headers)

try_count = 5
while not resp.text.startswith("jQuery"):
try_count = try_count - 1
if try_count > 0:
resp = self.session.get(url=url, params=payload, headers=headers)
else:
break
wait_some_time()
# 响应中包含了许多用户信息,现在在其中返回昵称
# jQuery2381773({"imgUrl":"//storage.360buyimg.com/i.imageUpload/xxx.jpg","lastLoginTime":"","nickName":"xxx","plusStatus":"0","realName":"xxx","userLevel":x,"userScoreVO":{"accountScore":xx,"activityScore":xx,"consumptionScore":xxxxx,"default":false,"financeScore":xxx,"pin":"xxx","riskScore":x,"totalScore":xxxxx}})
return parse_json(resp.text).get('nickName')

def get_sku_title(self):
"""获取商品名称"""
url = 'https://item.jd.com/{}.html'.format(global_config.getRaw('config', 'sku_id'))
resp = self.session.get(url).content
x_data = etree.HTML(resp)
sku_title = x_data.xpath('/html/head/title/text()')
return sku_title[0]

def get_seckill_url(self):
"""获取商品的抢购链接
点击"抢购"按钮后,会有两次302跳转,最后到达订单结算页面
这里返回第一次跳转后的页面url,作为商品的抢购链接
:return: 商品的抢购链接
"""
url = 'https://itemko.jd.com/itemShowBtn'
payload = {
'callback': 'jQuery{}'.format(random.randint(1000000, 9999999)),
'skuId': self.sku_id,
'from': 'pc',
'_': str(int(time.time() * 1000)),
}
headers = {
'User-Agent': self.user_agent,
'Host': 'itemko.jd.com',
'Referer': 'https://item.jd.com/{}.html'.format(self.sku_id),
}
while True:
resp = self.session.get(url=url, headers=headers, params=payload)
resp_json = parse_json(resp.text)
if resp_json.get('url'):
# https://divide.jd.com/user_rou ... %3Dpc
router_url = 'https:' + resp_json.get('url')
# https://marathon.jd.com/captch ... %3Dpc
seckill_url = router_url.replace(
'divide', 'marathon').replace(
'user_routing', 'captcha.html')
logger.info("抢购链接获取成功: %s", seckill_url)
return seckill_url
else:
logger.info("抢购链接获取失败,稍后自动重试")
wait_some_time()

def request_seckill_url(self):
"""访问商品的抢购链接(用于设置cookie等"""
logger.info('用户:{}'.format(self.get_username()))
logger.info('商品名称:{}'.format(self.get_sku_title()))
self.timers.start() # 阻塞

self.seckill_url[self.sku_id] = self.get_seckill_url()
logger.info('访问商品的抢购连接...')
headers = {
'User-Agent': self.user_agent,
'Host': 'marathon.jd.com',
'Referer': 'https://item.jd.com/{}.html'.format(self.sku_id),
}
self.session.get(
url=self.seckill_url.get(
self.sku_id),
headers=headers,
allow_redirects=False)

def request_seckill_checkout_page(self):
"""访问抢购订单结算页面"""
logger.info('访问抢购订单结算页面...')
url = 'https://marathon.jd.com/seckill/seckill.action'
payload = {
'skuId': self.sku_id,
'num': self.seckill_num,
'rid': int(time.time())
}
headers = {
'User-Agent': self.user_agent,
'Host': 'marathon.jd.com',
'Referer': 'https://item.jd.com/{}.html'.format(self.sku_id),
}
self.session.get(url=url, params=payload, headers=headers, allow_redirects=False)

def _get_seckill_init_info(self):
"""获取秒杀初始化信息(包括:地址,发票,token)
:return: 初始化信息组成的dict
"""
logger.info('获取秒杀初始化信息...')
url = 'https://marathon.jd.com/seckillnew/orderService/pc/init.action'
data = {
'sku': self.sku_id,
'num': self.seckill_num,
'isModifyAddress': 'false',
}
headers = {
'User-Agent': self.user_agent,
'Host': 'marathon.jd.com',
}
resp = self.session.post(url=url, data=data, headers=headers)

resp_json = None
try:
resp_json = parse_json(resp.text)
except Exception:
raise SKException('抢购失败,返回信息:{}'.format(resp.text[0: 128]))

return resp_json

def _get_seckill_order_data(self):
"""生成提交抢购订单所需的请求体参数
:return: 请求体参数组成的dict
"""
logger.info('生成提交抢购订单所需参数...')
# 获取用户秒杀初始化信息
self.seckill_init_info[self.sku_id] = self._get_seckill_init_info()
init_info = self.seckill_init_info.get(self.sku_id)
default_address = init_info['addressList'][0] # 默认地址dict
invoice_info = init_info.get('invoiceInfo', {}) # 默认发票信息dict, 有可能不返回
token = init_info['token']
data = {
'skuId': self.sku_id,
'num': self.seckill_num,
'addressId': default_address['id'],
'yuShou': 'true',
'isModifyAddress': 'false',
'name': default_address['name'],
'provinceId': default_address['provinceId'],
'cityId': default_address['cityId'],
'countyId': default_address['countyId'],
'townId': default_address['townId'],
'addressDetail': default_address['addressDetail'],
'mobile': default_address['mobile'],
'mobileKey': default_address['mobileKey'],
'email': default_address.get('email', ''),
'postCode': '',
'invoiceTitle': invoice_info.get('invoiceTitle', -1),
'invoiceCompanyName': '',
'invoiceContent': invoice_info.get('invoiceContentType', 1),
'invoiceTaxpayerNO': '',
'invoiceEmail': '',
'invoicePhone': invoice_info.get('invoicePhone', ''),
'invoicePhoneKey': invoice_info.get('invoicePhoneKey', ''),
'invoice': 'true' if invoice_info else 'false',
'password': global_config.get('account', 'payment_pwd'),
'codTimeType': 3,
'paymentType': 4,
'areaCode': '',
'overseas': 0,
'phone': '',
'eid': global_config.getRaw('config', 'eid'),
'fp': global_config.getRaw('config', 'fp'),
'token': token,
'pru': ''
}

return data

def submit_seckill_order(self):
"""提交抢购(秒杀)订单
:return: 抢购结果 True/False
"""
url = 'https://marathon.jd.com/seckillnew/orderService/pc/submitOrder.action'
payload = {
'skuId': self.sku_id,
}
try:
self.seckill_order_data[self.sku_id] = self._get_seckill_order_data()
except Exception as e:
logger.info('抢购失败,无法获取生成订单的基本信息,接口返回:【{}】'.format(str(e)))
return False

logger.info('提交抢购订单...')
headers = {
'User-Agent': self.user_agent,
'Host': 'marathon.jd.com',
'Referer': 'https://marathon.jd.com/seckill/seckill.action?skuId={0}&num={1}&rid={2}'.format(
self.sku_id, self.seckill_num, int(time.time())),
}
resp = self.session.post(
url=url,
params=payload,
data=self.seckill_order_data.get(
self.sku_id),
headers=headers)
resp_json = None
try:
resp_json = parse_json(resp.text)
except Exception as e:
logger.info('抢购失败,返回信息:{}'.format(resp.text[0: 128]))
return False
# 返回信息
# 抢购失败:
# {'errorMessage': '很遗憾没有抢到,再接再厉哦。', 'orderId': 0, 'resultCode': 60074, 'skuId': 0, 'success': False}
# {'errorMessage': '抱歉,您提交过快,请稍后再提交订单!', 'orderId': 0, 'resultCode': 60017, 'skuId': 0, 'success': False}
# {'errorMessage': '系统正在开小差,请重试~~', 'orderId': 0, 'resultCode': 90013, 'skuId': 0, 'success': False}
# 抢购成功:
# {"appUrl":"xxxxx","orderId":820227xxxxx,"pcUrl":"xxxxx","resultCode":0,"skuId":0,"success":true,"totalMoney":"xxxxx"}
if resp_json.get('success'):
order_id = resp_json.get('orderId')
total_money = resp_json.get('totalMoney')
pay_url = 'https:' + resp_json.get('pcUrl')
logger.info('抢购成功,订单号:{}, 总价:{}, 电脑端付款链接:{}'.format(order_id, total_money, pay_url))
if global_config.getRaw('messenger', 'enable') == 'true':
success_message = "抢购成功,订单号:{}, 总价:{}, 电脑端付款链接:{}".format(order_id, total_money, pay_url)
send_wechat(success_message)
return True
else:
logger.info('抢购失败,返回信息:{}'.format(resp_json))
if global_config.getRaw('messenger', 'enable') == 'true':
error_message = '抢购失败,返回信息:{}'.format(resp_json)
send_wechat(error_message)
return False





 
苏宁脚本目前在测试途中,需要继续调试。
原创文章,
转载请注明:http://30daydo.com/article/44129 
欢迎关注公众号:
可转债量化分析


  查看全部
最近掀起了茅台抢购风,所以分享一个python抢购脚本。
运行环境 windows,linux,mac,python3+
 
京东小白分查询:
https://plus.m.jd.com/rights/windControl
分太低的就不要参与了,毕竟概率会小很多
 
############ 2021-01-13 更新 ======
最新的用Go重写的,搞了几瓶

微信图片_20210113104908.jpg


photo_2021-01-11_10-07-41.jpg

 
苏宁家的:

photo_2021-01-13_10-51-53.jpg

 


============= 2021-01-11 更新 ============


感觉苏宁的抢购是耍猴的,那个按钮基本处于不可点状态,所以就放弃了,感觉官方就是没放多少量,加上苏宁公司过往的尿性,所以洗洗睡了 



main.py
import sys

from maotai.jd_spider_requests import ProdectPurchase


if __name__ == '__main__':
tip = """
功能列表:
1.预约商品
2.秒杀抢购商品
"""
print(tip)

product = ProdectPurchase()
choice_function = input('请选择:')
if choice_function == '1':
product.reserve()
elif choice_function == '2':
product.seckill_by_proc_pool()
else:
print('没有此功能')
sys.exit(1)







jd_spider_requests.py
import random
import time
import requests
import functools
import json
import os
import pickle

from lxml import etree

from error.exception import SKException
from maotai.jd_logger import logger
from maotai.timer import Timer
from maotai.config import global_config
from concurrent.futures import ProcessPoolExecutor
from helper.jd_helper import (
parse_json,
send_wechat,
wait_some_time,
response_status,
save_image,
open_image
)


class SpiderSession:
"""
Session相关操作
"""

def __init__(self):
self.cookies_dir_path = "./cookies/"
self.user_agent = global_config.getRaw('config', 'DEFAULT_USER_AGENT')

self.session = self._init_session()

def _init_session(self):
session = requests.session()
session.headers = self.get_headers()
return session

def get_headers(self):
return {"User-Agent": self.user_agent,
"Accept": "text/html,application/xhtml+xml,application/xml;"
"q=0.9,image/webp,image/apng,*/*;"
"q=0.8,application/signed-exchange;"
"v=b3",
"Connection": "keep-alive"}

def get_user_agent(self):
return self.user_agent

def get_session(self):
"""
获取当前Session
:return:
"""
return self.session

def get_cookies(self):
"""
获取当前Cookies
:return:
"""
return self.get_session().cookies

def set_cookies(self, cookies):
self.session.cookies.update(cookies)

def load_cookies_from_local(self):
"""
从本地加载Cookie
:return:
"""
cookies_file = ''
if not os.path.exists(self.cookies_dir_path):
return False
for name in os.listdir(self.cookies_dir_path):
if name.endswith(".cookies"):
cookies_file = '{}{}'.format(self.cookies_dir_path, name)
break
if cookies_file == '':
return False
with open(cookies_file, 'rb') as f:
local_cookies = pickle.load(f)
self.set_cookies(local_cookies)

def save_cookies_to_local(self, cookie_file_name):
"""
保存Cookie到本地
:param cookie_file_name: 存放Cookie的文件名称
:return:
"""
cookies_file = '{}{}.cookies'.format(self.cookies_dir_path, cookie_file_name)
directory = os.path.dirname(cookies_file)
if not os.path.exists(directory):
os.makedirs(directory)
with open(cookies_file, 'wb') as f:
pickle.dump(self.get_cookies(), f)


class QrLogin:
"""
扫码登录
"""

def __init__(self, spider_session: SpiderSession):
"""
初始化扫码登录
大致流程:
1、访问登录二维码页面,获取Token
2、使用Token获取票据
3、校验票据
:param spider_session:
"""
self.qrcode_img_file = 'qr_code.png'

self.spider_session = spider_session
self.session = self.spider_session.get_session()

self.is_login = False
self.refresh_login_status()

def refresh_login_status(self):
"""
刷新是否登录状态
:return:
"""
self.is_login = self._validate_cookies()

def _validate_cookies(self):
"""
验证cookies是否有效(是否登陆)
通过访问用户订单列表页进行判断:若未登录,将会重定向到登陆页面。
:return: cookies是否有效 True/False
"""
url = 'https://order.jd.com/center/list.action'
payload = {
'rid': str(int(time.time() * 1000)),
}
try:
resp = self.session.get(url=url, params=payload, allow_redirects=False)
if resp.status_code == requests.codes.OK:
return True
except Exception as e:
logger.error("验证cookies是否有效发生异常", e)
return False

def _get_login_page(self):
"""
获取PC端登录页面
阻塞,更新cookies
:return:
"""
url = "https://passport.jd.com/new/login.aspx"
page = self.session.get(url, headers=self.spider_session.get_headers())
return page

def _get_qrcode(self):
"""
缓存并展示登录二维码
:return:
"""
url = 'https://qr.m.jd.com/show'
payload = {
'appid': 133,
'size': 147,
't': str(int(time.time() * 1000)),
}
headers = {
'User-Agent': self.spider_session.get_user_agent(),
'Referer': 'https://passport.jd.com/new/login.aspx',
}
resp = self.session.get(url=url, headers=headers, params=payload)

if not response_status(resp):
logger.info('获取二维码失败')
return False

save_image(resp, self.qrcode_img_file)
logger.info('二维码获取成功,请打开京东APP扫描')
open_image(self.qrcode_img_file)
return True

def _get_qrcode_ticket(self):
"""
通过 token 获取票据 ticket
:return:
"""
url = 'https://qr.m.jd.com/check'
payload = {
'appid': '133',
'callback': 'jQuery{}'.format(random.randint(1000000, 9999999)),
'token': self.session.cookies.get('wlfstk_smdl'), # 从cookies获取值
'_': str(int(time.time() * 1000)),
}
headers = {
'User-Agent': self.spider_session.get_user_agent(),
'Referer': 'https://passport.jd.com/new/login.aspx',
}
resp = self.session.get(url=url, headers=headers, params=payload)

if not response_status(resp):
logger.error('获取二维码扫描结果异常')
return False

resp_json = parse_json(resp.text)
if resp_json['code'] != 200:
logger.info('Code: %s, Message: %s', resp_json['code'], resp_json['msg'])
return None
else:
logger.info('已完成手机客户端确认')
return resp_json['ticket']

def _validate_qrcode_ticket(self, ticket):
"""
通过已获取的票据进行校验
:param ticket: 已获取的票据
:return:
"""
url = 'https://passport.jd.com/uc/qrCodeTicketValidation'
headers = {
'User-Agent': self.spider_session.get_user_agent(),
'Referer': 'https://passport.jd.com/uc/login?ltype=logout',
}

resp = self.session.get(url=url, headers=headers, params={'t': ticket})
if not response_status(resp):
return False

resp_json = json.loads(resp.text)
if resp_json['returnCode'] == 0:
return True
else:
logger.info(resp_json)
return False

def login_by_qrcode(self):
"""
二维码登陆
:return:
"""
self._get_login_page() # 更新cookies

# download QR code
if not self._get_qrcode():
raise SKException('二维码下载失败')

# get QR code ticket
ticket = None
retry_times = 85
for _ in range(retry_times):
# 重试 拿到ticket
ticket = self._get_qrcode_ticket()
if ticket:
break
time.sleep(2)
else:
raise SKException('二维码过期,请重新获取扫描')

# validate QR code ticket
if not self._validate_qrcode_ticket(ticket):
raise SKException('二维码信息校验失败')

self.refresh_login_status()

logger.info('二维码登录成功')


class ProdectPurchase(object):
def __init__(self):
self.spider_session = SpiderSession()
self.spider_session.load_cookies_from_local()
# 共享一个session

self.qrlogin = QrLogin(self.spider_session)

# 初始化信息
self.sku_id = global_config.getRaw('config', 'sku_id')
self.seckill_num = global_config.getRaw('config', 'seckill_num')
self.work_count = global_config.getRaw('config','process_num')
self.seckill_init_info = dict()
self.seckill_url = dict()
self.seckill_order_data = dict()
self.timers = Timer()

self.session = self.spider_session.get_session()
self.user_agent = self.spider_session.user_agent
self.nick_name = None

def login_by_qrcode(self):
"""
二维码登陆
:return:
"""
if self.qrlogin.is_login:
logger.info('登录成功')
return

self.qrlogin.login_by_qrcode()

if self.qrlogin.is_login:
self.nick_name = self.get_username()
self.spider_session.save_cookies_to_local(self.nick_name)
else:
raise SKException("二维码登录失败!")

def check_login(func):
"""
用户登陆态校验装饰器。若用户未登陆,则调用扫码登陆
"""

@functools.wraps(func)
def new_func(self, *args, **kwargs):
if not self.qrlogin.is_login:
logger.info("{0} 需登陆后调用,开始扫码登陆".format(func.__name__))
self.login_by_qrcode()
return func(self, *args, **kwargs)

return new_func

@check_login
def reserve(self):
"""
预约
"""
self._reserve()

@check_login
def seckill(self):
"""
抢购
"""
self._seckill()

@check_login
def seckill_by_proc_pool(self):
"""
多进程进行抢购
work_count:进程数量
"""
with ProcessPoolExecutor() as pool:
for i in range(self.work_count):
pool.submit(self.seckill)

def _reserve(self):
"""
预约
"""
while True:
try:
self.make_reserve()
break
except Exception as e:
logger.info('预约发生异常!', e)
wait_some_time()

def _seckill(self):
"""
抢购
"""
while True:
try:
self.request_seckill_url()
while True:
self.request_seckill_checkout_page()
self.submit_seckill_order()
except Exception as e:
logger.info('抢购发生异常,稍后继续执行!', e)
wait_some_time()

def make_reserve(self):
"""商品预约"""
logger.info('商品名称:{}'.format(self.get_sku_title()))
url = 'https://yushou.jd.com/youshouinfo.action?'
payload = {
'callback': 'fetchJSON',
'sku': self.sku_id,
'_': str(int(time.time() * 1000)),
}
headers = {
'User-Agent': self.user_agent,
'Referer': 'https://item.jd.com/{}.html'.format(self.sku_id),
}
resp = self.session.get(url=url, params=payload, headers=headers)
resp_json = parse_json(resp.text)
reserve_url = resp_json.get('url')
# self.timers.start()
while True:
try:
self.session.get(url='https:' + reserve_url)
logger.info('预约成功,已获得抢购资格 / 您已成功预约过了,无需重复预约')
if global_config.getRaw('messenger', 'enable') == 'true':
success_message = "预约成功,已获得抢购资格 / 您已成功预约过了,无需重复预约"
send_wechat(success_message)
break
except Exception as e:
logger.error('预约失败正在重试...')

def get_username(self):
"""获取用户信息"""
url = 'https://passport.jd.com/user/petName/getUserInfoForMiniJd.action'
payload = {
'callback': 'jQuery{}'.format(random.randint(1000000, 9999999)),
'_': str(int(time.time() * 1000)),
}
headers = {
'User-Agent': self.user_agent,
'Referer': 'https://order.jd.com/center/list.action',
}

resp = self.session.get(url=url, params=payload, headers=headers)

try_count = 5
while not resp.text.startswith("jQuery"):
try_count = try_count - 1
if try_count > 0:
resp = self.session.get(url=url, params=payload, headers=headers)
else:
break
wait_some_time()
# 响应中包含了许多用户信息,现在在其中返回昵称
# jQuery2381773({"imgUrl":"//storage.360buyimg.com/i.imageUpload/xxx.jpg","lastLoginTime":"","nickName":"xxx","plusStatus":"0","realName":"xxx","userLevel":x,"userScoreVO":{"accountScore":xx,"activityScore":xx,"consumptionScore":xxxxx,"default":false,"financeScore":xxx,"pin":"xxx","riskScore":x,"totalScore":xxxxx}})
return parse_json(resp.text).get('nickName')

def get_sku_title(self):
"""获取商品名称"""
url = 'https://item.jd.com/{}.html'.format(global_config.getRaw('config', 'sku_id'))
resp = self.session.get(url).content
x_data = etree.HTML(resp)
sku_title = x_data.xpath('/html/head/title/text()')
return sku_title[0]

def get_seckill_url(self):
"""获取商品的抢购链接
点击"抢购"按钮后,会有两次302跳转,最后到达订单结算页面
这里返回第一次跳转后的页面url,作为商品的抢购链接
:return: 商品的抢购链接
"""
url = 'https://itemko.jd.com/itemShowBtn'
payload = {
'callback': 'jQuery{}'.format(random.randint(1000000, 9999999)),
'skuId': self.sku_id,
'from': 'pc',
'_': str(int(time.time() * 1000)),
}
headers = {
'User-Agent': self.user_agent,
'Host': 'itemko.jd.com',
'Referer': 'https://item.jd.com/{}.html'.format(self.sku_id),
}
while True:
resp = self.session.get(url=url, headers=headers, params=payload)
resp_json = parse_json(resp.text)
if resp_json.get('url'):
# https://divide.jd.com/user_rou ... %3Dpc
router_url = 'https:' + resp_json.get('url')
# https://marathon.jd.com/captch ... %3Dpc
seckill_url = router_url.replace(
'divide', 'marathon').replace(
'user_routing', 'captcha.html')
logger.info("抢购链接获取成功: %s", seckill_url)
return seckill_url
else:
logger.info("抢购链接获取失败,稍后自动重试")
wait_some_time()

def request_seckill_url(self):
"""访问商品的抢购链接(用于设置cookie等"""
logger.info('用户:{}'.format(self.get_username()))
logger.info('商品名称:{}'.format(self.get_sku_title()))
self.timers.start() # 阻塞

self.seckill_url[self.sku_id] = self.get_seckill_url()
logger.info('访问商品的抢购连接...')
headers = {
'User-Agent': self.user_agent,
'Host': 'marathon.jd.com',
'Referer': 'https://item.jd.com/{}.html'.format(self.sku_id),
}
self.session.get(
url=self.seckill_url.get(
self.sku_id),
headers=headers,
allow_redirects=False)

def request_seckill_checkout_page(self):
"""访问抢购订单结算页面"""
logger.info('访问抢购订单结算页面...')
url = 'https://marathon.jd.com/seckill/seckill.action'
payload = {
'skuId': self.sku_id,
'num': self.seckill_num,
'rid': int(time.time())
}
headers = {
'User-Agent': self.user_agent,
'Host': 'marathon.jd.com',
'Referer': 'https://item.jd.com/{}.html'.format(self.sku_id),
}
self.session.get(url=url, params=payload, headers=headers, allow_redirects=False)

def _get_seckill_init_info(self):
"""获取秒杀初始化信息(包括:地址,发票,token)
:return: 初始化信息组成的dict
"""
logger.info('获取秒杀初始化信息...')
url = 'https://marathon.jd.com/seckillnew/orderService/pc/init.action'
data = {
'sku': self.sku_id,
'num': self.seckill_num,
'isModifyAddress': 'false',
}
headers = {
'User-Agent': self.user_agent,
'Host': 'marathon.jd.com',
}
resp = self.session.post(url=url, data=data, headers=headers)

resp_json = None
try:
resp_json = parse_json(resp.text)
except Exception:
raise SKException('抢购失败,返回信息:{}'.format(resp.text[0: 128]))

return resp_json

def _get_seckill_order_data(self):
"""生成提交抢购订单所需的请求体参数
:return: 请求体参数组成的dict
"""
logger.info('生成提交抢购订单所需参数...')
# 获取用户秒杀初始化信息
self.seckill_init_info[self.sku_id] = self._get_seckill_init_info()
init_info = self.seckill_init_info.get(self.sku_id)
default_address = init_info['addressList'][0] # 默认地址dict
invoice_info = init_info.get('invoiceInfo', {}) # 默认发票信息dict, 有可能不返回
token = init_info['token']
data = {
'skuId': self.sku_id,
'num': self.seckill_num,
'addressId': default_address['id'],
'yuShou': 'true',
'isModifyAddress': 'false',
'name': default_address['name'],
'provinceId': default_address['provinceId'],
'cityId': default_address['cityId'],
'countyId': default_address['countyId'],
'townId': default_address['townId'],
'addressDetail': default_address['addressDetail'],
'mobile': default_address['mobile'],
'mobileKey': default_address['mobileKey'],
'email': default_address.get('email', ''),
'postCode': '',
'invoiceTitle': invoice_info.get('invoiceTitle', -1),
'invoiceCompanyName': '',
'invoiceContent': invoice_info.get('invoiceContentType', 1),
'invoiceTaxpayerNO': '',
'invoiceEmail': '',
'invoicePhone': invoice_info.get('invoicePhone', ''),
'invoicePhoneKey': invoice_info.get('invoicePhoneKey', ''),
'invoice': 'true' if invoice_info else 'false',
'password': global_config.get('account', 'payment_pwd'),
'codTimeType': 3,
'paymentType': 4,
'areaCode': '',
'overseas': 0,
'phone': '',
'eid': global_config.getRaw('config', 'eid'),
'fp': global_config.getRaw('config', 'fp'),
'token': token,
'pru': ''
}

return data

def submit_seckill_order(self):
"""提交抢购(秒杀)订单
:return: 抢购结果 True/False
"""
url = 'https://marathon.jd.com/seckillnew/orderService/pc/submitOrder.action'
payload = {
'skuId': self.sku_id,
}
try:
self.seckill_order_data[self.sku_id] = self._get_seckill_order_data()
except Exception as e:
logger.info('抢购失败,无法获取生成订单的基本信息,接口返回:【{}】'.format(str(e)))
return False

logger.info('提交抢购订单...')
headers = {
'User-Agent': self.user_agent,
'Host': 'marathon.jd.com',
'Referer': 'https://marathon.jd.com/seckill/seckill.action?skuId={0}&num={1}&rid={2}'.format(
self.sku_id, self.seckill_num, int(time.time())),
}
resp = self.session.post(
url=url,
params=payload,
data=self.seckill_order_data.get(
self.sku_id),
headers=headers)
resp_json = None
try:
resp_json = parse_json(resp.text)
except Exception as e:
logger.info('抢购失败,返回信息:{}'.format(resp.text[0: 128]))
return False
# 返回信息
# 抢购失败:
# {'errorMessage': '很遗憾没有抢到,再接再厉哦。', 'orderId': 0, 'resultCode': 60074, 'skuId': 0, 'success': False}
# {'errorMessage': '抱歉,您提交过快,请稍后再提交订单!', 'orderId': 0, 'resultCode': 60017, 'skuId': 0, 'success': False}
# {'errorMessage': '系统正在开小差,请重试~~', 'orderId': 0, 'resultCode': 90013, 'skuId': 0, 'success': False}
# 抢购成功:
# {"appUrl":"xxxxx","orderId":820227xxxxx,"pcUrl":"xxxxx","resultCode":0,"skuId":0,"success":true,"totalMoney":"xxxxx"}
if resp_json.get('success'):
order_id = resp_json.get('orderId')
total_money = resp_json.get('totalMoney')
pay_url = 'https:' + resp_json.get('pcUrl')
logger.info('抢购成功,订单号:{}, 总价:{}, 电脑端付款链接:{}'.format(order_id, total_money, pay_url))
if global_config.getRaw('messenger', 'enable') == 'true':
success_message = "抢购成功,订单号:{}, 总价:{}, 电脑端付款链接:{}".format(order_id, total_money, pay_url)
send_wechat(success_message)
return True
else:
logger.info('抢购失败,返回信息:{}'.format(resp_json))
if global_config.getRaw('messenger', 'enable') == 'true':
error_message = '抢购失败,返回信息:{}'.format(resp_json)
send_wechat(error_message)
return False





 
苏宁脚本目前在测试途中,需要继续调试。
原创文章,
转载请注明:http://30daydo.com/article/44129 
欢迎关注公众号:
可转债量化分析


 

霍华德 马斯克 周期 mobi kindel电子书下载

书籍李魔佛 发表了文章 • 0 个评论 • 295 次浏览 • 2021-01-05 18:13 • 来自相关话题

一本不错的书,在人大经管网站下载的,花了几个币,需要的朋友拿去。
为了规避屏蔽风险,请关注公众号后,在后台回复关键字即可

 

回复:周期 
即可获取下载链接。
  查看全部
一本不错的书,在人大经管网站下载的,花了几个币,需要的朋友拿去。
为了规避屏蔽风险,请关注公众号后,在后台回复关键字即可

 

回复:周期 
即可获取下载链接。