python

python

scrapy在settings中定义变量不能包含小写!

python爬虫李魔佛 发表了文章 • 0 个评论 • 33 次浏览 • 2019-11-16 16:39 • 来自相关话题

如果变量名包含小写字母,那么你的变量会被过滤掉,在scrapy编码的其他地方都会无法被识别。
比如定义了一个叫 Redis_host = '192.168.1.1',的值
 
然后在spider中,如果你调用self.settings.get('Redis_host')
那么返回值是 None。
 
如果用REDIS_HOST定义,那么就可以正确返回它的值。
 
如果你一定要用小写,也有其他方法可正常调用。
先导入settings文件
fromt xxxx import setttings # xxx为项目名
 
host = settings.Redis_host # 直接导入一个文件的形式来调用是可以的 查看全部
如果变量名包含小写字母,那么你的变量会被过滤掉,在scrapy编码的其他地方都会无法被识别。
比如定义了一个叫 Redis_host = '192.168.1.1',的值
 
然后在spider中,如果你调用self.settings.get('Redis_host')
那么返回值是 None。
 
如果用REDIS_HOST定义,那么就可以正确返回它的值。
 
如果你一定要用小写,也有其他方法可正常调用。
先导入settings文件
fromt xxxx import setttings # xxx为项目名
 
host = settings.Redis_host # 直接导入一个文件的形式来调用是可以的

etree.strip_tags的用法

python爬虫李魔佛 发表了文章 • 0 个评论 • 99 次浏览 • 2019-10-24 11:24 • 来自相关话题

直接从官方文档那里拿过来,发现这个函数功能还挺不错的。
它把参数中的标签从源htmlelement中删除,并且把里面的标签文本给合并进来。
 
举个例子:from lxml.html import etree
from lxml.html import fromstring, HtmlElement

test_html = '''<p><span>hello</span><span>world</span></p>'''
test_element = fromstring(test_html)
etree.strip_tags(test_element,'span') # 清除span标签
etree.tostring(test_element)
因为上述操作直接应用于test_element上的,所以test_element的值已经被修改了。
 
所以现在test_element 的值是 
b'<p>helloworld</p>'

原创文章,转载请注明出处
http://30daydo.com/article/553
  查看全部
直接从官方文档那里拿过来,发现这个函数功能还挺不错的。
它把参数中的标签从源htmlelement中删除,并且把里面的标签文本给合并进来。
 
举个例子:
from lxml.html import etree
from lxml.html import fromstring, HtmlElement

test_html = '''<p><span>hello</span><span>world</span></p>'''
test_element = fromstring(test_html)
etree.strip_tags(test_element,'span') # 清除span标签
etree.tostring(test_element)

因为上述操作直接应用于test_element上的,所以test_element的值已经被修改了。
 
所以现在test_element 的值是 
b'<p>helloworld</p>'

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

aiohttp异步下载图片

python爬虫李魔佛 发表了文章 • 0 个评论 • 196 次浏览 • 2019-09-16 17:14 • 来自相关话题

保存图片的时候不能用自带的open函数打开文件,需要用到异步io库 aiofiles来打开url = 'http://xyhz.huizhou.gov.cn/static/js/common/jigsaw/images/{}.jpg'
headers={'User-Agent':'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'}
async def getPage(num):

async with aiohttp.ClientSession() as session:
async with session.get(url.format(num),headers=headers) as resp:
if resp.status==200:
f= await aiofiles.open('{}.jpg'.format(num),mode='wb')
await f.write(await resp.read())
await f.close()

loop = asyncio.get_event_loop()
tasks = [getPage(i) for i in range(5)]
loop.run_until_complete(asyncio.wait(tasks))
原创文章,
转载请注明出处:
http://30daydo.com/article/537
  查看全部
保存图片的时候不能用自带的open函数打开文件,需要用到异步io库 aiofiles来打开
url = 'http://xyhz.huizhou.gov.cn/static/js/common/jigsaw/images/{}.jpg'
headers={'User-Agent':'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)'}
async def getPage(num):

async with aiohttp.ClientSession() as session:
async with session.get(url.format(num),headers=headers) as resp:
if resp.status==200:
f= await aiofiles.open('{}.jpg'.format(num),mode='wb')
await f.write(await resp.read())
await f.close()

loop = asyncio.get_event_loop()
tasks = [getPage(i) for i in range(5)]
loop.run_until_complete(asyncio.wait(tasks))

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

基于文本及符号密度的网页正文提取方法 python实现

python李魔佛 发表了文章 • 0 个评论 • 521 次浏览 • 2019-09-10 15:19 • 来自相关话题

基于文本及符号密度的网页正文提取方法 python实现
 项目路径https://github.com/Rockyzsu/CodePool/tree/master/GeneralNewsExtractor
完成后在本文详细介绍,
请密切关注。 查看全部
基于文本及符号密度的网页正文提取方法 python实现
 项目路径https://github.com/Rockyzsu/CodePool/tree/master/GeneralNewsExtractor
完成后在本文详细介绍,
请密切关注。

根据东财股吧爬虫数据进行自然语言分析,展示股市热度

股票李魔佛 发表了文章 • 0 个评论 • 380 次浏览 • 2019-09-10 09:27 • 来自相关话题

根据东财股吧爬虫数据进行自然语言分析,展示股市热度
 项目开展中.....
https://github.com/Rockyzsu/StockPredict
 
完工后会把代码搬上来并加注释。
 
### 2019-11-17 更新 ###### 
 
股市舆情情感分类可视化系统
 
此Web基于Django+Bootstrap+Echarts等框架,个股交易行情数据调用了Tushare接口。对于舆情文本数据采取先爬取东方财富网股吧论坛标题词语设置机器学习训练集,在此基础上运用scikit-learn机器学习朴素贝叶斯方法构建文本分类器。通过Django Web框架,将所得数据传递到前端经过Bootstrap渲染过的html,对数据使用Echarts进行图表可视化处理
 
不足之处或交流学习欢迎通过邮箱联系我


目前的功能:

个股历史交易行情
个股相关词云展示
情感字典舆情预测
朴素贝叶斯舆情预测
 

 
Quick Start

在项目当前目录下: $ python manage.py runserver
浏览器打开127.0.0.1:8000
 
  查看全部
根据东财股吧爬虫数据进行自然语言分析,展示股市热度
 项目开展中.....
https://github.com/Rockyzsu/StockPredict
 
完工后会把代码搬上来并加注释。
 
### 2019-11-17 更新 ###### 
 
股市舆情情感分类可视化系统
 
此Web基于Django+Bootstrap+Echarts等框架,个股交易行情数据调用了Tushare接口。对于舆情文本数据采取先爬取东方财富网股吧论坛标题词语设置机器学习训练集,在此基础上运用scikit-learn机器学习朴素贝叶斯方法构建文本分类器。通过Django Web框架,将所得数据传递到前端经过Bootstrap渲染过的html,对数据使用Echarts进行图表可视化处理
 
不足之处或交流学习欢迎通过邮箱联系我


目前的功能:

个股历史交易行情
个股相关词云展示
情感字典舆情预测
朴素贝叶斯舆情预测
 

 
Quick Start

在项目当前目录下: $ python manage.py runserver
浏览器打开127.0.0.1:8000
 
 

python exchange保存备份邮件

python李魔佛 发表了文章 • 0 个评论 • 379 次浏览 • 2019-09-09 10:50 • 来自相关话题

python exchange保存备份邮件
 方便自己平时备份邮件。# -*-coding=utf-8-*-

# @Time : 2019/9/9 9:25
# @File : mail_backup.py
# @Author :
import codecs
import re
import config
import os
from exchangelib import DELEGATE, Account, Credentials, Configuration, NTLM, Message, Mailbox, HTMLBody,FileAttachment,ItemAttachment
from exchangelib.protocol import BaseProtocol, NoVerifyHTTPAdapter


#此句用来消除ssl证书错误,exchange使用自签证书需加上
BaseProtocol.HTTP_ADAPTER_CLS = NoVerifyHTTPAdapter


# 输入你的域账号如example\xxx
cred = Credentials(r'example\xxx', 你的邮箱密码)

configx = Configuration(server='mail.credlink.com', credentials=cred, auth_type=NTLM)
a = Account(
primary_smtp_address='你的邮箱地址', config=configx, autodiscover=False, access_type=DELEGATE
)


for item in a.inbox.all().order_by('-datetime_received')[:100]:
print(item.subject, item.sender, item.unique_body,item.datetime_received)

name = item.subject
name = re.sub('[\/:*?"<>|]', '-', name)
local_path = os.path.join('inbox', name+'.html')
with codecs.open(local_path, 'w','utf-8') as f:
f.write(item.unique_body)

for attachment in item.attachments:
if isinstance(attachment, FileAttachment):
name = attachment.name
name = re.sub('[\/:*?"<>|]','-',name)
local_path = os.path.join('inbox', attachment.name)
with codecs.open(local_path, 'wb') as f:
f.write(attachment.content)
print('Saved attachment to', local_path)

elif isinstance(attachment, ItemAttachment):
if isinstance(attachment.item, Message):
name=attachment.item.subject
name = re.sub('[\/:*?"<>|]', '-', name)
local_path = os.path.join('inbox', 'attachment')
with codecs.open(local_path, 'w') as f:
f.write(attachment.item.body)
原创文章,
转载请注明出处
http://30daydo.com/article/534
  查看全部
python exchange保存备份邮件
 方便自己平时备份邮件。
# -*-coding=utf-8-*-

# @Time : 2019/9/9 9:25
# @File : mail_backup.py
# @Author :
import codecs
import re
import config
import os
from exchangelib import DELEGATE, Account, Credentials, Configuration, NTLM, Message, Mailbox, HTMLBody,FileAttachment,ItemAttachment
from exchangelib.protocol import BaseProtocol, NoVerifyHTTPAdapter


#此句用来消除ssl证书错误,exchange使用自签证书需加上
BaseProtocol.HTTP_ADAPTER_CLS = NoVerifyHTTPAdapter


# 输入你的域账号如example\xxx
cred = Credentials(r'example\xxx', 你的邮箱密码)

configx = Configuration(server='mail.credlink.com', credentials=cred, auth_type=NTLM)
a = Account(
primary_smtp_address='你的邮箱地址', config=configx, autodiscover=False, access_type=DELEGATE
)


for item in a.inbox.all().order_by('-datetime_received')[:100]:
print(item.subject, item.sender, item.unique_body,item.datetime_received)

name = item.subject
name = re.sub('[\/:*?"<>|]', '-', name)
local_path = os.path.join('inbox', name+'.html')
with codecs.open(local_path, 'w','utf-8') as f:
f.write(item.unique_body)

for attachment in item.attachments:
if isinstance(attachment, FileAttachment):
name = attachment.name
name = re.sub('[\/:*?"<>|]','-',name)
local_path = os.path.join('inbox', attachment.name)
with codecs.open(local_path, 'wb') as f:
f.write(attachment.content)
print('Saved attachment to', local_path)

elif isinstance(attachment, ItemAttachment):
if isinstance(attachment.item, Message):
name=attachment.item.subject
name = re.sub('[\/:*?"<>|]', '-', name)
local_path = os.path.join('inbox', 'attachment')
with codecs.open(local_path, 'w') as f:
f.write(attachment.item.body)

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

scrapy源码分析<一>:入口函数以及是如何运行

python爬虫李魔佛 发表了文章 • 0 个评论 • 288 次浏览 • 2019-08-31 10:47 • 来自相关话题

运行scrapy crawl example 命令的时候,就会执行我们写的爬虫程序。
下面我们从源码分析一下scrapy执行的流程:
 

执行scrapy crawl 命令时,调用的是Command类class Command(ScrapyCommand):

requires_project = True

def syntax(self):
return '[options]'

def short_desc(self):
return 'Runs all of the spiders - My Defined'

def run(self,args,opts):
print('==================')
print(type(self.crawler_process))
spider_list = self.crawler_process.spiders.list() # 找到爬虫类

for name in spider_list:
print('=================')
print(name)
self.crawler_process.crawl(name,**opts.__dict__)

self.crawler_process.start()
然后我们去看看crawler_process,这个是来自ScrapyCommand,而ScrapyCommand又是CrawlerProcess的子类,而CrawlerProcess又是CrawlerRunner的子类

在CrawlerRunner构造函数里面主要作用就是这个 def __init__(self, settings=None):
if isinstance(settings, dict) or settings is None:
settings = Settings(settings)
self.settings = settings
self.spider_loader = _get_spider_loader(settings) # 构造爬虫
self._crawlers = set()
self._active = set()
self.bootstrap_failed = False
1. 加载配置文件def _get_spider_loader(settings):

cls_path = settings.get('SPIDER_LOADER_CLASS')

# settings文件没有定义SPIDER_LOADER_CLASS,所以这里获取到的是系统的默认配置文件,
# 默认配置文件在接下来的代码块A
# SPIDER_LOADER_CLASS = 'scrapy.spiderloader.SpiderLoader'

loader_cls = load_object(cls_path)
# 这个函数就是根据路径转为类对象,也就是上面crapy.spiderloader.SpiderLoader 这个
# 字符串变成一个类对象
# 具体的load_object 对象代码见下面代码块B

return loader_cls.from_settings(settings.frozencopy())
默认配置文件defautl_settting.py# 代码块A
#......省略若干
SCHEDULER = 'scrapy.core.scheduler.Scheduler'
SCHEDULER_DISK_QUEUE = 'scrapy.squeues.PickleLifoDiskQueue'
SCHEDULER_MEMORY_QUEUE = 'scrapy.squeues.LifoMemoryQueue'
SCHEDULER_PRIORITY_QUEUE = 'scrapy.pqueues.ScrapyPriorityQueue'

SPIDER_LOADER_CLASS = 'scrapy.spiderloader.SpiderLoader' 就是这个值
SPIDER_LOADER_WARN_ONLY = False

SPIDER_MIDDLEWARES = {}

load_object的实现# 代码块B 为了方便,我把异常处理的去除
from importlib import import_module #导入第三方库

def load_object(path):
dot = path.rindex('.')
module, name = path[:dot], path[dot+1:]
# 上面把路径分为基本路径+模块名

mod = import_module(module)
obj = getattr(mod, name)
# 获取模块里面那个值

return obj

测试代码:In [33]: mod = import_module(module)

In [34]: mod
Out[34]: <module 'scrapy.spiderloader' from '/home/xda/anaconda3/lib/python3.7/site-packages/scrapy/spiderloader.py'>

In [35]: getattr(mod,name)
Out[35]: scrapy.spiderloader.SpiderLoader

In [36]: obj = getattr(mod,name)

In [37]: obj
Out[37]: scrapy.spiderloader.SpiderLoader

In [38]: type(obj)
Out[38]: type
在代码块A中,loader_cls是SpiderLoader,最后返回的的是SpiderLoader.from_settings(settings.frozencopy())
接下来看看SpiderLoader.from_settings, def from_settings(cls, settings):
return cls(settings)
返回类对象自己,所以直接看__init__函数即可class SpiderLoader(object):
"""
SpiderLoader is a class which locates and loads spiders
in a Scrapy project.
"""
def __init__(self, settings):
self.spider_modules = settings.getlist('SPIDER_MODULES')
# 获得settting中的模块名字,创建scrapy的时候就默认帮你生成了
# 你可以看看你的settings文件里面的内容就可以找到这个值,是一个list

self.warn_only = settings.getbool('SPIDER_LOADER_WARN_ONLY')
self._spiders = {}
self._found = defaultdict(list)
self._load_all_spiders() # 加载所有爬虫

核心就是这个_load_all_spiders:
走起:def _load_all_spiders(self):
for name in self.spider_modules:

for module in walk_modules(name): # 这个遍历文件夹里面的文件,然后再转化为类对象,
# 保存到字典:self._spiders = {}
self._load_spiders(module) # 模块变成spider

self._check_name_duplicates() # 去重,如果名字一样就异常

接下来看看_load_spiders
核心就是下面的。def iter_spider_classes(module):
from scrapy.spiders import Spider

for obj in six.itervalues(vars(module)): # 找到模块里面的变量,然后迭代出来
if inspect.isclass(obj) and \
issubclass(obj, Spider) and \
obj.__module__ == module.__name__ and \
getattr(obj, 'name', None): # 有name属性,继承于Spider
yield obj
这个obj就是我们平时写的spider类了。
原来分析了这么多,才找到了我们平时写的爬虫类

待续。。。。
 
原创文章
转载请注明出处
http://30daydo.com/article/530
  查看全部
运行scrapy crawl example 命令的时候,就会执行我们写的爬虫程序。
下面我们从源码分析一下scrapy执行的流程:
 

执行scrapy crawl 命令时,调用的是Command类
class Command(ScrapyCommand):

requires_project = True

def syntax(self):
return '[options]'

def short_desc(self):
return 'Runs all of the spiders - My Defined'

def run(self,args,opts):
print('==================')
print(type(self.crawler_process))
spider_list = self.crawler_process.spiders.list() # 找到爬虫类

