通知设置 新通知
可转债费率百分之二 全市场最便宜
券商万一免五 • 绫波丽 发表了文章 • 0 个评论 • 3380 次浏览 • 2021-03-14 02:03
目前根据可转债新规 沪市十万分之4.1,深市十万分之4。支持同花顺交易
没有最低5元限制,也没有任何最低限制。
以前旧的费率可转债 沪市 百万分之二已经不复存在了。大部分券商把存量的用户也提高了。
需要的朋友欢迎扫码加我开户吧
备注:开户
非诚勿扰!
查看全部
目前根据可转债新规 沪市十万分之4.1,深市十万分之4。支持同花顺交易
没有最低5元限制,也没有任何最低限制。
以前旧的费率可转债 沪市 百万分之二已经不复存在了。大部分券商把存量的用户也提高了。
需要的朋友欢迎扫码加我开户吧
备注:开户
非诚勿扰!
requests使用断点续传时注意要加stream=True,不然你的硬盘可能会爆掉
python爬虫 • 李魔佛 发表了文章 • 0 个评论 • 4009 次浏览 • 2021-03-14 00:56
with open(dst, "ab") as f:
dp = Down_progress(file_size, first_size, dst)
dp.start()
chunk_size = 1024
for chunk in res.iter_content(chunk_size = chunk_size):
if chunk:
f.write(chunk)
dp.update(chunk_size)
如果不加stream=True,那么你的硬盘很可能就不停被写入,文件会变得无比巨大,最后磁盘空间不够死机。
不要问我为什么知道。 查看全部
res = requests.get(url, stream=True, headers=headers, verify=False)
with open(dst, "ab") as f:
dp = Down_progress(file_size, first_size, dst)
dp.start()
chunk_size = 1024
for chunk in res.iter_content(chunk_size = chunk_size):
if chunk:
f.write(chunk)
dp.update(chunk_size)
如果不加stream=True,那么你的硬盘很可能就不停被写入,文件会变得无比巨大,最后磁盘空间不够死机。
不要问我为什么知道。
弘盈A - 套套利者
股票 • 李魔佛 发表了文章 • 0 个评论 • 1925 次浏览 • 2021-03-12 19:38
而赎回后的手续费是算入基金的净值。
所以策略就很明显,点到即止。
### 2021-03-27 更新 ##########
判断错误,原来这个基金是打算清盘的了。
限制申购后第一天地天板。公司是早有预谋,关联方收集筹码,便于开基金持有人大会时投票通过。 查看全部
而赎回后的手续费是算入基金的净值。
所以策略就很明显,点到即止。
### 2021-03-27 更新 ##########
判断错误,原来这个基金是打算清盘的了。
限制申购后第一天地天板。公司是早有预谋,关联方收集筹码,便于开基金持有人大会时投票通过。
a股券商开户 万1免五 没有最低消费
券商万一免五 • 李魔佛 发表了文章 • 0 个评论 • 12535 次浏览 • 2021-03-07 17:51
不过之前还找到一家万一免五的,没有最低费率,用多少算多少,比如买了1000元股票,那么费率只有1000*万分之一,等于1分钱,略等于不用钱哈。
优势杠杆的。
需要的点击下面链接即可开户: 注意:当前默认的免五已经取消了,需要开通量化交易权限后可以进行免五操作。
开通ptrade和qmt量化交易接口的条件,入金30万,过3天左右可以开通,开通后可以免五!
交割单:
心动不,赶紧心动吧。
该券商也支持同花顺客户端登录,做量化的使用easytrader也可以友好支持。
如果有疑问,可以扫码咨询。备注:开户
查看全部
富途牛牛的模拟买入卖出无法生效
股票 • 李魔佛 发表了文章 • 0 个评论 • 6351 次浏览 • 2021-03-03 18:44
下图是富途美股的期权交易
后来咨询了客服,原来富途的模拟撮合系统需要真实有成交才能生效。
也就是你挂卖一价,比如10元,你挂一个买单10,是不会成交的,甚至挂一个12,13,也不会成交,需要在实盘交易中,其他人成交了一单,你的模拟才会真正成交。而且如果实盘别人成交的是100股,你模拟挂单的是200股,那么实际成交也只会是100股。
最近入手的期权模拟,先练练手。
港股,美股的账号默认就帮你开了期权和模拟账号,放心玩。不像股需要一定的资金体量还要考试等几天。
在上面拿来练手最好不过了,白天可以练港股,晚上可以练美股。
推荐开个富途玩玩,不需要入金也可以玩,注册账号分分钟的事情。
富途开户链接
一步一步注册即可。可以不入金就可以模拟。
查看全部
下图是富途美股的期权交易
后来咨询了客服,原来富途的模拟撮合系统需要真实有成交才能生效。
也就是你挂卖一价,比如10元,你挂一个买单10,是不会成交的,甚至挂一个12,13,也不会成交,需要在实盘交易中,其他人成交了一单,你的模拟才会真正成交。而且如果实盘别人成交的是100股,你模拟挂单的是200股,那么实际成交也只会是100股。
最近入手的期权模拟,先练练手。
港股,美股的账号默认就帮你开了期权和模拟账号,放心玩。不像股需要一定的资金体量还要考试等几天。
在上面拿来练手最好不过了,白天可以练港股,晚上可以练美股。
推荐开个富途玩玩,不需要入金也可以玩,注册账号分分钟的事情。
富途开户链接
一步一步注册即可。可以不入金就可以模拟。
github上私有仓库提交的星星是不会显示
每日总结 • 李魔佛 发表了文章 • 0 个评论 • 1912 次浏览 • 2021-02-26 18:58
登录后
登录前
chrome secure shell插件无法上传下载文件
Linux • 李魔佛 发表了文章 • 0 个评论 • 1706 次浏览 • 2021-02-22 19:28
后记:
只好用scp传输啦,还好windows平台的git客户端。
后记:
只好用scp传输啦,还好windows平台的git客户端。
redis启动报错
数据库 • 李魔佛 发表了文章 • 0 个评论 • 3219 次浏览 • 2021-02-21 14:50
Failed to start Advanced key-value store
csdn查出来的全是垃圾。
后面再stackoverflow看了下,尝试其中一个方案:
使用命令启动
/usr/bin/redis-server /etc/redis/redis-conf
然后一起就又正常了, 如果还是报错,把bind的ip地址后面那截改为127.0.0.1,后面那个ipv6格式的不要 查看全部
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 个评论 • 2001 次浏览 • 2021-02-20 00:28
而在数据量很大的情况下,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就是列数,不断地写在第一行和第二行,就可以达到所要的需求了。
查看全部
而在数据量很大的情况下,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 个评论 • 2166 次浏览 • 2021-02-06 22:38
python的发邮件代码demo:
try:
stmp.connect(host='smtp.mxhichina.com', port=80)
stmp.login(username, password)
stmp.sendmail(username, TO_MAIL_, msg.as_string()) 查看全部
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 个评论 • 2091 次浏览 • 2021-02-05 09:27
结果启动后卡了很久,当时还以为内存消耗比较大,kill了一下,结果还是很快,原来当时是在后台删除数据。。。。。
启动后发现,数据不见了,要重新登录。。。。哭。。。。 查看全部
结果启动后卡了很久,当时还以为内存消耗比较大,kill了一下,结果还是很快,原来当时是在后台删除数据。。。。。
启动后发现,数据不见了,要重新登录。。。。哭。。。。
chrome浏览器右下加弹出广告
网络安全 • 李魔佛 发表了文章 • 0 个评论 • 1859 次浏览 • 2021-02-02 21:46
在提示通知里面,把所有允许的网站给移出就可以了
在提示通知里面,把所有允许的网站给移出就可以了
看到用户在b站的墨茶下的留言
闲聊 • 李魔佛 发表了文章 • 0 个评论 • 2018 次浏览 • 2021-01-30 15:26
留言的人何尝不是。
安装nodejs后新增的python把原来的python版本覆盖了
python • 李魔佛 发表了文章 • 0 个评论 • 3896 次浏览 • 2021-01-29 14:58
解决办法:
win10: 打开环境变量,把第一个python39或者类似字样的环境变量往下移,最好移到最后。
解决办法:
win10: 打开环境变量,把第一个python39或者类似字样的环境变量往下移,最好移到最后。
交易所的基金份额更新时间
股票 • 李魔佛 发表了文章 • 0 个评论 • 2089 次浏览 • 2021-01-21 23:05
具体时间再T+1 收盘前,待会测试下给结果。 上午开盘前9点没见到数据更新,中午1点前已经更新了的。
最新的数据在11:30已经出来了
基金的份额是怎么算的
股票 • 李魔佛 发表了文章 • 0 个评论 • 1905 次浏览 • 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 个评论 • 7825 次浏览 • 2021-01-21 11:24
只能重新注册一个新账号了。
如果有需要开港卡,可以联系,国内见面开户,一次性收中介费,以后无年费,管理费。
需要的联系
需要资料:
1.身份证复印件
2.护照复印件(如果实在没有护照的,通行证也可以)
3.开户申请表(现在一个表格就可以搞定,不用6个)
4.资产证明(余额还是要求50万以上)。
PS:资产证明:可以是银行打印的纸质流水,也可以是股票,基金,支付宝这种电子的账单也行。
如果达不到,可以代办,不影响。 查看全部
只能重新注册一个新账号了。
如果有需要开港卡,可以联系,国内见面开户,一次性收中介费,以后无年费,管理费。
需要的联系
需要资料:
1.身份证复印件
2.护照复印件(如果实在没有护照的,通行证也可以)
3.开户申请表(现在一个表格就可以搞定,不用6个)
4.资产证明(余额还是要求50万以上)。
PS:资产证明:可以是银行打印的纸质流水,也可以是股票,基金,支付宝这种电子的账单也行。
如果达不到,可以代办,不影响。
armdebian 修改大写键 为esc
Linux • 李魔佛 发表了文章 • 0 个评论 • 2210 次浏览 • 2021-01-18 18:15
armdebian上没有xmodmap 这个软件,但有一个xkeycaps的GUI的小应用,可以很方便地修改在图形界面上修改按键映射。
而且xkeycaps修改是持续有效的,如果想该回去,上面有个restore的功能,可以一键恢复默认值。
查看全部
armdebian上没有xmodmap 这个软件,但有一个xkeycaps的GUI的小应用,可以很方便地修改在图形界面上修改按键映射。
而且xkeycaps修改是持续有效的,如果想该回去,上面有个restore的功能,可以一键恢复默认值。
python解析windows日志文件,查询服务器是否被人攻击
python • 李魔佛 发表了文章 • 0 个评论 • 4173 次浏览 • 2021-01-17 23:49
最终效果:
【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日志解析获取
查看全部
最终效果:
【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 个评论 • 10964 次浏览 • 2021-01-05 22:34
运行环境 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
欢迎关注公众号:
可转债量化分析
查看全部
运行环境 windows,linux,mac,python3+
京东小白分查询:
https://plus.m.jd.com/rights/windControl
分太低的就不要参与了,毕竟概率会小很多
############ 2021-01-13 更新 ======
最新的用Go重写的,搞了几瓶
苏宁家的:
============= 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
欢迎关注公众号:
可转债量化分析
bbdoc居然不支持代码搜索
Linux • 李魔佛 发表了文章 • 0 个评论 • 2095 次浏览 • 2021-01-03 16:54
什么python,cpp,java一个都不支持。
什么python,cpp,java一个都不支持。
win7安装sshd服务
闲聊 • 李魔佛 发表了文章 • 0 个评论 • 3106 次浏览 • 2020-12-29 08:52
Recently, Microsoft has released a port of OpenSSH for Windows. You can use the package to set up an SFTP/SSH server on Windows.Installing SFTP/SSH Server
On Windows 10 version 1803 and newer
On earlier versions of Windows
https://github.com/PowerShell/Win32-OpenSSH/releases
Configuring SSH server
Setting up SSH public key authentication
Connecting to the server
Finding Host Key
Connecting
Further readingInstalling SFTP/SSH Server
On Windows 10 version 1803 and newerIn Settings app, go to Apps > Apps & features > Manage optional features.
Locate “OpenSSH server” feature, expand it, and select Install.Binaries are installed to %WINDIR%\System32\OpenSSH.
Configuration file (sshd_config) and host keys are installed to %ProgramData%\ssh
(only after the server is started for the first time).
You may still want to use the following manual installation, if you want to install a newer version of OpenSSH than the one built into Windows 10.
On earlier versions of WindowsDownload the latest OpenSSH for Windows binaries (package OpenSSH-Win64.zip or OpenSSH-Win32.zip)
As the Administrator, extract the package to C:\Program Files\OpenSSH
As the Administrator, install sshd and ssh-agent services:
powershell.exe -ExecutionPolicy Bypass -File install-sshd.ps1
Configuring SSH serverAllow incoming connections to SSH server in Windows Firewall:
When installed as an optional feature, the firewall rule “OpenSSH SSH Server (sshd)” should have been created automatically. If not, proceed to create and enable the rule as follows.
Either run the following PowerShell command as the Administrator:New-NetFirewallRule -Name sshd -DisplayName 'OpenSSH SSH Server' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22 -Program "C:\System32\OpenSSH\sshd.exe"
Replace C:\System32\OpenSSH\sshd.exe with the actual path to the sshd.exe
(C:\Program Files\OpenSSH\ssh.exe,
had you followed the manual installation instructions above).or go to Control Panel > System and Security > Windows Firewall1 > Advanced Settings > Inbound Rules and add a new rule for port 22.
Start the service and/or configure automatic start:
Go to Control Panel > System and Security > Administrative Tools and open Services. Locate OpenSSH SSH Server service.
If you want the server to start automatically when your machine is started: Go to Action > Properties. In the Properties dialog, change Startup type to Automatic and confirm.
Start the OpenSSH SSH Server service by clicking the Start the service.These instructions are partially based on the official deployment instructions. 查看全部
Recently, Microsoft has released a port of OpenSSH for Windows. You can use the package to set up an SFTP/SSH server on Windows.Installing SFTP/SSH Server
On Windows 10 version 1803 and newer
On earlier versions of Windows
https://github.com/PowerShell/Win32-OpenSSH/releases
Configuring SSH server
Setting up SSH public key authentication
Connecting to the server
Finding Host Key
Connecting
Further readingInstalling SFTP/SSH Server
On Windows 10 version 1803 and newerIn Settings app, go to Apps > Apps & features > Manage optional features.
Locate “OpenSSH server” feature, expand it, and select Install.Binaries are installed to %WINDIR%\System32\OpenSSH.
Configuration file (sshd_config) and host keys are installed to %ProgramData%\ssh
(only after the server is started for the first time).
You may still want to use the following manual installation, if you want to install a newer version of OpenSSH than the one built into Windows 10.
On earlier versions of WindowsDownload the latest OpenSSH for Windows binaries (package OpenSSH-Win64.zip or OpenSSH-Win32.zip)
As the Administrator, extract the package to C:\Program Files\OpenSSH
As the Administrator, install sshd and ssh-agent services:
powershell.exe -ExecutionPolicy Bypass -File install-sshd.ps1
Configuring SSH serverAllow incoming connections to SSH server in Windows Firewall:
When installed as an optional feature, the firewall rule “OpenSSH SSH Server (sshd)” should have been created automatically. If not, proceed to create and enable the rule as follows.
Either run the following PowerShell command as the Administrator:New-NetFirewallRule -Name sshd -DisplayName 'OpenSSH SSH Server' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22 -Program "C:\System32\OpenSSH\sshd.exe"
Replace C:\System32\OpenSSH\sshd.exe with the actual path to the sshd.exe
(C:\Program Files\OpenSSH\ssh.exe,
had you followed the manual installation instructions above).or go to Control Panel > System and Security > Windows Firewall1 > Advanced Settings > Inbound Rules and add a new rule for port 22.
Start the service and/or configure automatic start:
Go to Control Panel > System and Security > Administrative Tools and open Services. Locate OpenSSH SSH Server service.
If you want the server to start automatically when your machine is started: Go to Action > Properties. In the Properties dialog, change Startup type to Automatic and confirm.
Start the OpenSSH SSH Server service by clicking the Start the service.These instructions are partially based on the official deployment instructions.
网易云音乐居然还有linux版本,网易还是一个良心企业
Linux • 李魔佛 发表了文章 • 0 个评论 • 2456 次浏览 • 2020-12-18 11:31
啥时候有道云笔记也搞一个linux版本的呀.
如果要在ubuntu16.04上安装,就不要去官网下载,gclib库不兼容,要升级到18.04, 会会很折腾.
直接下载:
$ wget http://s1.music.126.net/downlo ... 4.deb --默认下载到Desktop
然后sudo dpkg -i xxxxx.deb 就可以啦
良心的还要搜狗,linux下的输入法好用.
更新:
安装上面方法安装后,可以打开,可以播放mv,不过就是无法播放声音.
需要解决依赖问题.
网上找到了好的方法: 亲测有效
更改源为阿里云的源
# deb cdrom:[Ubuntu 16.04 LTS _Xenial Xerus_ - Release amd64 (20160420.1)]/ xenial main restricted
deb-src http://archive.ubuntu.com/ubuntu xenial main restricted #Added by software-properties
deb http://mirrors.aliyun.com/ubuntu/ xenial main restricted
deb-src http://mirrors.aliyun.com/ubuntu/ xenial main restricted multiverse universe #Added by software-properties
deb http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted
deb-src http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted multiverse universe #Added by software-properties
deb http://mirrors.aliyun.com/ubuntu/ xenial universe
deb http://mirrors.aliyun.com/ubuntu/ xenial-updates universe
deb http://mirrors.aliyun.com/ubuntu/ xenial multiverse
deb http://mirrors.aliyun.com/ubuntu/ xenial-updates multiverse
deb http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse #Added by software-properties
deb http://archive.canonical.com/ubuntu xenial partner
deb-src http://archive.canonical.com/ubuntu xenial partner
deb http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted
deb-src http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted multiverse universe #Added by software-properties
deb http://mirrors.aliyun.com/ubuntu/ xenial-security universe
deb http://mirrors.aliyun.com/ubuntu/ xenial-security multiversean然后运行 apt -f install 修复依赖关系就可以了.
查看全部
啥时候有道云笔记也搞一个linux版本的呀.
如果要在ubuntu16.04上安装,就不要去官网下载,gclib库不兼容,要升级到18.04, 会会很折腾.
直接下载:
$ wget http://s1.music.126.net/downlo ... 4.deb --默认下载到Desktop
然后sudo dpkg -i xxxxx.deb 就可以啦
良心的还要搜狗,linux下的输入法好用.
更新:
安装上面方法安装后,可以打开,可以播放mv,不过就是无法播放声音.
需要解决依赖问题.
网上找到了好的方法: 亲测有效
更改源为阿里云的源
# deb cdrom:[Ubuntu 16.04 LTS _Xenial Xerus_ - Release amd64 (20160420.1)]/ xenial main restricted然后运行 apt -f install 修复依赖关系就可以了.
deb-src http://archive.ubuntu.com/ubuntu xenial main restricted #Added by software-properties
deb http://mirrors.aliyun.com/ubuntu/ xenial main restricted
deb-src http://mirrors.aliyun.com/ubuntu/ xenial main restricted multiverse universe #Added by software-properties
deb http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted
deb-src http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted multiverse universe #Added by software-properties
deb http://mirrors.aliyun.com/ubuntu/ xenial universe
deb http://mirrors.aliyun.com/ubuntu/ xenial-updates universe
deb http://mirrors.aliyun.com/ubuntu/ xenial multiverse
deb http://mirrors.aliyun.com/ubuntu/ xenial-updates multiverse
deb http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse #Added by software-properties
deb http://archive.canonical.com/ubuntu xenial partner
deb-src http://archive.canonical.com/ubuntu xenial partner
deb http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted
deb-src http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted multiverse universe #Added by software-properties
deb http://mirrors.aliyun.com/ubuntu/ xenial-security universe
deb http://mirrors.aliyun.com/ubuntu/ xenial-security multiversean
在阿里云的服务器上登录淘宝提示 访问被拒绝
闲聊 • 李魔佛 发表了文章 • 0 个评论 • 5110 次浏览 • 2020-12-16 08:45
亲,访问被拒绝
可能因为:
请检查是否使用了代理软件或 VPN 哦~
只能说阿里的工程师够懒的(la ji),一刀切,粗暴简单省事.
亲,访问被拒绝
可能因为:
请检查是否使用了代理软件或 VPN 哦~
只能说阿里的工程师够懒的(la ji),一刀切,粗暴简单省事.
python函数调用后面可以有一个空格
python • 李魔佛 发表了文章 • 0 个评论 • 2397 次浏览 • 2020-12-13 11:13
print ('hello')
hello
def sayhi():
...: print('Done')
...:
sayhi () # 这里有一个空格
Done
不过如果平时这么写,会被人打的 查看全部
print ('hello')
hello
def sayhi():
...: print('Done')
...:
sayhi () # 这里有一个空格
Done
不过如果平时这么写,会被人打的
导出python自带关键字 keyword
python • 李魔佛 发表了文章 • 0 个评论 • 2155 次浏览 • 2020-12-13 10:57
import keyword
keyword.kwlist
Out[3]:
['False',
'None',
'True',
'and',
'as',
'assert',
'async',
'await',
'break',
'class',
'continue',
'def',
'del',
'elif',
'else',
'except',
'finally',
'for',
'from',
'global',
'if',
'import',
'in',
'is',
'lambda',
'nonlocal',
'not',
'or',
'pass',
'raise',
'return',
'try',
'while',
'with',
'yield']
len(keyword.kwlist)
Out[4]: 35 查看全部
import keyword
keyword.kwlist
Out[3]:
['False',
'None',
'True',
'and',
'as',
'assert',
'async',
'await',
'break',
'class',
'continue',
'def',
'del',
'elif',
'else',
'except',
'finally',
'for',
'from',
'global',
'if',
'import',
'in',
'is',
'lambda',
'nonlocal',
'not',
'or',
'pass',
'raise',
'return',
'try',
'while',
'with',
'yield']
len(keyword.kwlist)
Out[4]: 35
微信公众号后台的签名校验的官方教程在python3下不兼容
python • 李魔佛 发表了文章 • 0 个评论 • 2221 次浏览 • 2020-12-11 11:43
首先文档用的python2代码写的,但文中没有标明。
python2旧就算了,而且那么多框架不用,还要用一个老掉牙的web.py来写,也是醉了。
django下的签名校验:token = '123456789'
def Services(request):
print(request.method)
if request.method=='GET':
signature = request.GET.get('signature')
echostr = request.GET.get('echostr')
timestamp = request.GET.get('timestamp')
nonce = request.GET.get('nonce')
list_ = [token, timestamp, nonce]
list_.sort()
list_str = ''.join(list_)
sha1 = hashlib.sha1(list_str.encode('utf8'))
hashcode = sha1.hexdigest()
if hashcode==signature:
return HttpResponse(echostr)
else:
return HttpResponse('')
原创文章,转载请注明出处http://30daydo.com/article/44121
查看全部
首先文档用的python2代码写的,但文中没有标明。
python2旧就算了,而且那么多框架不用,还要用一个老掉牙的web.py来写,也是醉了。
django下的签名校验:
token = '123456789'
def Services(request):
print(request.method)
if request.method=='GET':
signature = request.GET.get('signature')
echostr = request.GET.get('echostr')
timestamp = request.GET.get('timestamp')
nonce = request.GET.get('nonce')
list_ = [token, timestamp, nonce]
list_.sort()
list_str = ''.join(list_)
sha1 = hashlib.sha1(list_str.encode('utf8'))
hashcode = sha1.hexdigest()
if hashcode==signature:
return HttpResponse(echostr)
else:
return HttpResponse('')
原创文章,转载请注明出处http://30daydo.com/article/44121
今晚看了一晚段永平老师的雪球上的问答,颇有感慨
股票 • 李魔佛 发表了文章 • 0 个评论 • 2133 次浏览 • 2020-12-10 00:43
行字之间,看到一位智者在将他的人生哲学侃侃而谈。 受益匪浅。
可惜的是段老师要关闭问答了,而且就是在上周末,来不及在问答里说一声问候,祝安康。
进度:第6页。
行字之间,看到一位智者在将他的人生哲学侃侃而谈。 受益匪浅。
可惜的是段老师要关闭问答了,而且就是在上周末,来不及在问答里说一声问候,祝安康。
进度:第6页。
不用一行代码 下载雪球嘉年华视频
python爬虫 • 李魔佛 发表了文章 • 0 个评论 • 2962 次浏览 • 2020-12-09 14:43
听说今年着重分享一些观念,抱着好奇心,就打算下载几部来看看。
雪球网站很简单,只要找到下载链接就可以下载了。
第一步。打开一个视频播放的页面,比如大金链的
11737544 粉丝主会场 | 巅峰对谈:金牛双子星主动VS量化
https://xueqiu.com/video/5285890810945319765
右键,查看源码,然后在源码里面试着查找 mp4,flv,webp等流媒体字样。
在这里找到一个了:
但是这个视频下载地址有很多转义字符:http:\u002F\u002F1256122120.vod2.myqcloud.com\u002F53ad1740vodtranscq1256122120\u002F17ebe5145285890810945319765\u002Fv.f20.mp4
直接在浏览器是无法直接打开的。
可以直接替换\u002f 为一个斜杠 \ 就可以了。
如果嫌麻烦,可以在浏览器里面,按下F12,在console页面里面输入上面的地址,前后加个双引号,然后回车,就可以得到完整的地址了。
原创文章,转载请注明出处
http://30daydo.com/article/44119
查看全部
听说今年着重分享一些观念,抱着好奇心,就打算下载几部来看看。
雪球网站很简单,只要找到下载链接就可以下载了。
第一步。打开一个视频播放的页面,比如大金链的
11737544 粉丝主会场 | 巅峰对谈:金牛双子星主动VS量化
https://xueqiu.com/video/5285890810945319765
右键,查看源码,然后在源码里面试着查找 mp4,flv,webp等流媒体字样。
在这里找到一个了:
但是这个视频下载地址有很多转义字符:
http:\u002F\u002F1256122120.vod2.myqcloud.com\u002F53ad1740vodtranscq1256122120\u002F17ebe5145285890810945319765\u002Fv.f20.mp4
直接在浏览器是无法直接打开的。
可以直接替换\u002f 为一个斜杠 \ 就可以了。
如果嫌麻烦,可以在浏览器里面,按下F12,在console页面里面输入上面的地址,前后加个双引号,然后回车,就可以得到完整的地址了。
原创文章,转载请注明出处
http://30daydo.com/article/44119