chrome浏览器右下加弹出广告

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

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

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

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

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






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

111111.jpg


留言的人何尝不是。

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

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

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

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

股票李魔佛 发表了文章 • 0 个评论 • 2075 次浏览 • 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 个评论 • 1882 次浏览 • 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 个评论 • 7798 次浏览 • 2021-01-21 11:24 • 来自相关话题

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

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

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

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

armdebian 修改大写键 为esc

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

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

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

python李魔佛 发表了文章 • 0 个评论 • 4154 次浏览 • 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 个评论 • 10938 次浏览 • 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 kindle电子书下载

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

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



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


  查看全部
srchttp___n.sinaimg_.cn_spider20190509_22_w992h630_20190509_93ff-hwsffzc1310377_.jpg

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



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


 

bbdoc居然不支持代码搜索

Linux李魔佛 发表了文章 • 0 个评论 • 2071 次浏览 • 2021-01-03 16:54 • 来自相关话题

那有什么用?辣鸡
什么python,cpp,java一个都不支持。
那有什么用?辣鸡
什么python,cpp,java一个都不支持。

win7安装sshd服务

闲聊李魔佛 发表了文章 • 0 个评论 • 3093 次浏览 • 2020-12-29 08:52 • 来自相关话题

Installing SFTP/SSH Server on Windows using OpenSSH
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. 查看全部
Installing SFTP/SSH Server on Windows using OpenSSH
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 个评论 • 2440 次浏览 • 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 修复依赖关系就可以了.
  查看全部
Workspace_1_0091.png

 
啥时候有道云笔记也搞一个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 修复依赖关系就可以了.
 

在阿里云的服务器上登录淘宝提示 访问被拒绝

闲聊李魔佛 发表了文章 • 0 个评论 • 5088 次浏览 • 2020-12-16 08:45 • 来自相关话题

提示出错是:
亲,访问被拒绝


可能因为:
请检查是否使用了代理软件或 VPN 哦~
只能说阿里的工程师够懒的(la ji),一刀切,粗暴简单省事.
 
 
 
提示出错是:
亲,访问被拒绝


可能因为:
请检查是否使用了代理软件或 VPN 哦~
只能说阿里的工程师够懒的(la ji),一刀切,粗暴简单省事.
 
 
 

python函数调用后面可以有一个空格

python李魔佛 发表了文章 • 0 个评论 • 2381 次浏览 • 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 个评论 • 2135 次浏览 • 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 个评论 • 2205 次浏览 • 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 个评论 • 2109 次浏览 • 2020-12-10 00:43 • 来自相关话题

不仅仅是投资,更多的是人生理念。
行字之间,看到一位智者在将他的人生哲学侃侃而谈。 受益匪浅。
可惜的是段老师要关闭问答了,而且就是在上周末,来不及在问答里说一声问候,祝安康。
 
进度:第6页。
 
 
不仅仅是投资,更多的是人生理念。
行字之间,看到一位智者在将他的人生哲学侃侃而谈。 受益匪浅。
可惜的是段老师要关闭问答了,而且就是在上周末,来不及在问答里说一声问候,祝安康。
 
进度:第6页。
 
 

不用一行代码 下载雪球嘉年华视频

python爬虫李魔佛 发表了文章 • 0 个评论 • 2943 次浏览 • 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
 

chrome_Z6q4VbZu5I1.png

 
右键,查看源码,然后在源码里面试着查找 mp4,flv,webp等流媒体字样。
 
在这里找到一个了:

chrome_WYjENd4ifc.png

 
但是这个视频下载地址有很多转义字符:
http:\u002F\u002F1256122120.vod2.myqcloud.com\u002F53ad1740vodtranscq1256122120\u002F17ebe5145285890810945319765\u002Fv.f20.mp4

直接在浏览器是无法直接打开的。
可以直接替换\u002f 为一个斜杠 \  就可以了。
如果嫌麻烦,可以在浏览器里面,按下F12,在console页面里面输入上面的地址,前后加个双引号,然后回车,就可以得到完整的地址了。
 

mstsc_v7jXwdJbSy.png

原创文章,转载请注明出处
 
http://30daydo.com/article/44119
 

监控公众号取消关注的粉丝

闲聊李魔佛 发表了文章 • 0 个评论 • 2347 次浏览 • 2020-12-08 23:48 • 来自相关话题

一时兴起做这个功能,因为后续还会开发下一个功能,取消关注的用户会被加入黑名单,也就是以后再也无法关注。










 
上面是获取到全部粉丝的数据,原理是直接利用mitmproxy抓包,监听到指定url数据后,把数据导出到文件就可以了。
 
如果需要教程和代码,可以私聊。(哦,网站关闭了注册了,那就公众号留言吧) 查看全部
一时兴起做这个功能,因为后续还会开发下一个功能,取消关注的用户会被加入黑名单,也就是以后再也无法关注。

cmd_vDpWZOE5Kj.png


notepad__PTCvh09ETp.png

 
上面是获取到全部粉丝的数据,原理是直接利用mitmproxy抓包,监听到指定url数据后,把数据导出到文件就可以了。
 
如果需要教程和代码,可以私聊。(哦,网站关闭了注册了,那就公众号留言吧)

优矿数据导出

股票李魔佛 发表了文章 • 0 个评论 • 5957 次浏览 • 2020-12-04 09:11 • 来自相关话题

在优矿上可以把数据保存并导出到本地。
 
比如有一个所有股票的dataframe ->df
df.to_csv('all_stock.csv')
 
然后到左边的数据栏里面,可以在里面看到自己刚刚导出的数据,然后可以选择你刚刚导出的文件,有个选项可以下载,一天可以下载100MB的文件。 查看全部
在优矿上可以把数据保存并导出到本地。
 
比如有一个所有股票的dataframe ->df
df.to_csv('all_stock.csv')
 
然后到左边的数据栏里面,可以在里面看到自己刚刚导出的数据,然后可以选择你刚刚导出的文件,有个选项可以下载,一天可以下载100MB的文件。

雪球上的手哥zangyn 是不是利用bug把收益率做的这么高?

股票绫波丽 发表了文章 • 0 个评论 • 5530 次浏览 • 2020-12-02 12:20 • 来自相关话题

这收益率太恐怖了吧?

每次看他都只是小赚小亏,最后居然还是这么牛叉的收益率。
有知道的朋友吗?