for name in spider_list:
print('=================')
print(name)
self.crawler_process.crawl(name,**opts.__dict__)

self.crawler_process.start()

然后我们去看看crawler_process,这个是来自ScrapyCommand,而ScrapyCommand又是CrawlerProcess的子类,而CrawlerProcess又是CrawlerRunner的子类

在CrawlerRunner构造函数里面主要作用就是这个
      def __init__(self, settings=None):
if isinstance(settings, dict) or settings is None:
settings = Settings(settings)
self.settings = settings
self.spider_loader = _get_spider_loader(settings) # 构造爬虫
self._crawlers = set()
self._active = set()
self.bootstrap_failed = False

1. 加载配置文件
def _get_spider_loader(settings):

cls_path = settings.get('SPIDER_LOADER_CLASS')

# settings文件没有定义SPIDER_LOADER_CLASS,所以这里获取到的是系统的默认配置文件,
# 默认配置文件在接下来的代码块A
# SPIDER_LOADER_CLASS = 'scrapy.spiderloader.SpiderLoader'

loader_cls = load_object(cls_path)
# 这个函数就是根据路径转为类对象,也就是上面crapy.spiderloader.SpiderLoader 这个
# 字符串变成一个类对象
# 具体的load_object 对象代码见下面代码块B

return loader_cls.from_settings(settings.frozencopy())

默认配置文件defautl_settting.py
# 代码块A
#......省略若干
SCHEDULER = 'scrapy.core.scheduler.Scheduler'
SCHEDULER_DISK_QUEUE = 'scrapy.squeues.PickleLifoDiskQueue'
SCHEDULER_MEMORY_QUEUE = 'scrapy.squeues.LifoMemoryQueue'
SCHEDULER_PRIORITY_QUEUE = 'scrapy.pqueues.ScrapyPriorityQueue'

SPIDER_LOADER_CLASS = 'scrapy.spiderloader.SpiderLoader' 就是这个值
SPIDER_LOADER_WARN_ONLY = False

SPIDER_MIDDLEWARES = {}


load_object的实现
# 代码块B 为了方便,我把异常处理的去除
from importlib import import_module #导入第三方库

def load_object(path):
dot = path.rindex('.')
module, name = path[:dot], path[dot+1:]
# 上面把路径分为基本路径+模块名

mod = import_module(module)
obj = getattr(mod, name)
# 获取模块里面那个值

return obj


测试代码:
In [33]: mod = import_module(module)                                                                                                                                             

In [34]: mod
Out[34]: <module 'scrapy.spiderloader' from '/home/xda/anaconda3/lib/python3.7/site-packages/scrapy/spiderloader.py'>

In [35]: getattr(mod,name)
Out[35]: scrapy.spiderloader.SpiderLoader

In [36]: obj = getattr(mod,name)

In [37]: obj
Out[37]: scrapy.spiderloader.SpiderLoader

In [38]: type(obj)
Out[38]: type

在代码块A中,loader_cls是SpiderLoader,最后返回的的是SpiderLoader.from_settings(settings.frozencopy())
接下来看看SpiderLoader.from_settings,
    def from_settings(cls, settings):
return cls(settings)

返回类对象自己,所以直接看__init__函数即可
class SpiderLoader(object):
"""
SpiderLoader is a class which locates and loads spiders
in a Scrapy project.
"""
def __init__(self, settings):
self.spider_modules = settings.getlist('SPIDER_MODULES')
# 获得settting中的模块名字,创建scrapy的时候就默认帮你生成了
# 你可以看看你的settings文件里面的内容就可以找到这个值,是一个list

self.warn_only = settings.getbool('SPIDER_LOADER_WARN_ONLY')
self._spiders = {}
self._found = defaultdict(list)
self._load_all_spiders() # 加载所有爬虫


核心就是这个_load_all_spiders:
走起:
def _load_all_spiders(self):
for name in self.spider_modules:

for module in walk_modules(name): # 这个遍历文件夹里面的文件,然后再转化为类对象,
# 保存到字典:self._spiders = {}
self._load_spiders(module) # 模块变成spider

self._check_name_duplicates() # 去重,如果名字一样就异常


接下来看看_load_spiders
核心就是下面的。
def iter_spider_classes(module):
from scrapy.spiders import Spider

for obj in six.itervalues(vars(module)): # 找到模块里面的变量,然后迭代出来
if inspect.isclass(obj) and \
issubclass(obj, Spider) and \
obj.__module__ == module.__name__ and \
getattr(obj, 'name', None): # 有name属性,继承于Spider
yield obj

这个obj就是我们平时写的spider类了。
原来分析了这么多,才找到了我们平时写的爬虫类

待续。。。。
 
原创文章
转载请注明出处
http://30daydo.com/article/530
 

python分析目前为止科创板企业省份分布

量化交易李魔佛 发表了文章 • 0 个评论 • 402 次浏览 • 2019-08-26 00:45 • 来自相关话题

科创板上市以来已经有一个多月了,我想看看到目前为止,上市企业都是归属哪些地方的。 因为个人觉得科创板是上证板块的,那么来自江浙一带的企业会更多。 毕竟现在深市和沪市在争夺资源,深市希望把深圳企业留回在深市的主板或者中小创版块。
 
首先获取行情数据,借助tushare这个框架:
在python3环境下,pip install tushare --upgrade ,记得要更新,因为用的旧版本会获取不到科创板的数据。
安装成功后试试import tushare as ts,看看有没有报错。没有就是安装成功了。
 
接下来抓取全市场的行情.




(点击查看大图)
查看前5条数据
 现在行情数据存储在df中,然后分析数据。
因为提取的是全市场的数据,然后获取科创板的企业:




(点击查看大图)

使用的是正则表达式,匹配688开头的代码。
 
接下来就是分析企业归属地:




(点击查看大图)

使用value_counts函数,统计该列每个值出现的次数。

搞定了! 是不是很简单?
 
而且企业地区分布和自己的构想也差不多,江浙沪一带占了一半,加上北京地区,占了80%以上的科创板企业了。
 
每周会定期更新一篇python数据分析股票的文章。
 
原创文章,欢迎转载
请注明出处:
 http://30daydo.com/article/528 

  查看全部
科创板上市以来已经有一个多月了,我想看看到目前为止,上市企业都是归属哪些地方的。 因为个人觉得科创板是上证板块的,那么来自江浙一带的企业会更多。 毕竟现在深市和沪市在争夺资源,深市希望把深圳企业留回在深市的主板或者中小创版块。
 
首先获取行情数据,借助tushare这个框架:
在python3环境下,pip install tushare --upgrade ,记得要更新,因为用的旧版本会获取不到科创板的数据。
安装成功后试试import tushare as ts,看看有没有报错。没有就是安装成功了。
 
接下来抓取全市场的行情.

a1.PNG
(点击查看大图)
查看前5条数据
 现在行情数据存储在df中,然后分析数据。
因为提取的是全市场的数据,然后获取科创板的企业:

a2.PNG
(点击查看大图)

使用的是正则表达式,匹配688开头的代码。
 
接下来就是分析企业归属地:

a3.PNG
(点击查看大图)

使用value_counts函数,统计该列每个值出现的次数。

搞定了! 是不是很简单?
 
而且企业地区分布和自己的构想也差不多,江浙沪一带占了一半,加上北京地区,占了80%以上的科创板企业了。
 
每周会定期更新一篇python数据分析股票的文章。
 
原创文章,欢迎转载
请注明出处:
 http://30daydo.com/article/528 

 

random.randint的用法

python李魔佛 发表了文章 • 0 个评论 • 440 次浏览 • 2019-08-01 16:31 • 来自相关话题

random.randint的用法:
from random import randint

randint(0,1)
Out[25]: 1

randint(0,1)
Out[26]: 1

randint(0,1)
Out[27]: 1

randint(0,1)
Out[28]: 1

randint(0,1)
Out[29]: 0

randint(0,1)
Out[30]: 1
random.randint(a,b)
 
输出的整数范围包含a和b,和之间的整数
  查看全部
random.randint的用法:
from random import randint

randint(0,1)
Out[25]: 1

randint(0,1)
Out[26]: 1

randint(0,1)
Out[27]: 1

randint(0,1)
Out[28]: 1

randint(0,1)
Out[29]: 0

randint(0,1)
Out[30]: 1

random.randint(a,b)
 
输出的整数范围包含a和b,和之间的整数
 

python执行shell命令时报错: -/bin/sh: 命令:not found的解决办法

Linux李魔佛 发表了文章 • 0 个评论 • 811 次浏览 • 2019-07-29 15:13 • 来自相关话题

file='test.txt'
cmd = f'rsync -av {file} root@10.18.6.46:/home/cjw/'

p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE,executable="/bin/bash")
output, error = p.communicate()
if p.returncode != 0:
print("Error while running - %s" % cmd)
print(error)
print(output) 
用sublime3 运行的时候一直报错。
后来发现,这个是sublime3的运行环境问题, 直接用shell执行 python main.py 执行上面的代码,命令可以正常运行。
/bin/sh: 1: rsync: not found 查看全部
     file='test.txt'
cmd = f'rsync -av {file} root@10.18.6.46:/home/cjw/'

p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE,executable="/bin/bash")
output, error = p.communicate()
if p.returncode != 0:
print("Error while running - %s" % cmd)
print(error)
print(output)
 
用sublime3 运行的时候一直报错。
后来发现,这个是sublime3的运行环境问题, 直接用shell执行 python main.py 执行上面的代码,命令可以正常运行。
/bin/sh: 1: rsync: not found

scrapy源码分析<一>:入口函数以及是如何运行

python爬虫李魔佛 发表了文章 • 0 个评论 • 288 次浏览 • 2019-08-31 10:47 • 来自相关话题

运行scrapy crawl example 命令的时候,就会执行我们写的爬虫程序。
下面我们从源码分析一下scrapy执行的流程:
 

执行scrapy crawl 命令时,调用的是Command类class Command(ScrapyCommand):

requires_project = True

def syntax(self):
return '[options]'

def short_desc(self):
return 'Runs all of the spiders - My Defined'

def run(self,args,opts):
print('==================')
print(type(self.crawler_process))
spider_list = self.crawler_process.spiders.list() # 找到爬虫类

for name in spider_list:
print('=================')
print(name)
self.crawler_process.crawl(name,**opts.__dict__)

self.crawler_process.start()
然后我们去看看crawler_process,这个是来自ScrapyCommand,而ScrapyCommand又是CrawlerProcess的子类,而CrawlerProcess又是CrawlerRunner的子类

在CrawlerRunner构造函数里面主要作用就是这个 def __init__(self, settings=None):
if isinstance(settings, dict) or settings is None:
settings = Settings(settings)
self.settings = settings
self.spider_loader = _get_spider_loader(settings) # 构造爬虫
self._crawlers = set()
self._active = set()
self.bootstrap_failed = False
1. 加载配置文件def _get_spider_loader(settings):

cls_path = settings.get('SPIDER_LOADER_CLASS')

# settings文件没有定义SPIDER_LOADER_CLASS,所以这里获取到的是系统的默认配置文件,
# 默认配置文件在接下来的代码块A
# SPIDER_LOADER_CLASS = 'scrapy.spiderloader.SpiderLoader'

loader_cls = load_object(cls_path)
# 这个函数就是根据路径转为类对象,也就是上面crapy.spiderloader.SpiderLoader 这个
# 字符串变成一个类对象
# 具体的load_object 对象代码见下面代码块B

return loader_cls.from_settings(settings.frozencopy())
默认配置文件defautl_settting.py# 代码块A
#......省略若干
SCHEDULER = 'scrapy.core.scheduler.Scheduler'
SCHEDULER_DISK_QUEUE = 'scrapy.squeues.PickleLifoDiskQueue'
SCHEDULER_MEMORY_QUEUE = 'scrapy.squeues.LifoMemoryQueue'
SCHEDULER_PRIORITY_QUEUE = 'scrapy.pqueues.ScrapyPriorityQueue'

SPIDER_LOADER_CLASS = 'scrapy.spiderloader.SpiderLoader' 就是这个值
SPIDER_LOADER_WARN_ONLY = False

SPIDER_MIDDLEWARES = {}

load_object的实现# 代码块B 为了方便,我把异常处理的去除
from importlib import import_module #导入第三方库

def load_object(path):
dot = path.rindex('.')
module, name = path[:dot], path[dot+1:]
# 上面把路径分为基本路径+模块名

mod = import_module(module)
obj = getattr(mod, name)
# 获取模块里面那个值

return obj

测试代码:In [33]: mod = import_module(module)

In [34]: mod
Out[34]: <module 'scrapy.spiderloader' from '/home/xda/anaconda3/lib/python3.7/site-packages/scrapy/spiderloader.py'>

In [35]: getattr(mod,name)
Out[35]: scrapy.spiderloader.SpiderLoader

In [36]: obj = getattr(mod,name)

In [37]: obj
Out[37]: scrapy.spiderloader.SpiderLoader

In [38]: type(obj)
Out[38]: type
在代码块A中,loader_cls是SpiderLoader,最后返回的的是SpiderLoader.from_settings(settings.frozencopy())
接下来看看SpiderLoader.from_settings, def from_settings(cls, settings):
return cls(settings)
返回类对象自己,所以直接看__init__函数即可class SpiderLoader(object):
"""
SpiderLoader is a class which locates and loads spiders
in a Scrapy project.
"""
def __init__(self, settings):
self.spider_modules = settings.getlist('SPIDER_MODULES')
# 获得settting中的模块名字,创建scrapy的时候就默认帮你生成了
# 你可以看看你的settings文件里面的内容就可以找到这个值,是一个list

self.warn_only = settings.getbool('SPIDER_LOADER_WARN_ONLY')
self._spiders = {}
self._found = defaultdict(list)
self._load_all_spiders() # 加载所有爬虫

核心就是这个_load_all_spiders:
走起:def _load_all_spiders(self):
for name in self.spider_modules:

for module in walk_modules(name): # 这个遍历文件夹里面的文件,然后再转化为类对象,
# 保存到字典:self._spiders = {}
self._load_spiders(module) # 模块变成spider

self._check_name_duplicates() # 去重,如果名字一样就异常

接下来看看_load_spiders
核心就是下面的。def iter_spider_classes(module):
from scrapy.spiders import Spider

for obj in six.itervalues(vars(module)): # 找到模块里面的变量,然后迭代出来
if inspect.isclass(obj) and \
issubclass(obj, Spider) and \
obj.__module__ == module.__name__ and \
getattr(obj, 'name', None): # 有name属性,继承于Spider
yield obj
这个obj就是我们平时写的spider类了。
原来分析了这么多,才找到了我们平时写的爬虫类

待续。。。。
 
原创文章
转载请注明出处
http://30daydo.com/article/530
  查看全部
运行scrapy crawl example 命令的时候,就会执行我们写的爬虫程序。
下面我们从源码分析一下scrapy执行的流程:
 

执行scrapy crawl 命令时,调用的是Command类
class Command(ScrapyCommand):

requires_project = True

def syntax(self):
return '[options]'

def short_desc(self):
return 'Runs all of the spiders - My Defined'

def run(self,args,opts):
print('==================')
print(type(self.crawler_process))
spider_list = self.crawler_process.spiders.list() # 找到爬虫类

for name in spider_list:
print('=================')
print(name)
self.crawler_process.crawl(name,**opts.__dict__)

self.crawler_process.start()

然后我们去看看crawler_process,这个是来自ScrapyCommand,而ScrapyCommand又是CrawlerProcess的子类,而CrawlerProcess又是CrawlerRunner的子类

在CrawlerRunner构造函数里面主要作用就是这个
      def __init__(self, settings=None):
if isinstance(settings, dict) or settings is None:
settings = Settings(settings)
self.settings = settings
self.spider_loader = _get_spider_loader(settings) # 构造爬虫
self._crawlers = set()
self._active = set()
self.bootstrap_failed = False

1. 加载配置文件
def _get_spider_loader(settings):

cls_path = settings.get('SPIDER_LOADER_CLASS')

# settings文件没有定义SPIDER_LOADER_CLASS,所以这里获取到的是系统的默认配置文件,
# 默认配置文件在接下来的代码块A
# SPIDER_LOADER_CLASS = 'scrapy.spiderloader.SpiderLoader'

loader_cls = load_object(cls_path)
# 这个函数就是根据路径转为类对象,也就是上面crapy.spiderloader.SpiderLoader 这个
# 字符串变成一个类对象
# 具体的load_object 对象代码见下面代码块B

return loader_cls.from_settings(settings.frozencopy())

默认配置文件defautl_settting.py
# 代码块A
#......省略若干
SCHEDULER = 'scrapy.core.scheduler.Scheduler'
SCHEDULER_DISK_QUEUE = 'scrapy.squeues.PickleLifoDiskQueue'
SCHEDULER_MEMORY_QUEUE = 'scrapy.squeues.LifoMemoryQueue'
SCHEDULER_PRIORITY_QUEUE = 'scrapy.pqueues.ScrapyPriorityQueue'

SPIDER_LOADER_CLASS = 'scrapy.spiderloader.SpiderLoader' 就是这个值
SPIDER_LOADER_WARN_ONLY = False

SPIDER_MIDDLEWARES = {}


load_object的实现
# 代码块B 为了方便,我把异常处理的去除
from importlib import import_module #导入第三方库

def load_object(path):
dot = path.rindex('.')
module, name = path[:dot], path[dot+1:]
# 上面把路径分为基本路径+模块名

mod = import_module(module)
obj = getattr(mod, name)
# 获取模块里面那个值

return obj


测试代码:
In [33]: mod = import_module(module)                                                                                                                                             

In [34]: mod
Out[34]: <module 'scrapy.spiderloader' from '/home/xda/anaconda3/lib/python3.7/site-packages/scrapy/spiderloader.py'>

In [35]: getattr(mod,name)
Out[35]: scrapy.spiderloader.SpiderLoader

In [36]: obj = getattr(mod,name)

In [37]: obj
Out[37]: scrapy.spiderloader.SpiderLoader

In [38]: type(obj)
Out[38]: type

在代码块A中,loader_cls是SpiderLoader,最后返回的的是SpiderLoader.from_settings(settings.frozencopy())
接下来看看SpiderLoader.from_settings,
    def from_settings(cls, settings):
return cls(settings)

返回类对象自己,所以直接看__init__函数即可
class SpiderLoader(object):
"""
SpiderLoader is a class which locates and loads spiders
in a Scrapy project.
"""
def __init__(self, settings):
self.spider_modules = settings.getlist('SPIDER_MODULES')
# 获得settting中的模块名字,创建scrapy的时候就默认帮你生成了
# 你可以看看你的settings文件里面的内容就可以找到这个值,是一个list

self.warn_only = settings.getbool('SPIDER_LOADER_WARN_ONLY')
self._spiders = {}
self._found = defaultdict(list)
self._load_all_spiders() # 加载所有爬虫


核心就是这个_load_all_spiders:
走起:
def _load_all_spiders(self):
for name in self.spider_modules:

for module in walk_modules(name): # 这个遍历文件夹里面的文件,然后再转化为类对象,
# 保存到字典:self._spiders = {}
self._load_spiders(module) # 模块变成spider

self._check_name_duplicates() # 去重,如果名字一样就异常


接下来看看_load_spiders
核心就是下面的。
def iter_spider_classes(module):
from scrapy.spiders import Spider

for obj in six.itervalues(vars(module)): # 找到模块里面的变量,然后迭代出来
if inspect.isclass(obj) and \
issubclass(obj, Spider) and \
obj.__module__ == module.__name__ and \
getattr(obj, 'name', None): # 有name属性,继承于Spider
yield obj

这个obj就是我们平时写的spider类了。
原来分析了这么多,才找到了我们平时写的爬虫类

待续。。。。
 
原创文章
转载请注明出处
http://30daydo.com/article/530
 

Linux下自制有道词典 - python 解密有道词典JS加密

python爬虫李魔佛 发表了文章 • 0 个评论 • 740 次浏览 • 2019-02-23 20:17 • 来自相关话题

对于爬虫新手来说,JS解密是一道过不去的坎,需要不断地练习。
平时在linux下开发,鉴于没有什么好用翻译软件,打开网易也占用系统资源,所以写了个在控制台的翻译软件接口。
 
使用python爬虫,查看网页的JS加密方法,一步一步地分析,就能够得到最后的加密方法啦。
 
直接给出代码:
 # -*- coding: utf-8 -*-
# website: http://30daydo.com
# @Time : 2019/2/23 19:34
# @File : youdao.py
# 解密有道词典的JS


import hashlib
import random
import requests
import time


def md5_(word):
s = bytes(word, encoding='utf8')
m = hashlib.md5()
m.update(s)
ret = m.hexdigest()
return ret

def get_sign(word, salt):
ret = md5_('fanyideskweb' + word + salt + 'p09@Bn{h02_BIEe]$P^nG')
return ret


def youdao(word):
url = 'http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'
headers = {
'Host': 'fanyi.youdao.com',
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0',
'Accept': 'application/json, text/javascript, */*; q=0.01',
'Accept-Language': 'zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3',
'Accept-Encoding': 'gzip, deflate',
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
'X-Requested-With': 'XMLHttpRequest',
'Referer': 'http://fanyi.youdao.com/',
'Content-Length': '252',
'Cookie': 'YOUDAO_MOBILE_ACCESS_TYPE=1; OUTFOX_SEARCH_USER_ID=1672542763@10.169.0.83; JSESSIONID=aaaWzxpjeDu1gbhopLzKw; ___rl__test__cookies=1550913722828; OUTFOX_SEARCH_USER_ID_NCOO=372126049.6326876',
'Connection': 'keep-alive',
'Pragma': 'no-cache',
'Cache-Control': 'no-cache',
}

ts = str(int(time.time()*1000))
salt=ts+str(random.randint(0,10))
bv = md5_("5.0 (Windows)")
sign= get_sign(word,salt)

post_data = {
'i': word,
'from': 'AUTO', 'to': 'AUTO', 'smartresult': 'dict', 'client': 'fanyideskweb', 'salt': salt,
'sign': sign, 'ts': ts, 'bv': bv, 'doctype': 'json', 'version': '2.1',
'keyfrom': 'fanyi.web', 'action': 'FY_BY_REALTIME', 'typoResult': 'false'
}

r = requests.post(
url=url,
headers=headers,
data=post_data
)

for item in r.json().get('smartResult',{}).get('entries'):
print(item)

word='student'
youdao(word)
得到结果:





 
Github:
https://github.com/Rockyzsu/CrawlMan/tree/master/youdao_dictionary
原创文章,转载请注明出处
http://30daydo.com/article/416 查看全部
对于爬虫新手来说,JS解密是一道过不去的坎,需要不断地练习。
平时在linux下开发,鉴于没有什么好用翻译软件,打开网易也占用系统资源,所以写了个在控制台的翻译软件接口。
 
使用python爬虫,查看网页的JS加密方法,一步一步地分析,就能够得到最后的加密方法啦。
 
直接给出代码:
 
# -*- coding: utf-8 -*-
# website: http://30daydo.com
# @Time : 2019/2/23 19:34
# @File : youdao.py
# 解密有道词典的JS


import hashlib
import random
import requests
import time


def md5_(word):
s = bytes(word, encoding='utf8')
m = hashlib.md5()
m.update(s)
ret = m.hexdigest()
return ret

def get_sign(word, salt):
ret = md5_('fanyideskweb' + word + salt + 'p09@Bn{h02_BIEe]$P^nG')
return ret


def youdao(word):
url = 'http://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'
headers = {
'Host': 'fanyi.youdao.com',
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0',
'Accept': 'application/json, text/javascript, */*; q=0.01',
'Accept-Language': 'zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3',
'Accept-Encoding': 'gzip, deflate',
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
'X-Requested-With': 'XMLHttpRequest',
'Referer': 'http://fanyi.youdao.com/',
'Content-Length': '252',
'Cookie': 'YOUDAO_MOBILE_ACCESS_TYPE=1; OUTFOX_SEARCH_USER_ID=1672542763@10.169.0.83; JSESSIONID=aaaWzxpjeDu1gbhopLzKw; ___rl__test__cookies=1550913722828; OUTFOX_SEARCH_USER_ID_NCOO=372126049.6326876',
'Connection': 'keep-alive',
'Pragma': 'no-cache',
'Cache-Control': 'no-cache',
}

ts = str(int(time.time()*1000))
salt=ts+str(random.randint(0,10))
bv = md5_("5.0 (Windows)")
sign= get_sign(word,salt)

post_data = {
'i': word,
'from': 'AUTO', 'to': 'AUTO', 'smartresult': 'dict', 'client': 'fanyideskweb', 'salt': salt,
'sign': sign, 'ts': ts, 'bv': bv, 'doctype': 'json', 'version': '2.1',
'keyfrom': 'fanyi.web', 'action': 'FY_BY_REALTIME', 'typoResult': 'false'
}

r = requests.post(
url=url,
headers=headers,
data=post_data
)

for item in r.json().get('smartResult',{}).get('entries'):
print(item)

word='student'
youdao(word)

得到结果:

youdao.PNG

 
Github:
https://github.com/Rockyzsu/CrawlMan/tree/master/youdao_dictionary
原创文章,转载请注明出处
http://30daydo.com/article/416

python 中文图片文字识别

python李魔佛 发表了文章 • 0 个评论 • 996 次浏览 • 2019-02-01 10:47 • 来自相关话题

pytesseract这个库识别率偏低,也就菜鸟才会用。
使用方法很简单,安装好pytesseract(里面很多坑,小白的话不可避免要折腾一番),然后下载一个中文的字库,百度网盘:https://pan.baidu.com/s/1_jom2d95IeR40gsvkhUuvQ
 
然后把文件放到tesseract的文件夹中 C:\Program Files (x86)\Tesseract-OCR\tessdata 
然后就可以拿来识别了:
from PIL import Image
im = Image.open('chinese.jpg')
plt.figure(figsize=(20,20))
plt.imshow(im)

pytesseract.image_to_string(im,lang='chi_sim')
图片的内容是这样的:





 
然后识别效果如下:
 
'可L又使用以下的语句i上图片显示大 此'
还是不咋地。
 
那么可以换成大厂的API。试试百度的:
""" 读取图片 """
def get_file_content(filePath):
with open(filePath, 'rb') as fp:
return fp.read()

image = get_file_content('example.jpg')

""" 调用通用文字识别, 图片参数为本地图片 """
client.basicGeneral(image);

""" 如果有可选参数 """
options = {}
options["language_type"] = "CHN_ENG"
options["detect_direction"] = "true"
options["detect_language"] = "true"
options["probability"] = "true"

from aip import AipOcr

""" 你的 APPID AK SK """
APP_ID = '你的 App ID'
API_KEY = '你的 Api Key'
SECRET_KEY = '你的 Secret Key'

client = AipOcr(APP_ID, API_KEY, SECRET_KEY)


""" 带参数调用通用文字识别, 图片参数为本地图片 """
client.basicGeneral(image, options)

url = "https//www.x.com/sample.jpg"

""" 调用通用文字识别, 图片参数为远程url图片 """
client.basicGeneralUrl(url);

""" 如果有可选参数 """
options = {}
options["language_type"] = "CHN_ENG"
options["detect_direction"] = "true"
options["detect_language"] = "true"
options["probability"] = "true"

""" 带参数调用通用文字识别, 图片参数为远程url图片 """
client.basicGeneralUrl(url, options)
先去百度云申请一个API,免费的。
https://cloud.baidu.com/doc/OCR/OCR-Python-SDK.html#.E9.85.8D.E7.BD.AEAipOcr
然后把key复制到上面的代码中就可以了。
 
然后再调用看看结果:
可以使用以下的语句让图片显示大些正确率明显高很多了。
 
 
 
  查看全部
pytesseract这个库识别率偏低,也就菜鸟才会用。
使用方法很简单,安装好pytesseract(里面很多坑,小白的话不可避免要折腾一番),然后下载一个中文的字库,百度网盘:https://pan.baidu.com/s/1_jom2d95IeR40gsvkhUuvQ
 
然后把文件放到tesseract的文件夹中 C:\Program Files (x86)\Tesseract-OCR\tessdata 
然后就可以拿来识别了:
from PIL import Image
im = Image.open('chinese.jpg')
plt.figure(figsize=(20,20))
plt.imshow(im)

pytesseract.image_to_string(im,lang='chi_sim')

图片的内容是这样的:

中文1.JPG

 
然后识别效果如下:
 
'可L又使用以下的语句i上图片显示大 此'

还是不咋地。
 
那么可以换成大厂的API。试试百度的:
""" 读取图片 """
def get_file_content(filePath):
with open(filePath, 'rb') as fp:
return fp.read()

image = get_file_content('example.jpg')

""" 调用通用文字识别, 图片参数为本地图片 """
client.basicGeneral(image);

""" 如果有可选参数 """
options = {}
options["language_type"] = "CHN_ENG"
options["detect_direction"] = "true"
options["detect_language"] = "true"
options["probability"] = "true"

from aip import AipOcr

""" 你的 APPID AK SK """
APP_ID = '你的 App ID'
API_KEY = '你的 Api Key'
SECRET_KEY = '你的 Secret Key'

client = AipOcr(APP_ID, API_KEY, SECRET_KEY)


""" 带参数调用通用文字识别, 图片参数为本地图片 """
client.basicGeneral(image, options)

url = "https//www.x.com/sample.jpg"

""" 调用通用文字识别, 图片参数为远程url图片 """
client.basicGeneralUrl(url);

""" 如果有可选参数 """
options = {}
options["language_type"] = "CHN_ENG"
options["detect_direction"] = "true"
options["detect_language"] = "true"
options["probability"] = "true"

""" 带参数调用通用文字识别, 图片参数为远程url图片 """
client.basicGeneralUrl(url, options)

先去百度云申请一个API,免费的。
https://cloud.baidu.com/doc/OCR/OCR-Python-SDK.html#.E9.85.8D.E7.BD.AEAipOcr
然后把key复制到上面的代码中就可以了。
 
然后再调用看看结果:
可以使用以下的语句让图片显示大些
正确率明显高很多了。
 
 
 
 

可转债价格分布堆叠图 绘制 可视化 python+pyecharts

量化交易李魔佛 发表了文章 • 0 个评论 • 1233 次浏览 • 2019-01-30 10:59 • 来自相关话题

这一节课带大家学习如何利用可视化,更好的呈现数据。
即使你有很多数据,可是,你无法直观地看到数据的总体趋势。使用可视化的绘图,可以帮助我们看到数据背后看不到的数据。 比如我已经有每一个可转债的价格,评级。数据如下:





 点击查看大图

如果我用下面的图形就可以看出规律:




 点击查看大图

横坐标是价格,纵坐标是落在该价格的可转债数量,不同颜色代表不同评级的可转债。
 
可以看到大部分AA-评级(浅橙色)的可转债价格都在100元以下,而AA(浅蓝色)的可转债价格分布较为平均,从90到110都有。而AA+和AAA的一般都在100以上。
 
那么如何使用代码实现呢?from setting import get_mysql_conn,get_engine
import pandas as pd
import pymongo
from pyecharts import Geo,Style,Map
engine = get_engine('db_stock',local='local')
# 堆叠图
from pyecharts import Bar
df = pd.read_sql('tb_bond_jisilu',con=engine)

result ={}
for name,grades in df.groupby('评级'):
# print(name,grades[['可转债名称','可转债价格']])
for each in grades['可转债价格']:
result.setdefault(name,)
result[name].append(each)


# 确定价格的范围

value = [str(i) for i in range(85,140)]
ret = [0]*len(value)
ret1 = dict(zip(value,ret))

ret_A_add = ret1.copy()
for item in result['A+']:
for k in ret1:
if float(k)+0.5>item and float(k)-0.5<=item:
ret_A_add[k]+=1

retAA_ = ret1.copy()
for item in result['']:
for k in ret1:
if float(k)+0.5>item and float(k)-0.5<=item:
retAA_[k]+=1

retAA = ret1.copy()
for item in result['AA']:
for k in ret1:
if float(k)+0.5>item and float(k)-0.5<=item:
retAA[k]+=1

retAA_add = ret1.copy()
for item in result['AA+']:
for k in ret1:
if float(k)+0.5>item and float(k)-0.5<=item:
retAA_add[k]+=1

retAAA = ret1.copy()
for item in result['AAA']:
for k in ret1:
if float(k)+0.5>item and float(k)-0.5<=item:
retAAA[k]+=1

bar = Bar('可转债价格分布')
bar.add('A+',value,list(ret_A_add.values()),is_stack=True,yaxis_max=11)
bar.add('',value,list(retAA_.values()),is_stack=True,yaxis_max=11)
bar.add('AA',value,list(retAA.values()),is_stack=True,yaxis_max=11)
bar.add('AA+',value,list(retAA_add.values()),is_stack=True,yaxis_max=11)
bar.add('AAA',value,list(retAAA.values()),is_stack=True,yaxis_max=11)
如果没有安装pyecharts,需要用pip安装即可。
 
上面代码运行后就可以得到上面最开始那张堆叠图了。
github:https://github.com/Rockyzsu/convertible_bond​ 
 
 
原创文章
转载请注明出处:
 http://30daydo.com/article/400 

  查看全部
这一节课带大家学习如何利用可视化,更好的呈现数据。
即使你有很多数据,可是,你无法直观地看到数据的总体趋势。使用可视化的绘图,可以帮助我们看到数据背后看不到的数据。 比如我已经有每一个可转债的价格,评级。数据如下:

可转债数据.JPG

 点击查看大图

如果我用下面的图形就可以看出规律:
可转债价格分布.JPG

 点击查看大图

横坐标是价格,纵坐标是落在该价格的可转债数量,不同颜色代表不同评级的可转债。
 
可以看到大部分AA-评级(浅橙色)的可转债价格都在100元以下,而AA(浅蓝色)的可转债价格分布较为平均,从90到110都有。而AA+和AAA的一般都在100以上。
 