chrome_9tbn19ulAc.png

这收益率太恐怖了吧?

每次看他都只是小赚小亏,最后居然还是这么牛叉的收益率。
有知道的朋友吗?

P站 视频下载 JS加密URL 【JS逆向】

python爬虫李魔佛 发表了文章 • 0 个评论 • 27236 次浏览 • 2020-12-02 10:43 • 来自相关话题

P站,你懂的网站,黄黑风格的。
它的真实下载地址是隐藏在JS加密当中的。
 
接下来我们看看如何找到它的真实地址。
 
首先随便打开一个视频:
我就找一个python学习的视频(什么鬼,上面还有python学习? 是的有的,还有很多数学题目在上面讲解的呢)





 
然后按F12
找到一个疑似的下载地址






试下拷贝直接去打开,发现无法打开,显示403 fobiden。
但是看url,应该就是最终的下载url的格式,通过最后的随机数控制播放权限。
 
然后打开页面的源码
 












 
在里面找下有没有一些mp4等的字符, 然后发现有个720p,1080p不同分辨率格式的字段,我们把这个JavaScript的代码扣下来,然后保存为p_hub.js
 
用vs code 或者其他编辑器打开





看到了他们生成过程了吗? 
 
然后尝试用nodejs运行一下。
什么都没有输出。
 
因为上面代码并没有任何输出语句,我们在最后加一个 console.log(quality_720p); 就会有输出的了。





看到了吗?
然后拿这个地址去试试,看能否播放和下载。
果然,浏览器里面出现了一个, 额, python学习的页面,一个单独的视频页面,所以可以直接右键,弹出一个保存视频的菜单,然后可以直接下载了。
 
用代码requesets.get(url) 保存text.content 写入文件,就可以把视频保存到本地了。
 
源码:#!/usr/bin/env python
# http://30daydo.com
import os
import re
import js2py
import requests
from lxml import etree
from clint.textui import progress
import fire
from loguru import logger

file='crawler'
logger.add(
"logs/%s.log" % file,
format="{time:MM-DD HH:mm:ss} {level} {message}",
)

headers = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36",
}
proxies = {}

# 如果代理不稳定,不推荐使用
# local proxy service
# proxies example:
# proxies = {
# "http": "socks5://127.0.0.1:1080",
# "https": "socks5://127.0.0.1:1080",
# }

def list_page(url):
logger.info("crawling : %s" % url)
resp = requests.get(url, headers=headers, proxies=proxies, verify=False)
html = etree.HTML(resp.text)

buff = '//*[@class="phimage"]/a/'
names = html.xpath(f"{buff}@href")
urls = html.xpath(f"{buff}img/@data-mediabook")
for i in range(len(urls)):
try:
url = urls
[i] name = re.findall("=ph(\w+)", names[i])[-1]
logger.info(f"{url} {name}")
download(url, name, "webm")
except Exception as err:
logger.error(err)


def detail_page(url):
s = requests.Session()
resp = s.get(url, headers=headers, proxies=proxies, verify=False)
html = etree.HTML(resp.content)

title = "".join(html.xpath("//h1//text()")).strip()
logger.info(title)

js_temp = html.xpath("//script/text()")
for j in js_temp:
if "flashvars" in j:
videoUrl = exeJs(j)

download(videoUrl, title, "mp4")
continue


def exeJs(js):
flashvars = re.findall("flashvars_\d+", js)[0]
js = "\n\t".join(js.split("\n\t")[:-5]).strip()

js = js.replace("// var nextVideoObject = flashvars_['nextVideo'];",'')
js+=flashvars
res = js2py.eval_js(js)

if res.quality_720p:
return res.quality_720p
elif res.quality_480p:
return res.quality_480p
elif res.quality_240p:
return res.quality_240p
else:
logger.error("parse url error")


def download(url, name, filetype):
logger.info(f"{url} {name} {filetype}")
filepath = "%s/%s.%s" % (filetype, name, filetype)
if os.path.exists(filepath):
logger.info("this file had been downloaded :: %s" % filepath)
return
else:
response = requests.get(url, headers=headers, proxies=proxies, stream=True)
with open(filepath, "wb") as file:
total_length = int(response.headers.get("content-length"))
for ch in progress.bar(
response.iter_content(chunk_size=2391975),
expected_size=(total_length / 1024) + 1,
):
if ch:
file.write(ch)

logger.info("download success :: %s" % filepath)


def run(_arg=None):
paths = ["webm", "mp4"]
for path in paths:
if not os.path.exists(path):
os.mkdir(path)
if _arg == "webm":
# https://www.pornhub.com/categories
urls = [
# "https://www.pornhub.com/video?o=tr",
# "https://www.pornhub.com/video?o=ht",
# "https://www.pornhub.com/video?o=mv",
"https://www.pornhub.com/video",
]
for url in urls:
list_page(url)
elif _arg == "mp4":
with open("download.txt", "r") as file:
keys = list(set(file.readlines()))
logger.info(keys)
keys += [d.strip(".webm") for d in os.listdir("webm/")]
for key in keys:
if not key.strip():
continue
url = "https://www.pornhub.com/view_v ... ot%3B % key.strip()
logger.info("url: {}", url)
detail_page(url)
else:
_str = """
tips:
python crawler.py webm
- 下载热门页面的缩略图,路径为webm文件夹下

python crawler.py mp4
- 该命令会下载webm文件下对应的mp4文件
- 也可以将目标地址写入download.txt中
"""
logger.info(_str)
return
logger.info("finish !")


if __name__ == "__main__":
fire.Fire(run)
[/i][/i]

[i]原创文章,
转载请注明出处:
http://30daydo.com/article/44115 

 [/i]
[i]


[/i] 查看全部
P站,你懂的网站,黄黑风格的。
它的真实下载地址是隐藏在JS加密当中的。
 
接下来我们看看如何找到它的真实地址。
 
首先随便打开一个视频:
我就找一个python学习的视频(什么鬼,上面还有python学习? 是的有的,还有很多数学题目在上面讲解的呢)

chrome_cID7nwLJtU.png

 
然后按F12
找到一个疑似的下载地址

chrome_d6YqqHw23u.png


试下拷贝直接去打开,发现无法打开,显示403 fobiden。
但是看url,应该就是最终的下载url的格式,通过最后的随机数控制播放权限。
 
然后打开页面的源码
 
chrome_TkTA0Gu2mZ.png