那么如何使用代码实现呢?
from  setting import get_mysql_conn,get_engine
import pandas as pd
import pymongo
from pyecharts import Geo,Style,Map
engine = get_engine('db_stock',local='local')
# 堆叠图
from pyecharts import Bar
df = pd.read_sql('tb_bond_jisilu',con=engine)

result ={}
for name,grades in df.groupby('评级'):
# print(name,grades[['可转债名称','可转债价格']])
for each in grades['可转债价格']:
result.setdefault(name,)
result[name].append(each)


# 确定价格的范围

value = [str(i) for i in range(85,140)]
ret = [0]*len(value)
ret1 = dict(zip(value,ret))

ret_A_add = ret1.copy()
for item in result['A+']:
for k in ret1:
if float(k)+0.5>item and float(k)-0.5<=item:
ret_A_add[k]+=1

retAA_ = ret1.copy()
for item in result['']:
for k in ret1:
if float(k)+0.5>item and float(k)-0.5<=item:
retAA_[k]+=1

retAA = ret1.copy()
for item in result['AA']:
for k in ret1:
if float(k)+0.5>item and float(k)-0.5<=item:
retAA[k]+=1

retAA_add = ret1.copy()
for item in result['AA+']:
for k in ret1:
if float(k)+0.5>item and float(k)-0.5<=item:
retAA_add[k]+=1

retAAA = ret1.copy()
for item in result['AAA']:
for k in ret1:
if float(k)+0.5>item and float(k)-0.5<=item:
retAAA[k]+=1

bar = Bar('可转债价格分布')
bar.add('A+',value,list(ret_A_add.values()),is_stack=True,yaxis_max=11)
bar.add('',value,list(retAA_.values()),is_stack=True,yaxis_max=11)
bar.add('AA',value,list(retAA.values()),is_stack=True,yaxis_max=11)
bar.add('AA+',value,list(retAA_add.values()),is_stack=True,yaxis_max=11)
bar.add('AAA',value,list(retAAA.values()),is_stack=True,yaxis_max=11)

如果没有安装pyecharts,需要用pip安装即可。
 
上面代码运行后就可以得到上面最开始那张堆叠图了。
github:https://github.com/Rockyzsu/convertible_bond​ 
 
 
原创文章
转载请注明出处:
 http://30daydo.com/article/400 

 

可转债套利【一】 python找出折价可转债个股

量化交易李魔佛 发表了文章 • 8 个评论 • 9954 次浏览 • 2018-03-16 17:17 • 来自相关话题

关于可转债的定义,可以到https://xueqiu.com/6832369826/103042836 这里科普一下。
 
下面的内容默认你对可转债已经有一定的了解。
 
可转债的价值=正股价格/转股价格 + 利息,忽略可转债的利息,直接用公式 可转债的价值=正股价格/转股价格 计算可转债的价值。
 
如果当前可转债的交易价格(在交易软件上显示的价格)如:




所以万信转债的价格是121.5元,然后万信转债的价值呢? 按照上面的公式,万信转债的正股是万达信息,今天万达信息  (2018-03-16)的股价是





以收盘价为例,17.25。
 
而万信转债的股转价格呢? 这个可以到万信转债F10页面的公告中找到,为13.11元。 所以万信转债的价值是
17.25/13.11 = 1.315 , 可转债单位是100, 所以万信转债的内在价值是1.315*100=131.5, 而当前的交易价格为 121.5





 
 
也就是你用121.5元买到一个价值 131.5的商品, 所以相当于打折买到了一个超值的商品,所以当前的万信转债是折价状态。
 
所以本次任务就是要找出可交易的可转债中折价状态的可转债。
 
然后直接上干货。上python代码。#-*-coding=utf-8
'''
可转债监控
'''
import tushare as ts
from setting import get_engine
engine = get_engine('db_bond')
import pandas as pd
import datetime
class ConvertBond():

def __init__(self):
self.conn=ts.get_apis()
self.allBonds=ts.new_cbonds(pause=2)
self.onSellBond=self.allBonds.dropna(subset=['marketprice'])
self.today=datetime.datetime.now().strftime('%Y-%m-%d %H:%M')

def stockPrice(self,code):
stock_df = ts.get_realtime_quotes(code)
price = float(stock_df['price'].values[0])
return price

def dataframe(self):
price_list=[]
for code in self.onSellBond['scode']:
price_list.append(self.stockPrice(code))
self.onSellBond['stock_price']=price_list
self.onSellBond['ratio'] = (
self.onSellBond['marketprice']
/(self.onSellBond['stock_price'] / self.onSellBond['convprice'])-1)*100
self.onSellBond['Updated']=self.today
self.onSellBond.to_sql('tb_bond',engine,if_exists='replace')

def closed(self):
ts.close_apis(self.conn)

def main():
bond=ConvertBond()
bond.dataframe()
bond.closed()
if __name__=='__main__':
main()







 上面的setting库,把下面的*** 替换成你自己的Mysql用户和密码即可。import os
import MySQLdb
MYSQL_USER = *********
MYSQL_PASSWORD = ********
MYSQL_HOST = *********
MYSQL_PORT = *****

def get_engine(db):
engine = create_engine('mysql+pymysql://{}:{}@{}:{}/{}?charset=utf8'.format(MYSQL_USER, MYSQL_PASSWORD, MYSQL_HOST, MYSQL_PORT, db))
return engine 
上面的少于100行的代码就能够满足你的要求。
运行后会把结果保存在MySQL 数据库。如下图所示:







点击放大
  2018-03-16 可转债表格
 
其中折价率是ratio列。按照ratio列进行排列,只有2个是正,也就是当前市场是只有2只可转债是处于折价状态的,其余的都是溢价状态(价格比内在价值要贵,忽略利息的前提下,如果把4~5%的利息也算进去的话,-3~4%的折价率其实也算小折价吧)
 
目前万信转债折价10个点,宝信转债折价5.8个点。 所以适合低风险投资者建仓。 因为可转债有兜底价格,所以出现亏损的概率很低(除非遇到黑天鹅,公司破产了,像遇到乐视这种PPT独角兽公司,欠债不还的。 但是A股上能够有资格发行可转债的,本身对公司的盈利,分红都有硬性要求)。
 
所以可以保存上面的代码,可以每天运行一次,可以很方便地找出折价的个股,当然也可以在盘中一直监测,因为可转债的价格是实时变化的,一旦遇到大跌,跌到折价状态,你也可以择时入手标的。

原文链接:
http://30daydo.com/article/286
转载请注明出处 查看全部
关于可转债的定义,可以到https://xueqiu.com/6832369826/103042836 这里科普一下。
 
下面的内容默认你对可转债已经有一定的了解。
 
可转债的价值=正股价格/转股价格 + 利息,忽略可转债的利息,直接用公式 可转债的价值=正股价格/转股价格 计算可转债的价值。
 
如果当前可转债的交易价格(在交易软件上显示的价格)如:
wxzz.GIF

所以万信转债的价格是121.5元,然后万信转债的价值呢? 按照上面的公式,万信转债的正股是万达信息,今天万达信息  (2018-03-16)的股价是

万达信息.GIF

以收盘价为例,17.25。
 
而万信转债的股转价格呢? 这个可以到万信转债F10页面的公告中找到,为13.11元。 所以万信转债的价值是
17.25/13.11 = 1.315 , 可转债单位是100, 所以万信转债的内在价值是1.315*100=131.5, 而当前的交易价格为 121.5

wxzz.GIF

 
 
也就是你用121.5元买到一个价值 131.5的商品, 所以相当于打折买到了一个超值的商品,所以当前的万信转债是折价状态。
 
所以本次任务就是要找出可交易的可转债中折价状态的可转债。
 
然后直接上干货。上python代码。
#-*-coding=utf-8
'''
可转债监控
'''
import tushare as ts
from setting import get_engine
engine = get_engine('db_bond')
import pandas as pd
import datetime
class ConvertBond():

def __init__(self):
self.conn=ts.get_apis()
self.allBonds=ts.new_cbonds(pause=2)
self.onSellBond=self.allBonds.dropna(subset=['marketprice'])
self.today=datetime.datetime.now().strftime('%Y-%m-%d %H:%M')

def stockPrice(self,code):
stock_df = ts.get_realtime_quotes(code)
price = float(stock_df['price'].values[0])
return price

def dataframe(self):
price_list=[]
for code in self.onSellBond['scode']:
price_list.append(self.stockPrice(code))
self.onSellBond['stock_price']=price_list
self.onSellBond['ratio'] = (
self.onSellBond['marketprice']
/(self.onSellBond['stock_price'] / self.onSellBond['convprice'])-1)*100
self.onSellBond['Updated']=self.today
self.onSellBond.to_sql('tb_bond',engine,if_exists='replace')

def closed(self):
ts.close_apis(self.conn)

def main():
bond=ConvertBond()
bond.dataframe()
bond.closed()
if __name__=='__main__':
main()







 上面的setting库,把下面的*** 替换成你自己的Mysql用户和密码即可。
import os
import MySQLdb
MYSQL_USER = *********
MYSQL_PASSWORD = ********
MYSQL_HOST = *********
MYSQL_PORT = *****

def get_engine(db):
engine = create_engine('mysql+pymysql://{}:{}@{}:{}/{}?charset=utf8'.format(MYSQL_USER, MYSQL_PASSWORD, MYSQL_HOST, MYSQL_PORT, db))
return engine
 
上面的少于100行的代码就能够满足你的要求。
运行后会把结果保存在MySQL 数据库。如下图所示:


Screenshot_from_2018-03-28_09-14-35.png


点击放大
  2018-03-16 可转债表格
 
其中折价率是ratio列。按照ratio列进行排列,只有2个是正,也就是当前市场是只有2只可转债是处于折价状态的,其余的都是溢价状态(价格比内在价值要贵,忽略利息的前提下,如果把4~5%的利息也算进去的话,-3~4%的折价率其实也算小折价吧)
 
目前万信转债折价10个点,宝信转债折价5.8个点。 所以适合低风险投资者建仓。 因为可转债有兜底价格,所以出现亏损的概率很低(除非遇到黑天鹅,公司破产了,像遇到乐视这种PPT独角兽公司,欠债不还的。 但是A股上能够有资格发行可转债的,本身对公司的盈利,分红都有硬性要求)。
 
所以可以保存上面的代码,可以每天运行一次,可以很方便地找出折价的个股,当然也可以在盘中一直监测,因为可转债的价格是实时变化的,一旦遇到大跌,跌到折价状态,你也可以择时入手标的。

原文链接:
http://30daydo.com/article/286
转载请注明出处

dataframe reindex和reset_index区别

量化交易李魔佛 发表了文章 • 0 个评论 • 23952 次浏览 • 2017-12-30 15:58 • 来自相关话题

reset_index的作用是重新设置dataframe的index,范围为0~len(df)。 df = pd.DataFrame({'A': [1, 2, 3, 4, 5], 'B': [10, 20, 30, 40, 50]})
df2 = pd.DataFrame({'A': [6], 'B': [60]})
print 'df\n', df
print 'df2\n', df2

df_x = [df, df2]
result = pd.concat(df_x)
print 'first result\n', result 
上面代码把df和df2合并为一个result,但是result的index是乱的。





 
那么执行result2= result.reset_index()
得到如下的result2: (默认只是返回一个copy,原来的result没有发生改变,所以需要副本赋值给result2)





可以看到,原来的一列index现在变成了columns之一,新的index为[0,1,2,3,4,5]
如果添加参数 reset_index(drop=True) 那么原index会被丢弃,不会显示为一个新列。result2 = result.reset_index(drop=True)



 
reindex的作用是按照原有的列进行重新生成一个新的df。
 
还是使用上面的代码
result目前是df和df2的合并序列。
如下:




 
可以看到index为[0,1,2,3,4,0]
执行 result3 = result.reindex(columns=['A','C'])




 
可以看到,原index并没有发生改变,而列变成了A和C,因为C是不存在的,所以使用了NaB填充,这个值的内容可以自己填充,可以改为默认填充0或者任意你想要的数据。reindex(columns=..)的作用类似于重新把列的顺序整理一遍, 而使用reindex(index=....) 则按照行重新整理一遍。

原文链接:http://30daydo.com/article/257 
欢迎转载,注明出处
  查看全部
reset_index的作用是重新设置dataframe的index,范围为0~len(df)。
    df = pd.DataFrame({'A': [1, 2, 3, 4, 5], 'B': [10, 20, 30, 40, 50]})
df2 = pd.DataFrame({'A': [6], 'B': [60]})
print 'df\n', df
print 'df2\n', df2

df_x = [df, df2]
result = pd.concat(df_x)
print 'first result\n', result
 
上面代码把df和df2合并为一个result,但是result的index是乱的。

df4.PNG

 
那么执行
result2= result.reset_index()

得到如下的result2: (默认只是返回一个copy,原来的result没有发生改变,所以需要副本赋值给result2)

df5.PNG

可以看到,原来的一列index现在变成了columns之一,新的index为[0,1,2,3,4,5]
如果添加参数 reset_index(drop=True) 那么原index会被丢弃,不会显示为一个新列。
result2 = result.reset_index(drop=True)
df6.PNG

 
reindex的作用是按照原有的列进行重新生成一个新的df。
 
还是使用上面的代码
result目前是df和df2的合并序列。
如下:
df7.PNG

 
可以看到index为[0,1,2,3,4,0]
执行 
result3 = result.reindex(columns=['A','C'])

df8.PNG

 
可以看到,原index并没有发生改变,而列变成了A和C,因为C是不存在的,所以使用了NaB填充,这个值的内容可以自己填充,可以改为默认填充0或者任意你想要的数据。reindex(columns=..)的作用类似于重新把列的顺序整理一遍, 而使用reindex(index=....) 则按照行重新整理一遍。

原文链接:http://30daydo.com/article/257 
欢迎转载,注明出处
 

聚币网/coinegg API使用教程 附demo代码

量化交易李魔佛 发表了文章 • 56 个评论 • 14886 次浏览 • 2017-05-11 09:05 • 来自相关话题

******* 2018.14 更新 ***********
现在聚币网已经被关闭了,但是所有的币都可以转移到CoinEgg网了,币种和以前一模一样,只是用户参与度减少了很多,市场不是一个有效的市场,但是这对于操盘手来说,更加是一个收益大的地方。
使用下面链接注册后,用户可以返30%的佣金。 其实也无所谓,佣金不会很多,一次也就几分钱到几毛钱,自己去官网注册也可以。看个人心情啦。
 
http://www.coinegg.com/user/register?inv=7d91a
 
 后续会就coinegg写一个自动交易的系统出来
 

******* 8.28 更新 ***********
不少人反应签名不通过,经过调试,发现是加密前的字符拼接的顺序问题,这个拼接顺序要和你post上去的顺序要一致,才能通过。如果出现104的返回代码,说明是你的顺序问题,说明你的签名没有成功。
 
贴代码说明下: 使用字典循环,就可以知道正确的拼接顺序。 下面的代码是获取成交订单的。 def Trade_list(self, coin):
'''
Trade_list(挂单查询)
您指定时间后的挂单,可以根据类型查询,比如查看正在挂单和全部挂单
Path:/api/v1/trade_list/
Request类型:POST
参数
key - API key
signature - signature
nonce - nonce
since - unix timestamp(utc timezone) default == 0, i.e. 返回所有
coin - 币种简称,例如btc、ltc、xas
type - 挂单类型[open:正在挂单, all:所有挂单]

返回JSON dictionary
id - 挂单ID
datetime - date and time
type - "buy" or "sell"
price - price
amount_original - 下单时数量
amount_outstanding - 当前剩余数量
'''
url = self.host + '/api/v1/trade_list/'
time.sleep(random.random())
nonce = self.get_nonce_time()
types = 'all'
since = 0
parameters = {'key': self.public_key, 'nonce': str(nonce), 'type': types, 'coin': coin, 'signature': ''}
# print parameters
post_data = ''
for k, v in parameters.items():
if not isinstance(v, str):
#if type(v) is not types.StringType:
v = str(v)
post_data = post_data + k
post_data = post_data + '=' + v + '&'

#print 'post-data:\n',post_data
post_data = post_data[:-1]
post_data = post_data.replace('&signature=', '')
#print post_data

signature = hmac.new(self.md5, post_data, digestmod=hashlib.sha256).digest()
sig = self.toHex(signature)
parameters['signature'] = sig
#print parameters
r = requests.post(url=url, data=parameters)
s = r.json()
#print s
return s
 
如果还是没有解决的话就网站内私信我看看问题所在。

******************************************* 原文内容 ***************************************************
 

 官方有API的文档,可是这个文档就像一个草稿一样,两个基本例子都没有。 所以自己摸索一下,自己写一个现成的例子给大家,可以有个参考。 下面的例子亲测成功。 
 
首先看一下官方的API文档:

一、API使用说明

1、请求过程说明

1.1 构造请求数据,用户数据按照Jubi提供的接口规则,通过程序生成签名和要传输给Jubi的数据集合;

1.2 发送请求数据,把构造完成的数据集合通过POST/GET提交的方式传递给Jubi;

1.3 Jubi对请求数据进行处理,服务器在接收到请求后,会首先进行安全校验,验证通过后便会处理该次发送过来的请求;

1.4 返回响应结果数据,Jubi把响应结果以JSON的格式反馈给用户,具体的响应格式,错误代码参见接口部分;

1.5 对获取的返回结果数据进行处理;

2、安全认证

所有的private API都需要经过认证

Api的申请可以到财务中心 -> API,申请得到私钥和公钥,私钥Jubi将不做储存,一旦丢失将无法找回

注意:请勿向任何人泄露这两个参数,这像您的密码一样重要

2.签名机制

每次请求private api 都需要验证签名,发送的参数示例:

$param = array(

amount => 1,

price => 10000,

type => 'buy',

nonce => 141377098123

key => 5zi7w-4mnes-swmc4-egg9b-f2iqw-396z4-g541b

signature => 459c69d25c496765191582d9611028b9974830e9dfafd762854669809290ed82

);

nonce 可以理解为一个递增的整数:http://zh.wikipedia.org/wiki/Nonce

key 是申请到的公钥

signature是签名,是将amount price type nonce key等参数通过'&'字符连接起来通过md5(私钥)为key进行sha256算法加密得到的值.

 

 
 
  
首先聚币的行情是使用网络爬虫获取的,而说明中给出了一系列的参数,你需要做的就是把这些参数填充上去。
 
如果你只是想要获取行情,那么事情容易很多。 def real_time_ticker(coin):
url = 'https://www.jubi.com/api/v1/ticker/'
try:
data = requests.post(url, data={'coin': coin}).json()

except Exception ,e:
print e
return data
上面代码展示的时候获取实时的行情。委一和买一的价格,数量,和当前成交的数量,价格。
 按照上面的格式,把参数coin填上去,比如要获取泽塔币, real_time_ticker('zet') 就会返回获取的数据。{u'sell': u'0.179000', u'volume': 21828245.102822, u'buy': u'0.175010', u'last': u'0.179000', u'vol': 108290769.9171, u'high': u'0.289000', u'low': u'0.119141'}
 
 
所有的private API都需要经过认证, 就是说如果你要进行交易,委托,下单,你就需要使用私钥和公钥,并进行一系列的加密。

每次请求private api 都需要验证签名,发送的参数示例:

$param = array(

amount => 1,

price => 10000,

type => 'buy',

nonce => 141377098123

key => 5zi7w-4mnes-swmc4-egg9b-f2iqw-396z4-g541b

signature => 459c69d25c496765191582d9611028b9974830e9dfafd762854669809290ed82

);

nonce 可以理解为一个递增的整数:http://zh.wikipedia.org/wiki/Nonce

key 是申请到的公钥

signature是签名,是将amount price type nonce key等参数通过'&'字符连接起来通过md5(私钥)为key进行sha256算法加密得到的值.

 
 
比如下单:

Trade_add(下单)
Path:/api/v1/trade_add/
Request类型:POST
 
参数
key - API key
signature - signature
nonce - nonce
amount - 购买数量
price - 购买价格
type - 买单或者卖单
coin - 币种简称,例如btc、ltc、xas
id - 挂单ID
result - true(成功), false(失败)
{"result":true, "id":"11"}
 
返回JSON dictionary
id - 挂单ID
result - true(成功), false(失败)
 
返回结果示例:
{"result":true, "id":"11"}
 


首先解决nonce。
 
在维基百科中
在安全工程中,Nonce是一个在加密通信只能使用一次的数字。在认证协议中,它往往是一个随机或伪随机数,以避免重放攻击。Nonce也用于流密码以确保安全。如果需要使用相同的密钥加密一个以上的消息,就需要Nonce来确保不同的消息与该密钥加密的密钥流不同。
 
结合stackoverflow, nonce只是一个12位的随机数。
可以用以下方法获得这个随机数 def get_nonce(self):
lens=12
return ''.join([str(random.randint(0, 9)) for i in range(lens)])
 聚币中的nonce的位数是12位,所以lens定义为12
 
或者可以直接用时间函数生成: def get_nonce_time(self):
lens = 12
curr_stamp = time.time()*100
nonece=int(curr_stamp)
return nonece
 
然后是signature。
signature是签名,是将amount price type nonce key等参数通过'&'字符连接起来通过md5(私钥)为key进行sha256算法加密得到的值.

先把私钥进行md5处理 def getHash(self,s):
m=hashlib.md5()
m.update(s)
return m.hexdigest()
只要把私钥传入函数getHash就可以得到一个md5处理过的字符串。
 
私钥是聚币网给每个用户分配的字符串,是唯一的,这里假设为private_key=123456789吧,具体是多少,在你的聚币网设置里面可以找到。
sha_256key=self.getHash(private_key)
 
按照要求吧 你要post的数据字符串连起来nonce=self.get_nonce_time
type='buy'
amount='10000'
key='xxxxxxxxxxx‘ #这个是聚币网给你的公钥,同样在设置里头可以找到
price='10' #你要设置的价格为10
coin='zet'
message = "amount=“+amount+”&nonce="+str(nonce)+"&type="+type+"&key="+key+'&price="+price+"&coin"+coin

signature = hmac.new(sha_256key, message, digestmod=hashlib.sha256).digest()

这样获得signature之后,就可以通过签名来进行post操作。

data_wrap={'nonce':nonce,'key':key_value,'signature':signature}

js=requests.post(url,data=data_wrap).json()
 
如果直接按照上面的代码去获取账户相关信息或者去挂单的话,会返回104的签名错误。 经过不断的排查,发现是signature的字符格式的问题。
 
构造一个str转换格式的函数: def toHex(self,str):
lst =
for ch in str:
hv = hex(ord(ch)).replace('0x', '')
if len(hv) == 1:
hv = '0' + hv
lst.append(hv)
return reduce(lambda x, y: x + y, lst)这个函数的作用就是把原来十六进制格式的字符完全转化成十六进制,把前面的0x去掉,不足2位的补全为2位。
把经过处理的signature进行格式转换后,几次提交,终于发现可以获取到用户的账户信息,进行下单,撤单,等操作。
 
 
 
下面是一个获取账户信息的代码段: def getAccount(self):
url='https://www.jubi.com/api/v1/balance/'

nonce_value=self.get_nonce_time()
print nonce_value
key_value=self.public_key
private_key=self.private_key

s='nonce='+str(nonce_value)+'&'+'key='+key_value

print s

#signature是签名,是将amount price type nonce key等参数通过'&'字符连接起来通过md5(私钥)为key进行sha256算法加密得到的值.
md5=self.getHash(private_key)
print md5
print type(md5)

msg=bytes(s).encode('utf-8')
key=bytes(md5).encode('utf-8')
signature =hmac.new(key,msg,digestmod=hashlib.sha256).digest()
print signature
print type(signature)
sig=self.toHex(signature)

print sig
data_wrap={'nonce':nonce_value,'key':key_value,'signature':sig}

print data_wrap

data_en=urllib.urlencode(data_wrap)
req=urllib2.Request(url,data=data_en)
resp=urllib2.urlopen(req).read()
print resp


def toHex(self,str):
lst =
for ch in str:
hv = hex(ord(ch)).replace('0x', '')
if len(hv) == 1:
hv = '0' + hv
lst.append(hv)
return reduce(lambda x, y: x + y, lst)
 
以上的代码运行后返回一下账户信息:{"uid":123456,"nameauth":1,"moflag":1,"asset":,"btc_balance":0,"btc_lock":0,"drk_balance":0,"drk_lock":0,"blk_balance":0,"blk_lock":0,"vrc_balance":0,"vrc_lock":0,"tfc_balance":0,"tfc_lock":0,"jbc_balance":0,"jbc_lock":0,"ltc_balance":0,"ltc_lock":0,"doge_balance":0,"doge_lock":0,"xpm_balance":0,"xpm_lock":0,"ppc_balance":0,"ppc_lock":0,"wdc_balance":0,"wdc_lock":0,"vtc_balance":0,"vtc_lock":0,"max_balance":0,"max_lock":0,"ifc_balance":0,"ifc_lock":0,"zcc_balance":0,"zcc_lock":0,"zet_balance":0,"zet_lock":0,"eac_balance":0,"eac_lock":0,"fz_balance":0,"fz_lock":0,"skt_balance":0,"skt_lock":0,"plc_balance":0,"plc_lock":0,"mtc_balance":0,"mtc_lock":0,"qec_balance":0,"qec_lock":0,"lkc_balance":10,"lkc_lock":0,"met_balance":0,"met_lock":0,"ytc_balance":0,"ytc_lock":0,"hlb_balance":0,"hlb_lock":0,"game_balance":0,"game_lock":0,"rss_balance":0,"rss_lock":0,"rio_balance":0,"rio_lock":0,"ktc_balance":0,"ktc_lock":0,"pgc_balance":0,"pgc_lock":0,"mryc_balance":0,"mryc_lock":0,"eth_balance":0,"eth_lock":0,"etc_balance":0,"etc_lock":0,"dnc_balance":0,"dnc_lock":0,"gooc_balance":0,"gooc_lock":0,"xrp_balance":0,"xrp_lock":0,"nxt_balance":0,"nxt_lock":0,"lsk_balance":0,"lsk_lock":0,"xas_balance":0,"xas_lock":0,"peb_balance":0,"peb_lock":0,"nhgh_balance":0,"nhgh_lock":0,"xsgs_balance":0,"xsgs_lock":0,"ans_balance":0,"ans_lock":0,"bts_balance":0,"bts_lock":0,"cny_balance":0,"cny_lock":0}











 
聚币网个人邀请码:
514330
 
还没注册可以拿去用,对于我而言可以拿到你们交易费用的50%,不过一般交易费除非是超级大户,一般散户都很少。千分之一的交易手续费。
 
欢迎一起讨论:
Email:weigesysu@qq.com

 原创内容,转载请注明出处
http://30daydo.com/article/181 
  查看全部
******* 2018.14 更新 ***********
现在聚币网已经被关闭了,但是所有的币都可以转移到CoinEgg网了,币种和以前一模一样,只是用户参与度减少了很多,市场不是一个有效的市场,但是这对于操盘手来说,更加是一个收益大的地方。
使用下面链接注册后,用户可以返30%的佣金。 其实也无所谓,佣金不会很多,一次也就几分钱到几毛钱,自己去官网注册也可以。看个人心情啦。
 
http://www.coinegg.com/user/register?inv=7d91a
 
 后续会就coinegg写一个自动交易的系统出来
 

******* 8.28 更新 ***********
不少人反应签名不通过,经过调试,发现是加密前的字符拼接的顺序问题,这个拼接顺序要和你post上去的顺序要一致,才能通过。如果出现104的返回代码,说明是你的顺序问题,说明你的签名没有成功。
 
贴代码说明下: 使用字典循环,就可以知道正确的拼接顺序。 下面的代码是获取成交订单的。
    def Trade_list(self, coin):
'''
Trade_list(挂单查询)
您指定时间后的挂单,可以根据类型查询,比如查看正在挂单和全部挂单
Path:/api/v1/trade_list/
Request类型:POST
参数
key - API key
signature - signature
nonce - nonce
since - unix timestamp(utc timezone) default == 0, i.e. 返回所有
coin - 币种简称,例如btc、ltc、xas
type - 挂单类型[open:正在挂单, all:所有挂单]

返回JSON dictionary
id - 挂单ID
datetime - date and time
type - "buy" or "sell"
price - price
amount_original - 下单时数量
amount_outstanding - 当前剩余数量
'''
url = self.host + '/api/v1/trade_list/'
time.sleep(random.random())
nonce = self.get_nonce_time()
types = 'all'
since = 0
parameters = {'key': self.public_key, 'nonce': str(nonce), 'type': types, 'coin': coin, 'signature': ''}
# print parameters
post_data = ''
for k, v in parameters.items():
if not isinstance(v, str):
#if type(v) is not types.StringType:
v = str(v)
post_data = post_data + k
post_data = post_data + '=' + v + '&'

#print 'post-data:\n',post_data
post_data = post_data[:-1]
post_data = post_data.replace('&signature=', '')
#print post_data

signature = hmac.new(self.md5, post_data, digestmod=hashlib.sha256).digest()
sig = self.toHex(signature)
parameters['signature'] = sig
#print parameters
r = requests.post(url=url, data=parameters)
s = r.json()
#print s
return s

 
如果还是没有解决的话就网站内私信我看看问题所在。

******************************************* 原文内容 ***************************************************
 

 官方有API的文档,可是这个文档就像一个草稿一样,两个基本例子都没有。 所以自己摸索一下,自己写一个现成的例子给大家,可以有个参考。 下面的例子亲测成功。 
 
首先看一下官方的API文档:


一、API使用说明

1、请求过程说明

1.1 构造请求数据,用户数据按照Jubi提供的接口规则,通过程序生成签名和要传输给Jubi的数据集合;

1.2 发送请求数据,把构造完成的数据集合通过POST/GET提交的方式传递给Jubi;

1.3 Jubi对请求数据进行处理,服务器在接收到请求后,会首先进行安全校验,验证通过后便会处理该次发送过来的请求;

1.4 返回响应结果数据,Jubi把响应结果以JSON的格式反馈给用户,具体的响应格式,错误代码参见接口部分;

1.5 对获取的返回结果数据进行处理;

2、安全认证

所有的private API都需要经过认证

Api的申请可以到财务中心 -> API,申请得到私钥和公钥,私钥Jubi将不做储存,一旦丢失将无法找回

注意:请勿向任何人泄露这两个参数,这像您的密码一样重要

2.签名机制

每次请求private api 都需要验证签名,发送的参数示例:

$param = array(

amount => 1,

price => 10000,

type => 'buy',

nonce => 141377098123

key => 5zi7w-4mnes-swmc4-egg9b-f2iqw-396z4-g541b

signature => 459c69d25c496765191582d9611028b9974830e9dfafd762854669809290ed82

);

nonce 可以理解为一个递增的整数:http://zh.wikipedia.org/wiki/Nonce

key 是申请到的公钥

signature是签名,是将amount price type nonce key等参数通过'&'字符连接起来通过md5(私钥)为key进行sha256算法加密得到的值.

 


 
 
  
首先聚币的行情是使用网络爬虫获取的,而说明中给出了一系列的参数,你需要做的就是把这些参数填充上去。
 
如果你只是想要获取行情,那么事情容易很多。
    def real_time_ticker(coin):
url = 'https://www.jubi.com/api/v1/ticker/'
try:
data = requests.post(url, data={'coin': coin}).json()

except Exception ,e:
print e
return data

上面代码展示的时候获取实时的行情。委一和买一的价格,数量,和当前成交的数量,价格。
 按照上面的格式,把参数coin填上去,比如要获取泽塔币, real_time_ticker('zet') 就会返回获取的数据。
{u'sell': u'0.179000', u'volume': 21828245.102822, u'buy': u'0.175010', u'last': u'0.179000', u'vol': 108290769.9171, u'high': u'0.289000', u'low': u'0.119141'}

 
 
所有的private API都需要经过认证, 就是说如果你要进行交易,委托,下单,你就需要使用私钥和公钥,并进行一系列的加密。


每次请求private api 都需要验证签名,发送的参数示例:

$param = array(

amount => 1,

price => 10000,

type => 'buy',

nonce => 141377098123

key => 5zi7w-4mnes-swmc4-egg9b-f2iqw-396z4-g541b

signature => 459c69d25c496765191582d9611028b9974830e9dfafd762854669809290ed82

);

nonce 可以理解为一个递增的整数:http://zh.wikipedia.org/wiki/Nonce

key 是申请到的公钥

signature是签名,是将amount price type nonce key等参数通过'&'字符连接起来通过md5(私钥)为key进行sha256算法加密得到的值.


 
 
比如下单:


Trade_add(下单)
Path:/api/v1/trade_add/
Request类型:POST
 
参数
key - API key
signature - signature
nonce - nonce
amount - 购买数量
price - 购买价格
type - 买单或者卖单
coin - 币种简称,例如btc、ltc、xas
id - 挂单ID
result - true(成功), false(失败)
{"result":true, "id":"11"}
 
返回JSON dictionary
id - 挂单ID
result - true(成功), false(失败)
 
返回结果示例:
{"result":true, "id":"11"}
 



首先解决nonce。
 
在维基百科中
在安全工程中,Nonce是一个在加密通信只能使用一次的数字。在认证协议中,它往往是一个随机或伪随机数,以避免重放攻击。Nonce也用于流密码以确保安全。如果需要使用相同的密钥加密一个以上的消息,就需要Nonce来确保不同的消息与该密钥加密的密钥流不同。
 
结合stackoverflow, nonce只是一个12位的随机数。
可以用以下方法获得这个随机数
    def get_nonce(self):
lens=12
return ''.join([str(random.randint(0, 9)) for i in range(lens)])

 聚币中的nonce的位数是12位,所以lens定义为12
 
或者可以直接用时间函数生成:
    def get_nonce_time(self):