chrome_xQ9PuglQfb.png



 
在里面找下有没有一些mp4等的字符, 然后发现有个720p,1080p不同分辨率格式的字段,我们把这个JavaScript的代码扣下来,然后保存为p_hub.js
 
用vs code 或者其他编辑器打开

sublime_text_fYK2l4s4NA.png

看到了他们生成过程了吗? 
 
然后尝试用nodejs运行一下。
什么都没有输出。
 
因为上面代码并没有任何输出语句,我们在最后加一个 console.log(quality_720p); 就会有输出的了。

cmd_HJhTndtvh8.png

看到了吗?
然后拿这个地址去试试,看能否播放和下载。
果然,浏览器里面出现了一个, 额, python学习的页面,一个单独的视频页面,所以可以直接右键,弹出一个保存视频的菜单,然后可以直接下载了。
 
用代码requesets.get(url) 保存text.content 写入文件,就可以把视频保存到本地了。
 
源码:
#!/usr/bin/env python
# http://30daydo.com
import os
import re
import js2py
import requests
from lxml import etree
from clint.textui import progress
import fire
from loguru import logger

file='crawler'
logger.add(
"logs/%s.log" % file,
format="{time:MM-DD HH:mm:ss} {level} {message}",
)

headers = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36",
}
proxies = {}

# 如果代理不稳定,不推荐使用
# local proxy service
# proxies example:
# proxies = {
# "http": "socks5://127.0.0.1:1080",
# "https": "socks5://127.0.0.1:1080",
# }

def list_page(url):
logger.info("crawling : %s" % url)
resp = requests.get(url, headers=headers, proxies=proxies, verify=False)
html = etree.HTML(resp.text)

buff = '//*[@class="phimage"]/a/'
names = html.xpath(f"{buff}@href")
urls = html.xpath(f"{buff}img/@data-mediabook")
for i in range(len(urls)):
try:
url = urls
[i] name = re.findall("=ph(\w+)", names[i])[-1]
logger.info(f"{url} {name}")
download(url, name, "webm")
except Exception as err:
logger.error(err)


def detail_page(url):
s = requests.Session()
resp = s.get(url, headers=headers, proxies=proxies, verify=False)
html = etree.HTML(resp.content)

title = "".join(html.xpath("//h1//text()")).strip()
logger.info(title)

js_temp = html.xpath("//script/text()")
for j in js_temp:
if "flashvars" in j:
videoUrl = exeJs(j)

download(videoUrl, title, "mp4")
continue


def exeJs(js):
flashvars = re.findall("flashvars_\d+", js)[0]
js = "\n\t".join(js.split("\n\t")[:-5]).strip()

js = js.replace("// var nextVideoObject = flashvars_['nextVideo'];",'')
js+=flashvars
res = js2py.eval_js(js)

if res.quality_720p:
return res.quality_720p
elif res.quality_480p:
return res.quality_480p
elif res.quality_240p:
return res.quality_240p
else:
logger.error("parse url error")


def download(url, name, filetype):
logger.info(f"{url} {name} {filetype}")
filepath = "%s/%s.%s" % (filetype, name, filetype)
if os.path.exists(filepath):
logger.info("this file had been downloaded :: %s" % filepath)
return
else:
response = requests.get(url, headers=headers, proxies=proxies, stream=True)
with open(filepath, "wb") as file:
total_length = int(response.headers.get("content-length"))
for ch in progress.bar(
response.iter_content(chunk_size=2391975),
expected_size=(total_length / 1024) + 1,
):
if ch:
file.write(ch)

logger.info("download success :: %s" % filepath)


def run(_arg=None):
paths = ["webm", "mp4"]
for path in paths:
if not os.path.exists(path):
os.mkdir(path)
if _arg == "webm":
# https://www.pornhub.com/categories
urls = [
# "https://www.pornhub.com/video?o=tr",
# "https://www.pornhub.com/video?o=ht",
# "https://www.pornhub.com/video?o=mv",
"https://www.pornhub.com/video",
]
for url in urls:
list_page(url)
elif _arg == "mp4":
with open("download.txt", "r") as file:
keys = list(set(file.readlines()))
logger.info(keys)
keys += [d.strip(".webm") for d in os.listdir("webm/")]
for key in keys:
if not key.strip():
continue
url = "https://www.pornhub.com/view_v ... ot%3B % key.strip()
logger.info("url: {}", url)
detail_page(url)
else:
_str = """
tips:
python crawler.py webm
- 下载热门页面的缩略图,路径为webm文件夹下

python crawler.py mp4
- 该命令会下载webm文件下对应的mp4文件
- 也可以将目标地址写入download.txt中
"""
logger.info(_str)
return
logger.info("finish !")


if __name__ == "__main__":
fire.Fire(run)
[/i][/i]


[i]原创文章,
转载请注明出处:
http://30daydo.com/article/44115 

 
[/i]
[i]
3lDOnb5.jpg
[/i]

开机启动禁用mumu模拟器

闲聊李魔佛 发表了文章 • 0 个评论 • 3842 次浏览 • 2020-12-02 08:28 • 来自相关话题

装的网易mumu手机模拟器,不希望它开机自动启动。 
在系统的msconfig的启动里面没找到,
在services服务里面也没有找到,
在系统的drivers钩子里面也没有找到,
 
偶然在计划任务里面找到了, 只要在计划任务里面把mumu登录启动的脚本给禁用掉就可以的了 查看全部
装的网易mumu手机模拟器,不希望它开机自动启动。 
在系统的msconfig的启动里面没找到,
在services服务里面也没有找到,
在系统的drivers钩子里面也没有找到,
 
偶然在计划任务里面找到了, 只要在计划任务里面把mumu登录启动的脚本给禁用掉就可以的了

pycharm 条件断点

python李魔佛 发表了文章 • 0 个评论 • 2531 次浏览 • 2020-12-01 13:42 • 来自相关话题

如果在一个循环或者需要执行很多次的的递归里面,可以使用条件断点。
 
先在想要停下来的地方打一个断点,然后再点击一下断点,弹出的一个条件断点的窗口,在窗口输入一个条件即可。
 
比如:
def main():
for i in range(100):
print(i*i)


if __name__ == '__main__':
main()
在i*i的地方打一个断点,然后在条件断点那里输入 i=50, 那么在调试模式下只有在i=50的时候才会停下来。
  查看全部