lens = 12
curr_stamp = time.time()*100
nonece=int(curr_stamp)
return nonece

 
然后是signature。
signature是签名,是将amount price type nonce key等参数通过'&'字符连接起来通过md5(私钥)为key进行sha256算法加密得到的值.

先把私钥进行md5处理
    def getHash(self,s):
m=hashlib.md5()
m.update(s)
return m.hexdigest()

只要把私钥传入函数getHash就可以得到一个md5处理过的字符串。
 
私钥是聚币网给每个用户分配的字符串,是唯一的,这里假设为private_key=123456789吧,具体是多少,在你的聚币网设置里面可以找到。
sha_256key=self.getHash(private_key)
 
按照要求吧 你要post的数据字符串连起来
nonce=self.get_nonce_time
type='buy'
amount='10000'
key='xxxxxxxxxxx‘ #这个是聚币网给你的公钥,同样在设置里头可以找到
price='10' #你要设置的价格为10
coin='zet'
message = "amount=“+amount+”&nonce="+str(nonce)+"&type="+type+"&key="+key+'&price="+price+"&coin"+coin

signature = hmac.new(sha_256key, message, digestmod=hashlib.sha256).digest()

这样获得signature之后,就可以通过签名来进行post操作。

data_wrap={'nonce':nonce,'key':key_value,'signature':signature}

js=requests.post(url,data=data_wrap).json()

 
如果直接按照上面的代码去获取账户相关信息或者去挂单的话,会返回104的签名错误。 经过不断的排查,发现是signature的字符格式的问题。
 
构造一个str转换格式的函数:
    def toHex(self,str):
lst =
for ch in str:
hv = hex(ord(ch)).replace('0x', '')
if len(hv) == 1:
hv = '0' + hv
lst.append(hv)
return reduce(lambda x, y: x + y, lst)
这个函数的作用就是把原来十六进制格式的字符完全转化成十六进制,把前面的0x去掉,不足2位的补全为2位。
把经过处理的signature进行格式转换后,几次提交,终于发现可以获取到用户的账户信息,进行下单,撤单,等操作。
 
 
 
下面是一个获取账户信息的代码段:
    def getAccount(self):
url='https://www.jubi.com/api/v1/balance/'

nonce_value=self.get_nonce_time()
print nonce_value
key_value=self.public_key
private_key=self.private_key

s='nonce='+str(nonce_value)+'&'+'key='+key_value

print s

#signature是签名,是将amount price type nonce key等参数通过'&'字符连接起来通过md5(私钥)为key进行sha256算法加密得到的值.
md5=self.getHash(private_key)
print md5
print type(md5)

msg=bytes(s).encode('utf-8')
key=bytes(md5).encode('utf-8')
signature =hmac.new(key,msg,digestmod=hashlib.sha256).digest()
print signature
print type(signature)
sig=self.toHex(signature)

print sig
data_wrap={'nonce':nonce_value,'key':key_value,'signature':sig}

print data_wrap

data_en=urllib.urlencode(data_wrap)
req=urllib2.Request(url,data=data_en)
resp=urllib2.urlopen(req).read()
print resp


def toHex(self,str):
lst =
for ch in str:
hv = hex(ord(ch)).replace('0x', '')
if len(hv) == 1:
hv = '0' + hv
lst.append(hv)
return reduce(lambda x, y: x + y, lst)

 
以上的代码运行后返回一下账户信息:
{"uid":123456,"nameauth":1,"moflag":1,"asset":,"btc_balance":0,"btc_lock":0,"drk_balance":0,"drk_lock":0,"blk_balance":0,"blk_lock":0,"vrc_balance":0,"vrc_lock":0,"tfc_balance":0,"tfc_lock":0,"jbc_balance":0,"jbc_lock":0,"ltc_balance":0,"ltc_lock":0,"doge_balance":0,"doge_lock":0,"xpm_balance":0,"xpm_lock":0,"ppc_balance":0,"ppc_lock":0,"wdc_balance":0,"wdc_lock":0,"vtc_balance":0,"vtc_lock":0,"max_balance":0,"max_lock":0,"ifc_balance":0,"ifc_lock":0,"zcc_balance":0,"zcc_lock":0,"zet_balance":0,"zet_lock":0,"eac_balance":0,"eac_lock":0,"fz_balance":0,"fz_lock":0,"skt_balance":0,"skt_lock":0,"plc_balance":0,"plc_lock":0,"mtc_balance":0,"mtc_lock":0,"qec_balance":0,"qec_lock":0,"lkc_balance":10,"lkc_lock":0,"met_balance":0,"met_lock":0,"ytc_balance":0,"ytc_lock":0,"hlb_balance":0,"hlb_lock":0,"game_balance":0,"game_lock":0,"rss_balance":0,"rss_lock":0,"rio_balance":0,"rio_lock":0,"ktc_balance":0,"ktc_lock":0,"pgc_balance":0,"pgc_lock":0,"mryc_balance":0,"mryc_lock":0,"eth_balance":0,"eth_lock":0,"etc_balance":0,"etc_lock":0,"dnc_balance":0,"dnc_lock":0,"gooc_balance":0,"gooc_lock":0,"xrp_balance":0,"xrp_lock":0,"nxt_balance":0,"nxt_lock":0,"lsk_balance":0,"lsk_lock":0,"xas_balance":0,"xas_lock":0,"peb_balance":0,"peb_lock":0,"nhgh_balance":0,"nhgh_lock":0,"xsgs_balance":0,"xsgs_lock":0,"ans_balance":0,"ans_lock":0,"bts_balance":0,"bts_lock":0,"cny_balance":0,"cny_lock":0}











 
聚币网个人邀请码:
514330
 
还没注册可以拿去用,对于我而言可以拿到你们交易费用的50%,不过一般交易费除非是超级大户,一般散户都很少。千分之一的交易手续费。
 
欢迎一起讨论:
Email:weigesysu@qq.com

 原创内容,转载请注明出处
http://30daydo.com/article/181 
 

python 获取 中国证券网 的公告

python爬虫李魔佛 发表了文章 • 11 个评论 • 14452 次浏览 • 2016-06-30 15:45 • 来自相关话题

中国证券网: http://ggjd.cnstock.com/
这个网站的公告会比同花顺东方财富的早一点,而且还出现过早上中国证券网已经发了公告,而东财却拿去做午间公告,以至于可以提前获取公告提前埋伏。
 
现在程序自动把抓取的公告存入本网站中:http://30daydo.com/news.php 
每天早上8:30更新一次。
 
生成的公告保存在stock/文件夹下,以日期命名。 下面脚本是循坏检测,如果有新的公告就会继续生成。
 
默认保存前3页的公告。(一次过太多页会被网站暂时屏蔽几分钟)。 代码以及使用了切换header来躲避网站的封杀。
 
修改
getInfo(3) 里面的数字就可以抓取前面某页数据
 
 




__author__ = 'rocchen'
# working v1.0
from bs4 import BeautifulSoup
import urllib2, datetime, time, codecs, cookielib, random, threading
import os,sys


def getInfo(max_index_user=5):
stock_news_site =
"http://ggjd.cnstock.com/gglist/search/ggkx/"

my_userAgent = [
'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50',
'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50',
'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0',
'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)',
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)',
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1',
'Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1',
'Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; en) Presto/2.8.131 Version/11.11',
'Opera/9.80 (Windows NT 6.1; U; en) Presto/2.8.131 Version/11.11',
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Maxthon 2.0)',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11',
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; 360SE)',
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SE 2.X MetaSr 1.0; SE 2.X MetaSr 1.0; .NET CLR 2.0.50727; SE 2.X MetaSr 1.0)']
index = 0
max_index = max_index_user
num = 1
temp_time = time.strftime("[%Y-%m-%d]-[%H-%M]", time.localtime())

store_filename = "StockNews-%s.log" % temp_time
fOpen = codecs.open(store_filename, 'w', 'utf-8')

while index < max_index:
user_agent = random.choice(my_userAgent)
# print user_agent
company_news_site = stock_news_site + str(index)
# content = urllib2.urlopen(company_news_site)
headers = {'User-Agent': user_agent, 'Host': "ggjd.cnstock.com", 'DNT': '1',
'Accept': 'text/html, application/xhtml+xml, */*', }
req = urllib2.Request(url=company_news_site, headers=headers)
resp = None
raw_content = ""
try:
resp = urllib2.urlopen(req, timeout=30)

except urllib2.HTTPError as e:
e.fp.read()
except urllib2.URLError as e:
if hasattr(e, 'code'):
print "error code %d" % e.code
elif hasattr(e, 'reason'):
print "error reason %s " % e.reason

finally:
if resp:
raw_content = resp.read()
time.sleep(2)
resp.close()

soup = BeautifulSoup(raw_content, "html.parser")
all_content = soup.find_all("span", "time")

for i in all_content:
news_time = i.string
node = i.next_sibling
str_temp = "No.%s \n%s\t%s\n---> %s \n\n" % (str(num), news_time, node['title'], node['href'])
#print "inside %d" %num
#print str_temp
fOpen.write(str_temp)
num = num + 1

#print "index %d" %index
index = index + 1

fOpen.close()


def execute_task(n=60):
period = int(n)
while True:
print datetime.datetime.now()
getInfo(3)

time.sleep(60 * period)



if __name__ == "__main__":

sub_folder = os.path.join(os.getcwd(), "stock")
if not os.path.exists(sub_folder):
os.mkdir(sub_folder)
os.chdir(sub_folder)
start_time = time.time() # user can change the max index number getInfo(10), by default is getInfo(5)
if len(sys.argv) <2:
n = raw_input("Input Period : ? mins to download every cycle")
else:
n=int(sys.argv[1])
execute_task(n)
end_time = time.time()
print "Total time: %s s." % str(round((end_time - start_time), 4))


 
github:https://github.com/Rockyzsu/cnstock
  查看全部
中国证券网: http://ggjd.cnstock.com/
这个网站的公告会比同花顺东方财富的早一点,而且还出现过早上中国证券网已经发了公告,而东财却拿去做午间公告,以至于可以提前获取公告提前埋伏。
 
现在程序自动把抓取的公告存入本网站中:http://30daydo.com/news.php 
每天早上8:30更新一次。
 
生成的公告保存在stock/文件夹下,以日期命名。 下面脚本是循坏检测,如果有新的公告就会继续生成。
 
默认保存前3页的公告。(一次过太多页会被网站暂时屏蔽几分钟)。 代码以及使用了切换header来躲避网站的封杀。
 
修改
getInfo(3) 里面的数字就可以抓取前面某页数据
 
 

公告.PNG
__author__ = 'rocchen'
# working v1.0
from bs4 import BeautifulSoup
import urllib2, datetime, time, codecs, cookielib, random, threading
import os,sys


def getInfo(max_index_user=5):
stock_news_site =
"http://ggjd.cnstock.com/gglist/search/ggkx/"

my_userAgent = [
'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50',
'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50',
'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0',
'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)',
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)',
'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1',
'Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1',
'Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; en) Presto/2.8.131 Version/11.11',
'Opera/9.80 (Windows NT 6.1; U; en) Presto/2.8.131 Version/11.11',
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Maxthon 2.0)',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11',
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; 360SE)',
'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SE 2.X MetaSr 1.0; SE 2.X MetaSr 1.0; .NET CLR 2.0.50727; SE 2.X MetaSr 1.0)']
index = 0
max_index = max_index_user
num = 1
temp_time = time.strftime("[%Y-%m-%d]-[%H-%M]", time.localtime())

store_filename = "StockNews-%s.log" % temp_time
fOpen = codecs.open(store_filename, 'w', 'utf-8')

while index < max_index:
user_agent = random.choice(my_userAgent)
# print user_agent
company_news_site = stock_news_site + str(index)
# content = urllib2.urlopen(company_news_site)
headers = {'User-Agent': user_agent, 'Host': "ggjd.cnstock.com", 'DNT': '1',
'Accept': 'text/html, application/xhtml+xml, */*', }
req = urllib2.Request(url=company_news_site, headers=headers)
resp = None
raw_content = ""
try:
resp = urllib2.urlopen(req, timeout=30)

except urllib2.HTTPError as e:
e.fp.read()
except urllib2.URLError as e:
if hasattr(e, 'code'):
print "error code %d" % e.code
elif hasattr(e, 'reason'):
print "error reason %s " % e.reason

finally:
if resp:
raw_content = resp.read()
time.sleep(2)
resp.close()

soup = BeautifulSoup(raw_content, "html.parser")
all_content = soup.find_all("span", "time")

for i in all_content:
news_time = i.string
node = i.next_sibling
str_temp = "No.%s \n%s\t%s\n---> %s \n\n" % (str(num), news_time, node['title'], node['href'])
#print "inside %d" %num
#print str_temp
fOpen.write(str_temp)
num = num + 1

#print "index %d" %index
index = index + 1

fOpen.close()


def execute_task(n=60):
period = int(n)
while True:
print datetime.datetime.now()
getInfo(3)

time.sleep(60 * period)



if __name__ == "__main__":

sub_folder = os.path.join(os.getcwd(), "stock")
if not os.path.exists(sub_folder):
os.mkdir(sub_folder)
os.chdir(sub_folder)
start_time = time.time() # user can change the max index number getInfo(10), by default is getInfo(5)
if len(sys.argv) <2:
n = raw_input("Input Period : ? mins to download every cycle")
else:
n=int(sys.argv[1])
execute_task(n)
end_time = time.time()
print "Total time: %s s." % str(round((end_time - start_time), 4))


 
github:https://github.com/Rockyzsu/cnstock
 

python 批量获取色影无忌 获奖图片

python爬虫李魔佛 发表了文章 • 6 个评论 • 11144 次浏览 • 2016-06-29 16:41 • 来自相关话题

色影无忌上的图片很多都可以直接拿来做壁纸的,而且发布面不会太广,基本不会和市面上大部分的壁纸或者图片素材重复。 关键还没有水印。 这么良心的图片服务商哪里找呀~~
 

 





 
不多说,直接来代码:#-*-coding=utf-8-*-
__author__ = 'rocky chen'
from bs4 import BeautifulSoup
import urllib2,sys,StringIO,gzip,time,random,re,urllib,os
reload(sys)
sys.setdefaultencoding('utf-8')
class Xitek():
    def __init__(self):
        self.url="http://photo.xitek.com/"
        user_agent="Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)"
        self.headers={"User-Agent":user_agent}
        self.last_page=self.__get_last_page()


    def __get_last_page(self):
        html=self.__getContentAuto(self.url)
        bs=BeautifulSoup(html,"html.parser")
        page=bs.find_all('a',class_="blast")
        last_page=page[0]['href'].split('/')[-1]
        return int(last_page)


    def __getContentAuto(self,url):
        req=urllib2.Request(url,headers=self.headers)
        resp=urllib2.urlopen(req)
        #time.sleep(2*random.random())
        content=resp.read()
        info=resp.info().get("Content-Encoding")
        if info==None:
            return content
        else:
            t=StringIO.StringIO(content)
            gziper=gzip.GzipFile(fileobj=t)
            html = gziper.read()
            return html

    #def __getFileName(self,stream):


    def __download(self,url):
        p=re.compile(r'href="(/photoid/\d+)"')
        #html=self.__getContentNoZip(url)

        html=self.__getContentAuto(url)

        content = p.findall(html)
        for i in content:
            print i

            photoid=self.__getContentAuto(self.url+i)
            bs=BeautifulSoup(photoid,"html.parser")
            final_link=bs.find('img',class_="mimg")['src']
            print final_link
            #pic_stream=self.__getContentAuto(final_link)
            title=bs.title.string.strip()
            filename = re.sub('[\/:*?"<>|]', '-', title)
            filename=filename+'.jpg'
            urllib.urlretrieve(final_link,filename)
            #f=open(filename,'w')
            #f.write(pic_stream)
            #f.close()
        #print html
        #bs=BeautifulSoup(html,"html.parser")
        #content=bs.find_all(p)
        #for i in content:
        #    print i
        '''
        print bs.title
        element_link=bs.find_all('div',class_="element")
        print len(element_link)
        k=1
        for href in element_link:

            #print type(href)
            #print href.tag
        '''
        '''
            if href.children[0]:
                print href.children[0]
        '''
        '''
            t=0

            for i in href.children:
                #if i.a:
                if t==0:
                    #print k
                    if i['href']
                    print link

                        if p.findall(link):
                            full_path=self.url[0:len(self.url)-1]+link
                            sub_html=self.__getContent(full_path)
                            bs=BeautifulSoup(sub_html,"html.parser")
                            final_link=bs.find('img',class_="mimg")['src']
                            #time.sleep(2*random.random())
                            print final_link
                    #k=k+1
                #print type(i)
                #print i.tag
                #if hasattr(i,"href"):
                    #print i['href']
                #print i.tag
                t=t+1
                #print "*"

        '''

        '''
            if href:
                if href.children:
                    print href.children[0]
        '''
            #print "one element link"



    def getPhoto(self):

        start=0
        #use style/0
        photo_url="http://photo.xitek.com/style/0/p/"
        for i in range(start,self.last_page+1):
            url=photo_url+str(i)
            print url
            #time.sleep(1)
            self.__download(url)

        '''
        url="http://photo.xitek.com/style/0/p/10"
        self.__download(url)
        '''
        #url="http://photo.xitek.com/style/0/p/0"
        #html=self.__getContent(url)
        #url="http://photo.xitek.com/"
        #html=self.__getContentNoZip(url)
        #print html
        #'''