如果在一个循环或者需要执行很多次的的递归里面,可以使用条件断点。
 
先在想要停下来的地方打一个断点,然后再点击一下断点,弹出的一个条件断点的窗口,在窗口输入一个条件即可。
 
比如:
def main():
for i in range(100):
print(i*i)


if __name__ == '__main__':
main()

在i*i的地方打一个断点,然后在条件断点那里输入 i=50, 那么在调试模式下只有在i=50的时候才会停下来。
 

python执行js语句,无函数返回值

python李魔佛 发表了文章 • 0 个评论 • 2414 次浏览 • 2020-11-30 16:11 • 来自相关话题

有时候在JS代码里面抠出部分语句,但是不是一个函数。
如下面的一段JSvar radra27radra27 = "D";
var ra72419ra91ra72419ra91 = "7.241.9" + ".";
var raurst500ra63raurst500ra63 = "urst=500";
var ravalidtora49ravalidtora49 = "validto=";
var raevphncdra57raevphncdra57 = "ev.ph" + "ncd";
var ra16067161ra17ra16067161ra17 = "16067161";
var radeos202ra16radeos202ra16 = "deos/20" + "2";
var ra1080p4ra73ra1080p4ra73 = "/1080P_4";
var ra209hashra72ra209hashra72 = "209&hash";
var ra2bmkdz7nra36ra2bmkdz7nra36 = "2BMKd" + "z7N";
var ra6708909ra29ra6708909ra29 = "6708909" + "&";
var ra00kip4ra41ra00kip4ra41 = "00k&i" + "p=4";
var ra006163ra73ra006163ra73 = "006/16/" + "3";
var raro7upu3ra66raro7upu3ra66 = "Ro7UPU%3";
var raroiu6qra26raroiu6qra26 = "=rOiU6q%";
var ra075351mra26ra075351mra26 = "075351." + "m";
var ramgdmctbvra11ramgdmctbvra11 = "MgdmCtbV";
var rap4validra25rap4validra25 = "p4?valid";
var ra09ratera79ra09ratera79 = "09&rate=";
var rancomvira35rancomvira35 = "n.com/vi";
var ra24075351ra94ra24075351ra94 = "24075" + "351";
var ra000k324ra70ra000k324ra70 = "000K_324";
var ra50000kbra49ra50000kbra49 = "50000k&" + "b";
var rahttpsra83rahttpsra83 = "https://";
var rafrom160ra56rafrom160ra56 = "from=16" + "0";
var quality_1080p =/* + radra27radra27 + */rahttpsra83rahttpsra83 + /* + rancomvira35rancomvira35 + */raevphncdra57raevphncdra57 + /* + radra27radra27 + */rancomvira35rancomvira35 + /* + ra006163ra73ra006163ra73 + */radeos202ra16radeos202ra16 + /* + ra09ratera79ra09ratera79 + */ra006163ra73ra006163ra73 + /* + ra1080p4ra73ra1080p4ra73 + */ra24075351ra94ra24075351ra94 + /* + raroiu6qra26raroiu6qra26 + */ra1080p4ra73ra1080p4ra73 + /* + ra000k324ra70ra000k324ra70 + */ra000k324ra70ra000k324ra70 + /* + rancomvira35rancomvira35 + */ra075351mra26ra075351mra26 + /* + ravalidtora49ravalidtora49 + */rap4validra25rap4validra25 + /* + ra209hashra72ra209hashra72 + */rafrom160ra56rafrom160ra56 + /* + ra1080p4ra73ra1080p4ra73 + */ra6708909ra29ra6708909ra29 + /* + ra209hashra72ra209hashra72 + */ravalidtora49ravalidtora49 + /* + ramgdmctbvra11ramgdmctbvra11 + */ra16067161ra17ra16067161ra17 + /* + ra24075351ra94ra24075351ra94 + */ra09ratera79ra09ratera79 + /* + ra50000kbra49ra50000kbra49 + */ra50000kbra49ra50000kbra49 + /* + ramgdmctbvra11ramgdmctbvra11 + */raurst500ra63raurst500ra63 + /* + ra209hashra72ra209hashra72 + */ra00kip4ra41ra00kip4ra41 + /* + raroiu6qra26raroiu6qra26 + */ra72419ra91ra72419ra91 + /* + ra09ratera79ra09ratera79 + */ra209hashra72ra209hashra72 + /* + raro7upu3ra66raro7upu3ra66 + */raroiu6qra26raroiu6qra26 + /* + ra075351mra26ra075351mra26 + */ra2bmkdz7nra36ra2bmkdz7nra36 + /* + ra50000kbra49ra50000kbra49 + */ramgdmctbvra11ramgdmctbvra11 + /* + radeos202ra16radeos202ra16 + */raro7upu3ra66raro7upu3ra66 + /* + ra075351mra26ra075351mra26 + */radra27radra27;
flashvars_324075351["quality_1080p"] = quality_1080p;
做了很多的运算,掩人耳目,虽然看多几下,用python写也简单,或者把它放入一个function里面也可以。
比如实时网络上下载获取一段js,然后再在头部和尾部组装为function。
function getValue(){
xxxxxx
xxxxxx
return flashvars_324075351
}
 
然后执行这一段JS,call返回函数 getValue() 就可以拿到返回值了。
 
不过今天我们用其他的方法直接获取flashvars_324075351
 
使用jsp库即可。
 
把上面的JS语句var radra27radra27 = "D";
var ra72419ra91ra72419ra91 = "7.241.9" + ".";
var raurst500ra63raurst500ra63 = "urst=500";
var ravalidtora49ravalidtora49 = "validto=";
var raevphncdra57raevphncdra57 = "ev.ph" + "ncd";
var ra16067161ra17ra16067161ra17 = "16067161";
var radeos202ra16radeos202ra16 = "deos/20" + "2";
var ra1080p4ra73ra1080p4ra73 = "/1080P_4";
var ra209hashra72ra209hashra72 = "209&hash";
var ra2bmkdz7nra36ra2bmkdz7nra36 = "2BMKd" + "z7N";
var ra6708909ra29ra6708909ra29 = "6708909" + "&";
var ra00kip4ra41ra00kip4ra41 = "00k&i" + "p=4";
var ra006163ra73ra006163ra73 = "006/16/" + "3";
var raro7upu3ra66raro7upu3ra66 = "Ro7UPU%3";
var raroiu6qra26raroiu6qra26 = "=rOiU6q%";
var ra075351mra26ra075351mra26 = "075351." + "m";
var ramgdmctbvra11ramgdmctbvra11 = "MgdmCtbV";
var rap4validra25rap4validra25 = "p4?valid";
var ra09ratera79ra09ratera79 = "09&rate=";
var rancomvira35rancomvira35 = "n.com/vi";
var ra24075351ra94ra24075351ra94 = "24075" + "351";
var ra000k324ra70ra000k324ra70 = "000K_324";
var ra50000kbra49ra50000kbra49 = "50000k&" + "b";
var rahttpsra83rahttpsra83 = "https://";
var rafrom160ra56rafrom160ra56 = "from=16" + "0";
var quality_1080p =/* + radra27radra27 + */rahttpsra83rahttpsra83 + /* + rancomvira35rancomvira35 + */raevphncdra57raevphncdra57 + /* + radra27radra27 + */rancomvira35rancomvira35 + /* + ra006163ra73ra006163ra73 + */radeos202ra16radeos202ra16 + /* + ra09ratera79ra09ratera79 + */ra006163ra73ra006163ra73 + /* + ra1080p4ra73ra1080p4ra73 + */ra24075351ra94ra24075351ra94 + /* + raroiu6qra26raroiu6qra26 + */ra1080p4ra73ra1080p4ra73 + /* + ra000k324ra70ra000k324ra70 + */ra000k324ra70ra000k324ra70 + /* + rancomvira35rancomvira35 + */ra075351mra26ra075351mra26 + /* + ravalidtora49ravalidtora49 + */rap4validra25rap4validra25 + /* + ra209hashra72ra209hashra72 + */rafrom160ra56rafrom160ra56 + /* + ra1080p4ra73ra1080p4ra73 + */ra6708909ra29ra6708909ra29 + /* + ra209hashra72ra209hashra72 + */ravalidtora49ravalidtora49 + /* + ramgdmctbvra11ramgdmctbvra11 + */ra16067161ra17ra16067161ra17 + /* + ra24075351ra94ra24075351ra94 + */ra09ratera79ra09ratera79 + /* + ra50000kbra49ra50000kbra49 + */ra50000kbra49ra50000kbra49 + /* + ramgdmctbvra11ramgdmctbvra11 + */raurst500ra63raurst500ra63 + /* + ra209hashra72ra209hashra72 + */ra00kip4ra41ra00kip4ra41 + /* + raroiu6qra26raroiu6qra26 + */ra72419ra91ra72419ra91 + /* + ra09ratera79ra09ratera79 + */ra209hashra72ra209hashra72 + /* + raro7upu3ra66raro7upu3ra66 + */raroiu6qra26raroiu6qra26 + /* + ra075351mra26ra075351mra26 + */ra2bmkdz7nra36ra2bmkdz7nra36 + /* + ra50000kbra49ra50000kbra49 + */ramgdmctbvra11ramgdmctbvra11 + /* + radeos202ra16radeos202ra16 + */raro7upu3ra66raro7upu3ra66 + /* + ra075351mra26ra075351mra26 + */radra27radra27;
flashvars_324075351["quality_1080p"] = quality_1080p;
后面加一个返回值,但不需要加return
比如....
ra50000kbra49ra50000kbra49 + */ramgdmctbvra11ramgdmctbvra11 + /* + radeos202ra16radeos202ra16 + */raro7upu3ra66raro7upu3ra66 + /* + ra075351mra26ra075351mra26 + */radra27radra27;
flashvars_324075351["quality_1080p"] = quality_1080p;
flashvars_324075351;
然后直接调用jspy
res = js2py.eval_js(js)
 
执行后print(res) , 显示的值就是flashvars_324075351
原创文章,转载请注明出处
http://30daydo.com/article/44112
  查看全部
有时候在JS代码里面抠出部分语句,但是不是一个函数。
如下面的一段JS
var radra27radra27 = "D";
var ra72419ra91ra72419ra91 = "7.241.9" + ".";
var raurst500ra63raurst500ra63 = "urst=500";
var ravalidtora49ravalidtora49 = "validto=";
var raevphncdra57raevphncdra57 = "ev.ph" + "ncd";
var ra16067161ra17ra16067161ra17 = "16067161";
var radeos202ra16radeos202ra16 = "deos/20" + "2";
var ra1080p4ra73ra1080p4ra73 = "/1080P_4";
var ra209hashra72ra209hashra72 = "209&hash";
var ra2bmkdz7nra36ra2bmkdz7nra36 = "2BMKd" + "z7N";
var ra6708909ra29ra6708909ra29 = "6708909" + "&";
var ra00kip4ra41ra00kip4ra41 = "00k&i" + "p=4";
var ra006163ra73ra006163ra73 = "006/16/" + "3";
var raro7upu3ra66raro7upu3ra66 = "Ro7UPU%3";
var raroiu6qra26raroiu6qra26 = "=rOiU6q%";
var ra075351mra26ra075351mra26 = "075351." + "m";
var ramgdmctbvra11ramgdmctbvra11 = "MgdmCtbV";
var rap4validra25rap4validra25 = "p4?valid";
var ra09ratera79ra09ratera79 = "09&rate=";
var rancomvira35rancomvira35 = "n.com/vi";
var ra24075351ra94ra24075351ra94 = "24075" + "351";
var ra000k324ra70ra000k324ra70 = "000K_324";
var ra50000kbra49ra50000kbra49 = "50000k&" + "b";
var rahttpsra83rahttpsra83 = "https://";
var rafrom160ra56rafrom160ra56 = "from=16" + "0";
var quality_1080p =/* + radra27radra27 + */rahttpsra83rahttpsra83 + /* + rancomvira35rancomvira35 + */raevphncdra57raevphncdra57 + /* + radra27radra27 + */rancomvira35rancomvira35 + /* + ra006163ra73ra006163ra73 + */radeos202ra16radeos202ra16 + /* + ra09ratera79ra09ratera79 + */ra006163ra73ra006163ra73 + /* + ra1080p4ra73ra1080p4ra73 + */ra24075351ra94ra24075351ra94 + /* + raroiu6qra26raroiu6qra26 + */ra1080p4ra73ra1080p4ra73 + /* + ra000k324ra70ra000k324ra70 + */ra000k324ra70ra000k324ra70 + /* + rancomvira35rancomvira35 + */ra075351mra26ra075351mra26 + /* + ravalidtora49ravalidtora49 + */rap4validra25rap4validra25 + /* + ra209hashra72ra209hashra72 + */rafrom160ra56rafrom160ra56 + /* + ra1080p4ra73ra1080p4ra73 + */ra6708909ra29ra6708909ra29 + /* + ra209hashra72ra209hashra72 + */ravalidtora49ravalidtora49 + /* + ramgdmctbvra11ramgdmctbvra11 + */ra16067161ra17ra16067161ra17 + /* + ra24075351ra94ra24075351ra94 + */ra09ratera79ra09ratera79 + /* + ra50000kbra49ra50000kbra49 + */ra50000kbra49ra50000kbra49 + /* + ramgdmctbvra11ramgdmctbvra11 + */raurst500ra63raurst500ra63 + /* + ra209hashra72ra209hashra72 + */ra00kip4ra41ra00kip4ra41 + /* + raroiu6qra26raroiu6qra26 + */ra72419ra91ra72419ra91 + /* + ra09ratera79ra09ratera79 + */ra209hashra72ra209hashra72 + /* + raro7upu3ra66raro7upu3ra66 + */raroiu6qra26raroiu6qra26 + /* + ra075351mra26ra075351mra26 + */ra2bmkdz7nra36ra2bmkdz7nra36 + /* + ra50000kbra49ra50000kbra49 + */ramgdmctbvra11ramgdmctbvra11 + /* + radeos202ra16radeos202ra16 + */raro7upu3ra66raro7upu3ra66 + /* + ra075351mra26ra075351mra26 + */radra27radra27;
flashvars_324075351["quality_1080p"] = quality_1080p;