def main():
    sub_folder = os.path.join(os.getcwd(), "content")
    if not os.path.exists(sub_folder):
        os.mkdir(sub_folder)
    os.chdir(sub_folder)
    obj=Xitek()
    obj.getPhoto()


if __name__=="__main__":
    main()








下载后在content文件夹下会自动抓取所有图片。 (色影无忌的服务器没有做任何的屏蔽处理,所以脚本不能跑那么快,可以适当调用sleep函数,不要让服务器压力那么大)
 
已经下载好的图片:





 
 
github: https://github.com/Rockyzsu/fetchXitek   (欢迎前来star) 查看全部
色影无忌上的图片很多都可以直接拿来做壁纸的,而且发布面不会太广,基本不会和市面上大部分的壁纸或者图片素材重复。 关键还没有水印。 这么良心的图片服务商哪里找呀~~
 

 

色影无忌_副本.png

 
不多说,直接来代码:
#-*-coding=utf-8-*-
__author__ = 'rocky chen'
from bs4 import BeautifulSoup
import urllib2,sys,StringIO,gzip,time,random,re,urllib,os
reload(sys)
sys.setdefaultencoding('utf-8')
class Xitek():
    def __init__(self):
        self.url="http://photo.xitek.com/"
        user_agent="Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)"
        self.headers={"User-Agent":user_agent}
        self.last_page=self.__get_last_page()


    def __get_last_page(self):
        html=self.__getContentAuto(self.url)
        bs=BeautifulSoup(html,"html.parser")
        page=bs.find_all('a',class_="blast")
        last_page=page[0]['href'].split('/')[-1]
        return int(last_page)


    def __getContentAuto(self,url):
        req=urllib2.Request(url,headers=self.headers)
        resp=urllib2.urlopen(req)
        #time.sleep(2*random.random())
        content=resp.read()
        info=resp.info().get("Content-Encoding")
        if info==None:
            return content
        else:
            t=StringIO.StringIO(content)
            gziper=gzip.GzipFile(fileobj=t)
            html = gziper.read()
            return html

    #def __getFileName(self,stream):


    def __download(self,url):
        p=re.compile(r'href="(/photoid/\d+)"')
        #html=self.__getContentNoZip(url)

        html=self.__getContentAuto(url)

        content = p.findall(html)
        for i in content:
            print i

            photoid=self.__getContentAuto(self.url+i)
            bs=BeautifulSoup(photoid,"html.parser")
            final_link=bs.find('img',class_="mimg")['src']
            print final_link
            #pic_stream=self.__getContentAuto(final_link)
            title=bs.title.string.strip()
            filename = re.sub('[\/:*?"<>|]', '-', title)
            filename=filename+'.jpg'
            urllib.urlretrieve(final_link,filename)
            #f=open(filename,'w')
            #f.write(pic_stream)
            #f.close()
        #print html
        #bs=BeautifulSoup(html,"html.parser")
        #content=bs.find_all(p)
        #for i in content:
        #    print i
        '''
        print bs.title
        element_link=bs.find_all('div',class_="element")
        print len(element_link)
        k=1
        for href in element_link:

            #print type(href)
            #print href.tag
        '''
        '''
            if href.children[0]:
                print href.children[0]
        '''
        '''
            t=0

            for i in href.children:
                #if i.a:
                if t==0:
                    #print k
                    if i['href']
                    print link

                        if p.findall(link):
                            full_path=self.url[0:len(self.url)-1]+link
                            sub_html=self.__getContent(full_path)
                            bs=BeautifulSoup(sub_html,"html.parser")
                            final_link=bs.find('img',class_="mimg")['src']
                            #time.sleep(2*random.random())
                            print final_link
                    #k=k+1
                #print type(i)
                #print i.tag
                #if hasattr(i,"href"):
                    #print i['href']
                #print i.tag
                t=t+1
                #print "*"

        '''

        '''
            if href:
                if href.children:
                    print href.children[0]
        '''
            #print "one element link"



    def getPhoto(self):

        start=0
        #use style/0
        photo_url="http://photo.xitek.com/style/0/p/"
        for i in range(start,self.last_page+1):
            url=photo_url+str(i)
            print url
            #time.sleep(1)
            self.__download(url)

        '''
        url="http://photo.xitek.com/style/0/p/10"
        self.__download(url)
        '''
        #url="http://photo.xitek.com/style/0/p/0"
        #html=self.__getContent(url)
        #url="http://photo.xitek.com/"
        #html=self.__getContentNoZip(url)
        #print html
        #'''
def main():
    sub_folder = os.path.join(os.getcwd(), "content")
    if not os.path.exists(sub_folder):
        os.mkdir(sub_folder)
    os.chdir(sub_folder)
    obj=Xitek()
    obj.getPhoto()


if __name__=="__main__":
    main()








下载后在content文件夹下会自动抓取所有图片。 (色影无忌的服务器没有做任何的屏蔽处理,所以脚本不能跑那么快,可以适当调用sleep函数,不要让服务器压力那么大)
 
已经下载好的图片:

色影无忌2_副本1.png

 
 
github: https://github.com/Rockyzsu/fetchXitek   (欢迎前来star)

抓取 知乎日报 中的 大误 系类文章,生成电子书推送到kindle

python爬虫李魔佛 发表了文章 • 0 个评论 • 4255 次浏览 • 2016-06-12 08:52 • 来自相关话题

无意中看了知乎日报的大误系列的一篇文章,之后就停不下来了,大误是虚构故事,知乎上神人虚构故事的功力要高于网络上的很多写手啊!! 看的欲罢不能,不过还是那句,手机屏幕太小,连续看几个小时很疲劳,而且每次都要联网去看。 
 
所以写了下面的python脚本,一劳永逸。 脚本抓取大误从开始到现在的所有文章,并推送到你自己的kindle账号。
 




# -*- coding=utf-8 -*-
__author__ = 'rocky @ www.30daydo.com'
import urllib2, re, os, codecs,sys,datetime
from bs4 import BeautifulSoup
# example https://zhhrb.sinaapp.com/index.php?date=20160610
from mail_template import MailAtt
reload(sys)
sys.setdefaultencoding('utf-8')

def save2file(filename, content):
filename = filename + ".txt"
f = codecs.open(filename, 'a', encoding='utf-8')
f.write(content)
f.close()


def getPost(date_time, filter_p):
url = 'https://zhhrb.sinaapp.com/index.php?date=' + date_time
user_agent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)"
header = {"User-Agent": user_agent}
req = urllib2.Request(url, headers=header)
resp = urllib2.urlopen(req)
content = resp.read()
p = re.compile('<h2 class="question-title">(.*)</h2></br></a>')
result = re.findall(p, content)
count = -1
row = -1
for i in result:
#print i
return_content = re.findall(filter_p, i)

if return_content:
row = count
break
#print return_content[0]
count = count + 1
#print row
if row == -1:
return 0
link_p = re.compile('<a href="(.*)" target="_blank" rel="nofollow">')
link_result = re.findall(link_p, content)[row + 1]
print link_result
result_req = urllib2.Request(link_result, headers=header)
result_resp = urllib2.urlopen(result_req)
#result_content= result_resp.read()
#print result_content

bs = BeautifulSoup(result_resp, "html.parser")
title = bs.title.string.strip()
#print title
filename = re.sub('[\/:*?"<>|]', '-', title)
print filename
print date_time
save2file(filename, title)
save2file(filename, "\n\n\n\n--------------------%s Detail----------------------\n\n" %date_time)

detail_content = bs.find_all('div', class_='content')

for i in detail_content:
#print i
save2file(filename,"\n\n-------------------------answer -------------------------\n\n")
for j in i.strings:

save2file(filename, j)

smtp_server = 'smtp.126.com'
from_mail = sys.argv[1]
password = sys.argv[2]
to_mail = 'jinweizsu@kindle.cn'
send_kindle = MailAtt(smtp_server, from_mail, password, to_mail)
send_kindle.send_txt(filename)


def main():
sub_folder = os.path.join(os.getcwd(), "content")
if not os.path.exists(sub_folder):
os.mkdir(sub_folder)
os.chdir(sub_folder)


date_time = '20160611'
filter_p = re.compile('大误.*')
ori_day=datetime.date(datetime.date.today().year,01,01)
t=datetime.date(datetime.date.today().year,datetime.date.today().month,datetime.date.today().day)
delta=(t-ori_day).days
print delta
for i in range(delta):
day=datetime.date(datetime.date.today().year,01,01)+datetime.timedelta(i)
getPost(day.strftime("%Y%m%d"),filter_p)
#getPost(date_time, filter_p)

if __name__ == "__main__":
main()




github: https://github.com/Rockyzsu/zhihu_daily__kindle
 
上面的代码可以稍作修改,就可以抓取瞎扯或者深夜食堂的系列文章。
 
附福利:
http://pan.baidu.com/s/1kVewz59
所有的知乎日报的大误文章。(截止2016/6/12日) 查看全部
无意中看了知乎日报的大误系列的一篇文章,之后就停不下来了,大误是虚构故事,知乎上神人虚构故事的功力要高于网络上的很多写手啊!! 看的欲罢不能,不过还是那句,手机屏幕太小,连续看几个小时很疲劳,而且每次都要联网去看。 
 
所以写了下面的python脚本,一劳永逸。 脚本抓取大误从开始到现在的所有文章,并推送到你自己的kindle账号。
 

大误.JPG
# -*- coding=utf-8 -*-
__author__ = 'rocky @ www.30daydo.com'
import urllib2, re, os, codecs,sys,datetime
from bs4 import BeautifulSoup
# example https://zhhrb.sinaapp.com/index.php?date=20160610
from mail_template import MailAtt
reload(sys)
sys.setdefaultencoding('utf-8')

def save2file(filename, content):
filename = filename + ".txt"
f = codecs.open(filename, 'a', encoding='utf-8')
f.write(content)
f.close()


def getPost(date_time, filter_p):
url = 'https://zhhrb.sinaapp.com/index.php?date=' + date_time
user_agent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)"
header = {"User-Agent": user_agent}
req = urllib2.Request(url, headers=header)
resp = urllib2.urlopen(req)
content = resp.read()
p = re.compile('<h2 class="question-title">(.*)</h2></br></a>')
result = re.findall(p, content)
count = -1
row = -1
for i in result:
#print i
return_content = re.findall(filter_p, i)

if return_content:
row = count
break
#print return_content[0]
count = count + 1
#print row
if row == -1:
return 0
link_p = re.compile('<a href="(.*)" target="_blank" rel="nofollow">')
link_result = re.findall(link_p, content)[row + 1]
print link_result
result_req = urllib2.Request(link_result, headers=header)
result_resp = urllib2.urlopen(result_req)
#result_content= result_resp.read()
#print result_content

bs = BeautifulSoup(result_resp, "html.parser")
title = bs.title.string.strip()
#print title
filename = re.sub('[\/:*?"<>|]', '-', title)
print filename
print date_time
save2file(filename, title)
save2file(filename, "\n\n\n\n--------------------%s Detail----------------------\n\n" %date_time)

detail_content = bs.find_all('div', class_='content')

for i in detail_content:
#print i
save2file(filename,"\n\n-------------------------answer -------------------------\n\n")
for j in i.strings:

save2file(filename, j)

smtp_server = 'smtp.126.com'
from_mail = sys.argv[1]
password = sys.argv[2]
to_mail = 'jinweizsu@kindle.cn'
send_kindle = MailAtt(smtp_server, from_mail, password, to_mail)
send_kindle.send_txt(filename)


def main():
sub_folder = os.path.join(os.getcwd(), "content")
if not os.path.exists(sub_folder):
os.mkdir(sub_folder)
os.chdir(sub_folder)


date_time = '20160611'
filter_p = re.compile('大误.*')
ori_day=datetime.date(datetime.date.today().year,01,01)
t=datetime.date(datetime.date.today().year,datetime.date.today().month,datetime.date.today().day)
delta=(t-ori_day).days
print delta
for i in range(delta):
day=datetime.date(datetime.date.today().year,01,01)+datetime.timedelta(i)
getPost(day.strftime("%Y%m%d"),filter_p)
#getPost(date_time, filter_p)

if __name__ == "__main__":
main()




github: https://github.com/Rockyzsu/zhihu_daily__kindle
 
上面的代码可以稍作修改,就可以抓取瞎扯或者深夜食堂的系列文章。
 
附福利:
http://pan.baidu.com/s/1kVewz59
所有的知乎日报的大误文章。(截止2016/6/12日)

kindle收不到python推送的附件,但是同邮件的客户端可以。求助。

回复

python李魔佛 回复了问题 • 2 人关注 • 1 个回复 • 419 次浏览 • 2019-04-08 10:03 • 来自相关话题

RuntimeWarning: More than 20 figures have been opened.

回复

python李魔佛 回复了问题 • 1 人关注 • 1 个回复 • 6000 次浏览 • 2018-04-12 12:40 • 来自相关话题

真像雪球和知乎啊,这种是用python开发的后台吗,是用的什么框架呢

回复

默认分类kflyddn 回复了问题 • 3 人关注 • 3 个回复 • 3748 次浏览 • 2018-04-02 14:52 • 来自相关话题

运行python requests/urllib2/urllib3 需要sudo/root权限,为什么?

回复

python李魔佛 回复了问题 • 1 人关注 • 1 个回复 • 2430 次浏览 • 2018-01-10 23:36 • 来自相关话题

dataframe重新设置index

回复

python李魔佛 回复了问题 • 1 人关注 • 1 个回复 • 2098 次浏览 • 2017-05-09 23:05 • 来自相关话题

This probably means that Tcl wasn't installed properly [matplotlib][win7]

回复

python李魔佛 发起了问题 • 1 人关注 • 0 个回复 • 3344 次浏览 • 2017-05-05 17:25 • 来自相关话题

在学习装饰器的过程中遇到的奇怪的输出

回复

python李魔佛 发起了问题 • 1 人关注 • 0 个回复 • 1438 次浏览 • 2017-02-09 18:56 • 来自相关话题

pyautogui 在Windows下遇到 WindowsError: [Error 5] Access is denied. 错误

回复

python李魔佛 发起了问题 • 1 人关注 • 0 个回复 • 1858 次浏览 • 2017-01-16 02:03 • 来自相关话题

使用requests 访问https的网页 返回错误: InsecurePlatformWarning: A true SSLContext object is not available

回复

python李魔佛 回复了问题 • 1 人关注 • 1 个回复 • 4201 次浏览 • 2016-08-13 22:52 • 来自相关话题

datetime weekday (可以返回某天是一个星期的第几天)的源码只有return 0

回复

python李魔佛 回复了问题 • 1 人关注 • 1 个回复 • 1784 次浏览 • 2016-08-07 17:57 • 来自相关话题

python exchange保存备份邮件

python李魔佛 发表了文章 • 0 个评论 • 379 次浏览 • 2019-09-09 10:50 • 来自相关话题

python exchange保存备份邮件
 方便自己平时备份邮件。# -*-coding=utf-8-*-

# @Time : 2019/9/9 9:25
# @File : mail_backup.py
# @Author :
import codecs
import re
import config
import os
from exchangelib import DELEGATE, Account, Credentials, Configuration, NTLM, Message, Mailbox, HTMLBody,FileAttachment,ItemAttachment
from exchangelib.protocol import BaseProtocol, NoVerifyHTTPAdapter


#此句用来消除ssl证书错误,exchange使用自签证书需加上
BaseProtocol.HTTP_ADAPTER_CLS = NoVerifyHTTPAdapter


# 输入你的域账号如example\xxx
cred = Credentials(r'example\xxx', 你的邮箱密码)

configx = Configuration(server='mail.credlink.com', credentials=cred, auth_type=NTLM)
a = Account(
primary_smtp_address='你的邮箱地址', config=configx, autodiscover=False, access_type=DELEGATE
)


for item in a.inbox.all().order_by('-datetime_received')[:100]:
print(item.subject, item.sender, item.unique_body,item.datetime_received)

name = item.subject
name = re.sub('[\/:*?"<>|]', '-', name)
local_path = os.path.join('inbox', name+'.html')
with codecs.open(local_path, 'w','utf-8') as f:
f.write(item.unique_body)

for attachment in item.attachments:
if isinstance(attachment, FileAttachment):
name = attachment.name
name = re.sub('[\/:*?"<>|]','-',name)
local_path = os.path.join('inbox', attachment.name)
with codecs.open(local_path, 'wb') as f:
f.write(attachment.content)
print('Saved attachment to', local_path)