做了很多的运算,掩人耳目,虽然看多几下,用python写也简单,或者把它放入一个function里面也可以。
比如实时网络上下载获取一段js,然后再在头部和尾部组装为function。
function getValue(){
xxxxxx
xxxxxx
return flashvars_324075351
}
 
然后执行这一段JS,call返回函数 getValue() 就可以拿到返回值了。
 
不过今天我们用其他的方法直接获取flashvars_324075351
 
使用jsp库即可。
 
把上面的JS语句
var radra27radra27 = "D";
var ra72419ra91ra72419ra91 = "7.241.9" + ".";
var raurst500ra63raurst500ra63 = "urst=500";
var ravalidtora49ravalidtora49 = "validto=";
var raevphncdra57raevphncdra57 = "ev.ph" + "ncd";
var ra16067161ra17ra16067161ra17 = "16067161";
var radeos202ra16radeos202ra16 = "deos/20" + "2";
var ra1080p4ra73ra1080p4ra73 = "/1080P_4";
var ra209hashra72ra209hashra72 = "209&hash";
var ra2bmkdz7nra36ra2bmkdz7nra36 = "2BMKd" + "z7N";
var ra6708909ra29ra6708909ra29 = "6708909" + "&";
var ra00kip4ra41ra00kip4ra41 = "00k&i" + "p=4";
var ra006163ra73ra006163ra73 = "006/16/" + "3";
var raro7upu3ra66raro7upu3ra66 = "Ro7UPU%3";
var raroiu6qra26raroiu6qra26 = "=rOiU6q%";
var ra075351mra26ra075351mra26 = "075351." + "m";
var ramgdmctbvra11ramgdmctbvra11 = "MgdmCtbV";
var rap4validra25rap4validra25 = "p4?valid";
var ra09ratera79ra09ratera79 = "09&rate=";
var rancomvira35rancomvira35 = "n.com/vi";
var ra24075351ra94ra24075351ra94 = "24075" + "351";
var ra000k324ra70ra000k324ra70 = "000K_324";
var ra50000kbra49ra50000kbra49 = "50000k&" + "b";
var rahttpsra83rahttpsra83 = "https://";
var rafrom160ra56rafrom160ra56 = "from=16" + "0";
var quality_1080p =/* + radra27radra27 + */rahttpsra83rahttpsra83 + /* + rancomvira35rancomvira35 + */raevphncdra57raevphncdra57 + /* + radra27radra27 + */rancomvira35rancomvira35 + /* + ra006163ra73ra006163ra73 + */radeos202ra16radeos202ra16 + /* + ra09ratera79ra09ratera79 + */ra006163ra73ra006163ra73 + /* + ra1080p4ra73ra1080p4ra73 + */ra24075351ra94ra24075351ra94 + /* + raroiu6qra26raroiu6qra26 + */ra1080p4ra73ra1080p4ra73 + /* + ra000k324ra70ra000k324ra70 + */ra000k324ra70ra000k324ra70 + /* + rancomvira35rancomvira35 + */ra075351mra26ra075351mra26 + /* + ravalidtora49ravalidtora49 + */rap4validra25rap4validra25 + /* + ra209hashra72ra209hashra72 + */rafrom160ra56rafrom160ra56 + /* + ra1080p4ra73ra1080p4ra73 + */ra6708909ra29ra6708909ra29 + /* + ra209hashra72ra209hashra72 + */ravalidtora49ravalidtora49 + /* + ramgdmctbvra11ramgdmctbvra11 + */ra16067161ra17ra16067161ra17 + /* + ra24075351ra94ra24075351ra94 + */ra09ratera79ra09ratera79 + /* + ra50000kbra49ra50000kbra49 + */ra50000kbra49ra50000kbra49 + /* + ramgdmctbvra11ramgdmctbvra11 + */raurst500ra63raurst500ra63 + /* + ra209hashra72ra209hashra72 + */ra00kip4ra41ra00kip4ra41 + /* + raroiu6qra26raroiu6qra26 + */ra72419ra91ra72419ra91 + /* + ra09ratera79ra09ratera79 + */ra209hashra72ra209hashra72 + /* + raro7upu3ra66raro7upu3ra66 + */raroiu6qra26raroiu6qra26 + /* + ra075351mra26ra075351mra26 + */ra2bmkdz7nra36ra2bmkdz7nra36 + /* + ra50000kbra49ra50000kbra49 + */ramgdmctbvra11ramgdmctbvra11 + /* + radeos202ra16radeos202ra16 + */raro7upu3ra66raro7upu3ra66 + /* + ra075351mra26ra075351mra26 + */radra27radra27;
flashvars_324075351["quality_1080p"] = quality_1080p;

后面加一个返回值,但不需要加return
比如
....
ra50000kbra49ra50000kbra49 + */ramgdmctbvra11ramgdmctbvra11 + /* + radeos202ra16radeos202ra16 + */raro7upu3ra66raro7upu3ra66 + /* + ra075351mra26ra075351mra26 + */radra27radra27;
flashvars_324075351["quality_1080p"] = quality_1080p;
flashvars_324075351;

然后直接调用jspy
res = js2py.eval_js(js)
 
执行后print(res) , 显示的值就是flashvars_324075351
原创文章,转载请注明出处
http://30daydo.com/article/44112
 

知乎发文章后面加个链接也会被封,以后不玩了

闲聊李魔佛 发表了文章 • 0 个评论 • 2821 次浏览 • 2020-11-30 09:24 • 来自相关话题

 
感觉不厚道,那好吧,88啦




 
 
感觉不厚道,那好吧,88啦
chrome_pCVCc8LgxG.png

 

简单快速下载知乎视频

python爬虫李魔佛 发表了文章 • 0 个评论 • 4252 次浏览 • 2020-11-29 23:03 • 来自相关话题

现在的知乎也有视频内容,目前看来没有任何反爬措施。可以简单通过以下方式用浏览器下载:
 
1. 打开视频前按F12
2. 播放视频
3. 查看F12的网络选项
4. 找到 https://vdn3.vzuu.com 的url
5. 对应的整个url链接就是视频的真实下载地址。把url复制到浏览器打开,然后右键另存为本地视频就可以了 
  查看全部
现在的知乎也有视频内容,目前看来没有任何反爬措施。可以简单通过以下方式用浏览器下载:
 
1. 打开视频前按F12
2. 播放视频
3. 查看F12的网络选项
4. 找到 https://vdn3.vzuu.com 的url
5. 对应的整个url链接就是视频的真实下载地址。把url复制到浏览器打开,然后右键另存为本地视频就可以了 
 

集思录用户名密码JS加密流程解密 【JS加密破解教程一】

python爬虫李魔佛 发表了文章 • 0 个评论 • 3906 次浏览 • 2020-11-27 17:26 • 来自相关话题

之前帮他人部署的一个集思录爬取的程序,忽然获取的数据不一样了。 查看日志后发现,现在的登录用户名和密码做了一层加密后再post提交。
 
而且提交的内容每次都固定,第一种最傻的方式就是每次提交就把加密的用户名和密码提交上去。







 
当然,对于有钻研的读者,可能想看看其具体的加密方式。
那么就按照流程,通过断点与搜索,找到其加密方法。
首先在上面的截图中很明显就知道,这个字符加密应该是aes,因为它的提交字段中aes:1
 
按F12,走完整个登录流程。
然后搜索password字样的地方。
 
在index.html首页中找到一处:





 
然后在该password的地方打个断点,然后跳转到jslencode 的地方。





跳转到的地方是这里。
 
然后我们浏览一下这个JS页面,尝试把整个JS代码抠出来。
放到我们的调试软件中,比较常用的是鬼鬼JS调试器。(有需要的可以关注wx公众号下载:回复 鬼鬼JS 即可)





这个调试器的好处是,可以很方便格式化JS代码,然后输入你要调试的字符,然后点击运行,可以当场拿到结果,等到结果ok了的话,就可以用python 的pyexecjs执行。
 