elif isinstance(attachment, ItemAttachment):
if isinstance(attachment.item, Message):
name=attachment.item.subject
name = re.sub('[\/:*?"<>|]', '-', name)
local_path = os.path.join('inbox', 'attachment')
with codecs.open(local_path, 'w') as f:
f.write(attachment.item.body)
原创文章,
转载请注明出处
http://30daydo.com/article/534
  查看全部
python exchange保存备份邮件
 方便自己平时备份邮件。
# -*-coding=utf-8-*-

# @Time : 2019/9/9 9:25
# @File : mail_backup.py
# @Author :
import codecs
import re
import config
import os
from exchangelib import DELEGATE, Account, Credentials, Configuration, NTLM, Message, Mailbox, HTMLBody,FileAttachment,ItemAttachment
from exchangelib.protocol import BaseProtocol, NoVerifyHTTPAdapter


#此句用来消除ssl证书错误,exchange使用自签证书需加上
BaseProtocol.HTTP_ADAPTER_CLS = NoVerifyHTTPAdapter


# 输入你的域账号如example\xxx
cred = Credentials(r'example\xxx', 你的邮箱密码)

configx = Configuration(server='mail.credlink.com', credentials=cred, auth_type=NTLM)
a = Account(
primary_smtp_address='你的邮箱地址', config=configx, autodiscover=False, access_type=DELEGATE
)


for item in a.inbox.all().order_by('-datetime_received')[:100]:
print(item.subject, item.sender, item.unique_body,item.datetime_received)

name = item.subject
name = re.sub('[\/:*?"<>|]', '-', name)
local_path = os.path.join('inbox', name+'.html')
with codecs.open(local_path, 'w','utf-8') as f:
f.write(item.unique_body)

for attachment in item.attachments:
if isinstance(attachment, FileAttachment):
name = attachment.name
name = re.sub('[\/:*?"<>|]','-',name)
local_path = os.path.join('inbox', attachment.name)
with codecs.open(local_path, 'wb') as f:
f.write(attachment.content)
print('Saved attachment to', local_path)

elif isinstance(attachment, ItemAttachment):
if isinstance(attachment.item, Message):
name=attachment.item.subject
name = re.sub('[\/:*?"<>|]', '-', name)
local_path = os.path.join('inbox', 'attachment')
with codecs.open(local_path, 'w') as f:
f.write(attachment.item.body)

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

random.randint的用法

python李魔佛 发表了文章 • 0 个评论 • 440 次浏览 • 2019-08-01 16:31 • 来自相关话题

random.randint的用法:
from random import randint

randint(0,1)
Out[25]: 1

randint(0,1)
Out[26]: 1

randint(0,1)
Out[27]: 1

randint(0,1)
Out[28]: 1

randint(0,1)
Out[29]: 0

randint(0,1)
Out[30]: 1
random.randint(a,b)
 
输出的整数范围包含a和b,和之间的整数
  查看全部
random.randint的用法:
from random import randint

randint(0,1)
Out[25]: 1

randint(0,1)
Out[26]: 1

randint(0,1)
Out[27]: 1

randint(0,1)
Out[28]: 1

randint(0,1)
Out[29]: 0

randint(0,1)
Out[30]: 1

random.randint(a,b)
 
输出的整数范围包含a和b,和之间的整数
 

python执行shell命令时报错: -/bin/sh: 命令:not found的解决办法

Linux李魔佛 发表了文章 • 0 个评论 • 811 次浏览 • 2019-07-29 15:13 • 来自相关话题

file='test.txt'
cmd = f'rsync -av {file} root@10.18.6.46:/home/cjw/'

p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE,executable="/bin/bash")
output, error = p.communicate()
if p.returncode != 0:
print("Error while running - %s" % cmd)
print(error)
print(output) 
用sublime3 运行的时候一直报错。
后来发现,这个是sublime3的运行环境问题, 直接用shell执行 python main.py 执行上面的代码,命令可以正常运行。
/bin/sh: 1: rsync: not found 查看全部
     file='test.txt'
cmd = f'rsync -av {file} root@10.18.6.46:/home/cjw/'

p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE,executable="/bin/bash")
output, error = p.communicate()
if p.returncode != 0:
print("Error while running - %s" % cmd)
print(error)
print(output)
 
用sublime3 运行的时候一直报错。
后来发现,这个是sublime3的运行环境问题, 直接用shell执行 python main.py 执行上面的代码,命令可以正常运行。
/bin/sh: 1: rsync: not found

exchange_declare() got an unexpected keyword argument 'type'

python李魔佛 发表了文章 • 0 个评论 • 271 次浏览 • 2019-07-16 14:40 • 来自相关话题

In new version of pika, now it is using 
exchange_type instead of type
 
credentials = pika.PlainCredentials('admin','admin')
connection = pika.BlockingConnection(pika.ConnectionParameters('192.168.1.101',5672,'/',credentials))

channel = connection.channel()

channel.exchange_declare(exchange='logs',exchange_type='fanout') 查看全部
In new version of pika, now it is using 
exchange_type instead of type
 
	credentials = pika.PlainCredentials('admin','admin')
connection = pika.BlockingConnection(pika.ConnectionParameters('192.168.1.101',5672,'/',credentials))

channel = connection.channel()

channel.exchange_declare(exchange='logs',exchange_type='fanout')

twisted reactor运行后,添加了addBoth函数,但是还是无法停止

python李魔佛 发表了文章 • 0 个评论 • 416 次浏览 • 2019-07-11 09:43 • 来自相关话题

代码如下:
  from scrapy.selector import Selector

def get_response_callback(content):
txt = str(content,encoding='utf-8')
resp = Selector(text=txt)
title = resp.xpath('//title/text()').extract_first()
print(title)

@defer.inlineCallbacks
def task():
url = 'http://www.baidu.com'
d=getPage(url.encode('utf-8'))
d.addCallback(get_response_callback)
yield d

def done():
reactor.stop()

def done1(*args,**kwargs):
reactor.stop()

task_list =
for i in range(4):
d=task()
task_list.append(d)

dd = defer.DeferredList(task_list)

dd.addBoth(done)

reactor.run()
上面的代码是无法停止的,如果使用的是 
dd.addBoth(done)
 
done函数的定义是没有参数的。 
 
而使用另一个done函数带参数的done(*args,**kwargs)
是可以正常退出的,done里面写了reactor.stop() 函数
 
原创文章
转载请注明出处:
http://30daydo.com/article/509
  查看全部
代码如下:
 
	from scrapy.selector import Selector

def get_response_callback(content):
txt = str(content,encoding='utf-8')
resp = Selector(text=txt)
title = resp.xpath('//title/text()').extract_first()
print(title)

@defer.inlineCallbacks
def task():
url = 'http://www.baidu.com'
d=getPage(url.encode('utf-8'))
d.addCallback(get_response_callback)
yield d

def done():
reactor.stop()

def done1(*args,**kwargs):
reactor.stop()

task_list =
for i in range(4):
d=task()
task_list.append(d)

dd = defer.DeferredList(task_list)

dd.addBoth(done)

reactor.run()

上面的代码是无法停止的,如果使用的是 
dd.addBoth(done)
 
done函数的定义是没有参数的。 
 
而使用另一个done函数带参数的done(*args,**kwargs)
是可以正常退出的,done里面写了reactor.stop() 函数
 
原创文章
转载请注明出处:
http://30daydo.com/article/509
 

python3与python2迭代器的写法的区别

python李魔佛 发表了文章 • 0 个评论 • 302 次浏览 • 2019-06-26 11:22 • 来自相关话题

大部分相同,只是python2里面需要实现在类中实现next()方法,而python3里面需要实现__next__()方法。
 
附一个例子:
def iter_demo():

class DefineIter(object):

def __init__(self,length):
self.length = length
self.data = range(self.length)
self.index=0

def __iter__(self):
return self


def __next__(self):

if self.index >=self.length:
# return None
raise StopIteration

d = self.data[self.index]*50
self.index =self.index + 1

return d

a = DefineIter(10)
print(type(a))
for i in a:
print(i) 查看全部
大部分相同,只是python2里面需要实现在类中实现next()方法,而python3里面需要实现__next__()方法。
 
附一个例子:
def iter_demo():

class DefineIter(object):

def __init__(self,length):
self.length = length
self.data = range(self.length)
self.index=0

def __iter__(self):
return self


def __next__(self):

if self.index >=self.length:
# return None
raise StopIteration

d = self.data[self.index]*50
self.index =self.index + 1

return d

a = DefineIter(10)
print(type(a))
for i in a:
print(i)

PyCharm 快捷键快速插入当前时间

python李魔佛 发表了文章 • 0 个评论 • 435 次浏览 • 2019-06-26 09:18 • 来自相关话题

个人觉得这是一个非常常用的功能,不过需要自定义实现。
 
方式
通过 Live Template 快速添加时间

步骤
1、添加一个 Template Group 命名为 Common
2、添加一个 Live Template 设置如下
Abbreviation: time
Description : current time
Template Text: $time$

Edit Variables -> Expresssion : date("yyyy-MM-dd HH:mm:ss")



3、让设置生效
Define->Everywhere

4、使用
输入 time 后 按下tab键 就能转换为当前时间了
  查看全部
个人觉得这是一个非常常用的功能,不过需要自定义实现。
 
方式
通过 Live Template 快速添加时间

步骤
1、添加一个 Template Group 命名为 Common
2、添加一个 Live Template 设置如下
Abbreviation: time
Description : current time
Template Text: $time$

Edit Variables -> Expresssion : date("yyyy-MM-dd HH:mm:ss")



3、让设置生效
Define->Everywhere

4、使用
输入 time 后 按下tab键 就能转换为当前时间了

 

conda无法在win10下用命令行切换虚拟环境

python李魔佛 发表了文章 • 0 个评论 • 568 次浏览 • 2019-06-11 10:04 • 来自相关话题

虚拟环境已经安装好了
然后在PowerShell下运行activate py2,没有任何反应。(powershell是win7后面系统的增强命令行)
后来使用系统原始的cmd命令行,在运行里面敲入cmd,然后重新执行activate py2,问题得到解决了。
原因是兼容问题。 查看全部
虚拟环境已经安装好了
然后在PowerShell下运行activate py2,没有任何反应。(powershell是win7后面系统的增强命令行)
后来使用系统原始的cmd命令行,在运行里面敲入cmd,然后重新执行activate py2,问题得到解决了。
原因是兼容问题。

requests直接post图片文件

python爬虫李魔佛 发表了文章 • 0 个评论 • 377 次浏览 • 2019-05-17 16:32 • 来自相关话题

代码如下:
file_path=r'9927_15562445086485238.png'
file=open(file_path, 'rb').read()
r=requests.post(url=code_url,data=file)
print(r.text) 查看全部
代码如下:
    file_path=r'9927_15562445086485238.png'
file=open(file_path, 'rb').read()
r=requests.post(url=code_url,data=file)
print(r.text)

python的mixin类

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

A mixin is a limited form of multiple inheritance.
 
maxin类似多重继承的一种限制形式:
 关于Python的Mixin模式

像C或C++这类语言都支持多重继承,一个子类可以有多个父类,这样的设计常被人诟病。因为继承应该是个”is-a”关系。比如轿车类继承交通工具类,因为轿车是一个(“is-a”)交通工具。一个物品不可能是多种不同的东西,因此就不应该存在多重继承。不过有没有这种情况,一个类的确是需要继承多个类呢?

答案是有,我们还是拿交通工具来举例子,民航飞机是一种交通工具,对于土豪们来说直升机也是一种交通工具。对于这两种交通工具,它们都有一个功能是飞行,但是轿车没有。所以,我们不可能将飞行功能写在交通工具这个父类中。但是如果民航飞机和直升机都各自写自己的飞行方法,又违背了代码尽可能重用的原则(如果以后飞行工具越来越多,那会出现许多重复代码)。怎么办,那就只好让这两种飞机同时继承交通工具以及飞行器两个父类,这样就出现了多重继承。这时又违背了继承必须是”is-a”关系。这个难题该怎么破?

不同的语言给出了不同的方法,让我们先来看下Java。Java提供了接口interface功能,来实现多重继承:public abstract class Vehicle {
}

public interface Flyable {
public void fly();
}

public class FlyableImpl implements Flyable {
public void fly() {
System.out.println("I am flying");
}
}

public class Airplane extends Vehicle implements Flyable {
private flyable;

public Airplane() {
flyable = new FlyableImpl();
}

public void fly() {
flyable.fly();
}
}

现在我们的飞机同时具有了交通工具及飞行器两种属性,而且我们不需要重写飞行器中的飞行方法,同时我们没有破坏单一继承的原则。飞机就是一种交通工具,可飞行的能力是是飞机的属性,通过继承接口来获取。

回到主题,Python语言可没有接口功能,但是它可以多重继承。那Python是不是就该用多重继承来实现呢?是,也不是。说是,因为从语法上看,的确是通过多重继承实现的。说不是,因为它的继承依然遵守”is-a”关系,从含义上看依然遵循单继承的原则。这个怎么理解呢?我们还是看例子吧。
class Vehicle(object):
pass

class PlaneMixin(object):
def fly(self):
print 'I am flying'

class Airplane(Vehicle, PlaneMixin):
pass

可以看到,上面的Airplane类实现了多继承,不过它继承的第二个类我们起名为PlaneMixin,而不是Plane,这个并不影响功能,但是会告诉后来读代码的人,这个类是一个Mixin类。所以从含义上理解,Airplane只是一个Vehicle,不是一个Plane。这个Mixin,表示混入(mix-in),它告诉别人,这个类是作为功能添加到子类中,而不是作为父类,它的作用同Java中的接口。

使用Mixin类实现多重继承要非常小心
首先它必须表示某一种功能,而不是某个物品,如同Java中的Runnable,Callable等
 
其次它必须责任单一,如果有多个功能,那就写多个Mixin类然后,它不依赖于子类的实现最后,子类即便没有继承这个Mixin类,也照样可以工作,就是缺少了某个功能。(比如飞机照样可以载客,就是不能飞了^_^) 查看全部
A mixin is a limited form of multiple inheritance.
 
maxin类似多重继承的一种限制形式:
 关于Python的Mixin模式

像C或C++这类语言都支持多重继承,一个子类可以有多个父类,这样的设计常被人诟病。因为继承应该是个”is-a”关系。比如轿车类继承交通工具类,因为轿车是一个(“is-a”)交通工具。一个物品不可能是多种不同的东西,因此就不应该存在多重继承。不过有没有这种情况,一个类的确是需要继承多个类呢?

答案是有,我们还是拿交通工具来举例子,民航飞机是一种交通工具,对于土豪们来说直升机也是一种交通工具。对于这两种交通工具,它们都有一个功能是飞行,但是轿车没有。所以,我们不可能将飞行功能写在交通工具这个父类中。但是如果民航飞机和直升机都各自写自己的飞行方法,又违背了代码尽可能重用的原则(如果以后飞行工具越来越多,那会出现许多重复代码)。怎么办,那就只好让这两种飞机同时继承交通工具以及飞行器两个父类,这样就出现了多重继承。这时又违背了继承必须是”is-a”关系。这个难题该怎么破?

不同的语言给出了不同的方法,让我们先来看下Java。Java提供了接口interface功能,来实现多重继承:
public abstract class Vehicle {
}

public interface Flyable {
public void fly();
}

public class FlyableImpl implements Flyable {
public void fly() {
System.out.println("I am flying");
}
}

public class Airplane extends Vehicle implements Flyable {
private flyable;

public Airplane() {
flyable = new FlyableImpl();
}

public void fly() {
flyable.fly();
}
}


现在我们的飞机同时具有了交通工具及飞行器两种属性,而且我们不需要重写飞行器中的飞行方法,同时我们没有破坏单一继承的原则。飞机就是一种交通工具,可飞行的能力是是飞机的属性,通过继承接口来获取。

回到主题,Python语言可没有接口功能,但是它可以多重继承。那Python是不是就该用多重继承来实现呢?是,也不是。说是,因为从语法上看,的确是通过多重继承实现的。说不是,因为它的继承依然遵守”is-a”关系,从含义上看依然遵循单继承的原则。这个怎么理解呢?我们还是看例子吧。
class Vehicle(object):
pass

class PlaneMixin(object):
def fly(self):
print 'I am flying'

class Airplane(Vehicle, PlaneMixin):
pass


可以看到,上面的Airplane类实现了多继承,不过它继承的第二个类我们起名为PlaneMixin,而不是Plane,这个并不影响功能,但是会告诉后来读代码的人,这个类是一个Mixin类。所以从含义上理解,Airplane只是一个Vehicle,不是一个Plane。这个Mixin,表示混入(mix-in),它告诉别人,这个类是作为功能添加到子类中,而不是作为父类,它的作用同Java中的接口。

使用Mixin类实现多重继承要非常小心
  • 首先它必须表示某一种功能,而不是某个物品,如同Java中的Runnable,Callable等

 
  • 其次它必须责任单一,如果有多个功能,那就写多个Mixin类
  • 然后,它不依赖于子类的实现
  • 最后,子类即便没有继承这个Mixin类,也照样可以工作,就是缺少了某个功能。(比如飞机照样可以载客,就是不能飞了^_^)