先点击代码格式化,然后在输入框里找到函数的入口:
jslencode(text, aes_key),好了,现在就把我们的密码 XXXXXX,和aes_key 放进去就可以了。
aes_key 在之前的index.html就能找到。var A397151C04723421F = '397151C04723421F';
function doLogin(){
var data = $('#login_form').serializeObjectToJson();
data['_post_type'] = 'ajax';
data['aes'] = 1;
data['user_name'] = jslencode(data['user_name'], A397151C04723421F);
data['password'] = jslencode(data['password'], A397151C04723421F);
$.post('/account/ajax/login_process/', data, function(rst){
on_login_error_processer(rst);
}, 'json');
var A397151C04723421F = '397151C04723421F';
 
jslencode(‘jisilupassword’, '397151C04723421F')
右下角有个系统引擎运行。
 
得到结果:
1d1bd2b22b8cc5c09ad8ce8f1e69b87f
 
对比一下第一张图里面的的post请求,发现是一样的。那么现在的JS解密就成功了一大半了。 接着我们就写python代码执行这段JS脚本。
 
 
尝试直接把JS放到一个文件,然后编写python代码# -*- coding: utf-8 -*-
# @Time : 2020/11/27 12:15
# @File : js_executor.py
# @Author : Rocky C@www.30daydo.com
import execjs

def main():
encode_user = ctx.call('jslencode', user, key)
encode_password = ctx.call('jslencode', password, key)
print(encode_user)
print(encode_password)


if __name__ == '__main__':
main()
然后发现报错: 说CryptoJS没有定义,那么我们看看代码。(function(root, factory) {
if (typeof exports === "object") {
module.exports = exports = factory()
} else {
if (typeof define === "function" && define.amd) {
define(, factory)
} else {
root.CryptoJS = factory()
}
}
}(this, function() {
var CryptoJS = CryptoJS || (function(Math, undefined) {
var create = Object.create || (function() {
发现这一行此时CryptoJS的定义

var CryptoJS = CryptoJS || (function(Math, undefined) { var create = Object.create || (function() {
 
那么我们把这一行上面的全部删除。最后的调试后,能够执行的JS代码如下,并保存为 集思录.js 文件,调用上面的python文件。
 
集思录.jsvar CryptoJS = CryptoJS || (function(Math, undefined) {
var create = Object.create || (function() {
function F() {}
return function(obj) {
var subtype;
F.prototype = obj;
subtype = new F();
F.prototype = null;
return subtype
}
}());
var C = {};
var C_lib = C.lib = {};
var Base = C_lib.Base = (function() {





下面的就跟上面的一模一样了:
源文件地址:https://www.jisilu.cn/static/js/crypto-js-3.3.0-min.js然后python运行后得到加密后的aes数据。
 
对比一下鬼鬼JS调试器的结果,一样的。
OK,手工。
这里汇聚了平时整理的JS破解工作流,大家可以参考参考。 
 https://github.com/Rockyzsu/JS-Reverse 

原创文章,转载请注明出处:
http://30daydo.com/article/44109
喜欢的朋友可以加入星球探讨: 查看全部
之前帮他人部署的一个集思录爬取的程序,忽然获取的数据不一样了。 查看日志后发现,现在的登录用户名和密码做了一层加密后再post提交。
 
而且提交的内容每次都固定,第一种最傻的方式就是每次提交就把加密的用户名和密码提交上去。


5960fc43cefbc020698b2d4b928274f8.png


 
当然,对于有钻研的读者,可能想看看其具体的加密方式。
那么就按照流程,通过断点与搜索,找到其加密方法。
首先在上面的截图中很明显就知道,这个字符加密应该是aes,因为它的提交字段中aes:1
 
按F12,走完整个登录流程。
然后搜索password字样的地方。
 
在index.html首页中找到一处:

chrome_3IrUrGEXxY.png

 
然后在该password的地方打个断点,然后跳转到jslencode 的地方。

YEtNA7EKa0.png

跳转到的地方是这里。
 
然后我们浏览一下这个JS页面,尝试把整个JS代码抠出来。
放到我们的调试软件中,比较常用的是鬼鬼JS调试器。(有需要的可以关注wx公众号下载:回复 鬼鬼JS 即可)

鬼鬼JS调试工具7.5_J47FALG4mD_.png

这个调试器的好处是,可以很方便格式化JS代码,然后输入你要调试的字符,然后点击运行,可以当场拿到结果,等到结果ok了的话,就可以用python 的pyexecjs执行。
 
先点击代码格式化,然后在输入框里找到函数的入口:
jslencode(text, aes_key),好了,现在就把我们的密码 XXXXXX,和aes_key 放进去就可以了。
aes_key 在之前的index.html就能找到。
var A397151C04723421F = '397151C04723421F';
function doLogin(){
var data = $('#login_form').serializeObjectToJson();
data['_post_type'] = 'ajax';
data['aes'] = 1;
data['user_name'] = jslencode(data['user_name'], A397151C04723421F);
data['password'] = jslencode(data['password'], A397151C04723421F);
$.post('/account/ajax/login_process/', data, function(rst){
on_login_error_processer(rst);
}, 'json');

var A397151C04723421F = '397151C04723421F';
 
jslencode(‘jisilupassword’, '397151C04723421F')
右下角有个系统引擎运行。
 
得到结果:
1d1bd2b22b8cc5c09ad8ce8f1e69b87f
 
对比一下第一张图里面的的post请求,发现是一样的。那么现在的JS解密就成功了一大半了。 接着我们就写python代码执行这段JS脚本。
 
 
尝试直接把JS放到一个文件,然后编写python代码
# -*- coding: utf-8 -*-
# @Time : 2020/11/27 12:15
# @File : js_executor.py
# @Author : Rocky C@www.30daydo.com
import execjs

def main():
encode_user = ctx.call('jslencode', user, key)
encode_password = ctx.call('jslencode', password, key)
print(encode_user)
print(encode_password)


if __name__ == '__main__':
main()

然后发现报错: 说CryptoJS没有定义,那么我们看看代码。
(function(root, factory) {
if (typeof exports === "object") {
module.exports = exports = factory()
} else {
if (typeof define === "function" && define.amd) {
define(, factory)
} else {
root.CryptoJS = factory()
}
}
}(this, function() {
var CryptoJS = CryptoJS || (function(Math, undefined) {
var create = Object.create || (function() {

发现这一行此时CryptoJS的定义

var CryptoJS = CryptoJS || (function(Math, undefined) { var create = Object.create || (function() {
 
那么我们把这一行上面的全部删除。最后的调试后,能够执行的JS代码如下,并保存为 集思录.js 文件,调用上面的python文件。
 
集思录.js
var CryptoJS = CryptoJS || (function(Math, undefined) {
var create = Object.create || (function() {
function F() {}
return function(obj) {
var subtype;
F.prototype = obj;
subtype = new F();
F.prototype = null;
return subtype
}
}());
var C = {};
var C_lib = C.lib = {};
var Base = C_lib.Base = (function() {





下面的就跟上面的一模一样了:
源文件地址:
https://www.jisilu.cn/static/js/crypto-js-3.3.0-min.js
然后python运行后得到加密后的aes数据。
 
对比一下鬼鬼JS调试器的结果,一样的。
OK,手工。
这里汇聚了平时整理的JS破解工作流,大家可以参考参考。 
 https://github.com/Rockyzsu/JS-Reverse 

原创文章,转载请注明出处:
http://30daydo.com/article/44109
喜欢的朋友可以加入星球探讨:

效率流工具 推荐

网络李魔佛 发表了文章 • 0 个评论 • 2003 次浏览 • 2020-11-26 23:05 • 来自相关话题

首先一点,在很多场合下,使用键盘的效率要远远高于鼠标。 所以最快的工作流是使用键盘去控制。
 
如果没有体会,说明你没有用过vim。 操控+控制使用键盘操作,浑然天成。 虽然有位大佬推荐我用emacs,可是学习成本过于高昂,一直学不会。
 
那么在windows平台下推荐几款 工作流 软件。
 
1.  vimium
啥,又是vim ? 不, 这是一款在浏览器上模拟vim操作的软件。 比如滚动到底部,GG, 滚动到顶部 gg,
上下左右移动hjkl,如果不是经常用vim的朋友可能会觉得特别别扭。
大写的JK 前后滚动tab
b 打开书签,打开常用的网站
 
2. listary + everything
打开程序+搜索文件
可以按2下ctrl,然后输入程序的快捷方式名称,就马上可以启动程序
 
3. 
 
  查看全部
首先一点,在很多场合下,使用键盘的效率要远远高于鼠标。 所以最快的工作流是使用键盘去控制。
 
如果没有体会,说明你没有用过vim。 操控+控制使用键盘操作,浑然天成。 虽然有位大佬推荐我用emacs,可是学习成本过于高昂,一直学不会。
 
那么在windows平台下推荐几款 工作流 软件。
 
1.  vimium
啥,又是vim ? 不, 这是一款在浏览器上模拟vim操作的软件。 比如滚动到底部,GG, 滚动到顶部 gg,
上下左右移动hjkl,如果不是经常用vim的朋友可能会觉得特别别扭。
大写的JK 前后滚动tab
b 打开书签,打开常用的网站
 
2. listary + everything
打开程序+搜索文件
可以按2下ctrl,然后输入程序的快捷方式名称,就马上可以启动程序
 
3.