2 months ago

1.下载字体 arial unicode ms.tff
点击下载
2.放置字体到系统字体库

/home/python/.virtualenvs/py3_ai/lib/python3.5/site-packages/matplotlib/mpl-data/fonts/ttf

3.修改配置文件

gedit /home/python/.virtualenvs/py3_ai/lib/python3.5/site-packages/matplotlib/mpl-data/matplotlibrc
font.family         : sans-serif        

font.sans-serif     : arial unicode ms, Bitstream Vera Sans, Lucida Grande, Verdana, Geneva, Lucid, Arial, Helvetica, Avant Garde, sans-serif

清空matplotlib缓存字体库

/home/python/.cache/matplotlib

重启jupyter notebook

对于mac系统,只需要变更些许路径即可
区别最大的是最后一步

rm -rf ~/.matplotlib/*.*

参考资料:
Mac python3 matplotlib中文乱码解决

 
2 months ago

一.ubuntu环境下安装

在虚拟机中安装TA-Lib遇到各种各样的问题,网上搜出来的解决方案以windows环境居多
ubuntu环境下的解决方案迟迟不见效,经过努力尝试,终于找到解决方案,依次执行以下代码即可

sudo apt-get update
sudo apt-get install python3.6-dev
# 装talib前要先装numpy
python3.6 -m pip install numpy -i https://pypi.doubanio.com/simple
wget http://prdownloads.sourceforge.net/ta-lib/ta-lib-0.4.0-src.tar.gz
tar -xzvf ta-lib-0.4.0-src.tar.gz
cd ta-lib
./configure --prefix=/usr
make
sudo make install
cd ..
pip install TA-Lib

二.mac环境下安装

本以为经过ubuntu的案例,mac会水到渠成,没想到依然诸多问题
还好经过层层探索,终于找到正确打开方式

sudo brew update
sudo brew install python3.6-dev
# 装talib前要先装numpy
python3.6 -m pip install numpy -i https://pypi.doubanio.com/simple
curl -o ta-lib-0.4.0-src.tar.gz 'http://prdownloads.sourceforge.net/ta-lib/ta-lib-0.4.0-src.tar.gz'
tar -xzvf ta-lib-0.4.0-src.tar.gz
cd ta-lib
./configure --prefix=/usr/local # 指定安装目录
make
sudo make install
cd ..
pip install TA-Lib

在安装过程中有一段提示:

make[3]: Nothing to be done for `install-exec-am'.
test -z "/usr/include/ta-lib/" || /usr/local/bin/gmkdir -p "/usr/include/ta-lib/"
gmkdir: cannot create directory ‘/usr/include/ta-lib/’: Operation not permitted

从以下stackoverflow上大神都回答可以看出:基于System Integrity Protection原则,新的软件应该安装在/usr/local

Local installations really should be installed under /usr/local, not directly under /usr. Starting in El Capitan, this is enforced by System Integrity Protection。

结合安装错误提示,直接指定安装目录为/usr/local

三.windows环境下安装

之前一直是pip install TA-Lib,但会遇到库的依赖问题
最好的办法是直接下载包本地安装,但是依然存在依赖问题
而且github上的安装包都是32位版本。
正确的安装方式:

1.下载64位拓展包

找到对应的CPU的和对应的python版本,然后下载whl文件

TA-Lib, a wrapper for the TA-LIB Technical Analysis Library.
TA_Lib‑0.4.17‑cp27‑cp27m‑win32.whl
TA_Lib‑0.4.17‑cp27‑cp27m‑win_amd64.whl
TA_Lib‑0.4.17‑cp34‑cp34m‑win32.whl
TA_Lib‑0.4.17‑cp34‑cp34m‑win_amd64.whl
TA_Lib‑0.4.17‑cp35‑cp35m‑win32.whl
TA_Lib‑0.4.17‑cp35‑cp35m‑win_amd64.whl
TA_Lib‑0.4.17‑cp36‑cp36m‑win32.whl
TA_Lib‑0.4.17‑cp36‑cp36m‑win_amd64.whl
TA_Lib‑0.4.17‑cp37‑cp37m‑win32.whl
TA_Lib‑0.4.17‑cp37‑cp37m‑win_amd64.whl

2.本地pip install xxx即可完成

例如

pip install TA_Lib-0.4.17-cp36-cp36m-win_amd64.whl

参考资料:
ubuntu TA-lib的安装
sudo mkdir in /usr/, Operation not permitted. El Capitan
windows下python3.6 TA-Lib的安装

 
3 months ago

1.哈希 是一种 算法,其作用就是提取数据的 特征码(指纹)

相同的内容 得到 相同的结果
不同的内容 得到 不同的结果

2.Python 中内置有一个名字叫做 hash() 的函数

接收一个 不可变类型 的数据作为 参数
返回 结果是一个 整数
常用不可变数据类型:数字(int,float,bool,complex),字符串,元祖

In[78]: hash("")
Out[78]: 0
In[79]: hash(123)
Out[79]: 123
In[80]: hash(1.23)
Out[80]: 530343892119149569
In[81]: hash(True)
Out[81]: 1
In[82]: hash(False)
Out[82]: 0
In[83]: hash(None)
Out[83]: 671750
In[84]: hash((1,2))
Out[84]: 3713081631934410656

常用可变数据类型:列表,字典

In[75]: hash([])
TypeError: unhashable type: 'list'
In[76]: hash({})
TypeError: unhashable type: 'dict'

有趣的是,对于字符串中嵌套列表或字典,是可哈希的(hashable)

In[85]: hash("[1,2]")
Out[85]: -4689649918355884084
In[86]: hash("{}")
Out[86]: -4204096371636323835

有趣的是,对于元祖中中嵌套列表或字典,是不可哈希的(unhashable)
也许,嵌套了列表和字典的元祖,就不是正宗的元祖了吧

In[88]: hash(({},))
TypeError: unhashable type: 'dict'
In[89]: hash(([],))
TypeError: unhashable type: 'list'

3.hash的关键在于是否有内置方法hash(self)

python3中所有的类都继承自基类Object,里面有内置方法hash(self)
换句话说,python3中的类都是可哈希的(hashable)

In[92]: class A(object):
   ...:     pass
In[93]: hash(A())
Out[93]: -9223363287761547390

4.哈希与字典中的键

在 Python 中,设置字典的 键值对 时,会首先对 key 进行 hash 已决定如何在内存中保存字典的数据,以方便 后续 对字典的操作:增、删、改、查
所以说,考察一个变量是否能作为字典中的键 实际上就是考察这个变量是否可哈希(hashable)

 
3 months ago

enumerate原意是"列举、枚举",enumerate()是python内置函数
对于一个可迭代的(iterable)/可遍历的对象(如列表、字符串),enumerate()将其组成一个索引序列,利用它可以同时获得索引和值,多用于在for循环中得到计数

In[5]: a="i love you"
In[6]: for i,c in enumerate(a):
  ...:     print(i,c)
  ...:     
0 i
1  
2 l
3 o
4 v
5 e
6  
7 y
8 o
9 u

以上代码相当于

In[20]: a="i love you"
In[21]: for i in range(len(a)):
   ...:     print(i,a[i])

明显前一段代码看起来可读性更好

enumerate()的值本身是一个可迭代对象

In[2]: a=[1,2,3,4,5]
In[4]: enumerate(a)
Out[4]: <enumerate at 0x7f50eaad0870>

这个特性可以用于特殊场合
如果要统计文件的行数,可以这样写:

count = len(open(filepath, 'r').readlines())

这种方法简单,但是可能比较慢,当文件比较大时甚至不能工作。

可以利用enumerate():

for index, line in enumerate(open(filepath,'r')): 
    pass
print("文件行数为%d" %(index+1))

参考资料
python enumerate用法总结

 
3 months ago

1.遇到问题

2.python中的队列

队列是一种列表,不同的是队列只能在队尾插入元素,在队首删除元素。队列用于存储按顺序排列的数据
Python提供的所有队列类型 :
先进先出队列 queue.Queue
后进先出队列 queue.LifoQueue (Queue的基础上进行的封装)
优先级队列 queue.PriorityQueue (Queue的基础上进行的封装)
双向队列 queue.deque

3.队列在爬虫中的应用

1)Scrapy中调度器Scheduler --- LIFO(后进先出),实现深度优先

2)自定义爬虫框架调度器Scheduler --- FIFO(先进先出),实现广度优先

# 利用six模块实现py2和py3兼容
from six.moves.queue import Queue


class Scheduler(object):
    '''
    1. 缓存请求对象(Request),并为下载器提供请求对象,实现请求的调度
    2. 对请求对象进行去重判断
    '''
    def __init__(self):
        self.queue = Queue()

    def add_request(self, request):
        '''添加请求对象'''
        self.queue.put(request)

    def get_request(self):
        '''获取一个请求对象并返回'''
        request = self.queue.get()
        return request

4.内容延伸——爬虫中的深度优先与广度优先

默认情况下,scrapy的请求调度队列是LIFO,也就是后进先出的,意味着scrapy默认是深度优先的。
比如总共10个初始请求,假设发起第1个初始请求后,又新增100个请求到了调度器队列中,可能导致其余9个初始请求在这新增的100个请求之后发起。

如上图中10个站点,如果广度优先,先返回的数据将是10个站点的数据,如果他们的数据之间关联不大的话,不利于程序的维护和管理。但如果他们之间的数据关联性较大,那么采用广度优先可能会更好。

但实际应用中,到底使用广度优先还是深度优先,其实并不是绝对的,只有在某种场景可能某种优先会更好。
关键点在于你需要获取的数据的关联性是深度还是广度

比如有这样一个应用场景:获取京东上所有的Iphone手机的名称,价格,销量,店铺,评价数
经过抓包分析,其余字段都可以在列表页抓取,唯有价格字段:需要在详情页抓取详情页url,然后在详情页抓取相应价格
为了获得完整数据,需要在列表页和详情页协同完成,这样数据在深度方向进行关联,适合使用深度算法

此时如果使用广度优先,在列表页获取到商品的不完整信息,详情页和下一页的url
由于先进后出的原则,最开始的商品一直无法获取完整数据,导致数据无法入库,内存一直被占用,影响爬虫执行效率
这样的情形采用广度优先是不合适的

参考资料:
Python数据结构——队列
Python队列
https://www.cnblogs.com/itogo/p/5635629.html
https://blog.csdn.net/linangfs/article/details/78109374

 
3 months ago

1.遇到问题

近期研究python爬虫框架Scarpy源码,尝试自己写成一个框架,忽然发现下面这段代码

from scrapy_plus.conf.settings import SPIDERS, PIPELINES

  class Engine:

      def __init__(self):
          self.spiders = self._auto_import_instances(SPIDERS,isspider=True)
          self.pipelines = self._auto_import_instances(PIPELINES)

      def _auto_import_instances(self,path=[],isspider=False):
            pass

注意看_auto_import_instances这个方法,仿佛是犯了python中先调用,后定义的大忌

2.原因分析

在python中,对于函数的调用,一定要遵循先定义,后调用的顺序
例如下面这个例子是万万不行的

a= func1()

def func1(self):
    print("a")

只有在函数调用函数的情况下,可以不必纠结定义和调用的先后顺序问题,举一个简单的小例子

def func1():
    return func2() #在类里面仿佛就不存在先调用后定义的问题

def func2():
    print("a")

func1()

所以,文章开头的代码是没有问题的

参考资料:
python函数的定义必须在调用前面(函数调用函数例外)

 
3 months ago

作者:妄明
链接:https://www.zhihu.com/question/31160385/answer/231833251
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

富人是结果,而不是原因。

人与人的区别,永远在于他们做了什么,而不是他们怎么看待世界。
执着于如何看待世界,那是小孩子的事情,成年人,重要的是如何参与其中。
能上知乎的,应该都有十多岁了吧,你们身边不可能没见过,那些发财又破产的人吧?
现实中,很多人都有这样几个亲戚,你自己去看看,分析下不就知道。

相信鼓吹富人思维的,基本上都没有富人思维。

时也命也,同一个人,在80年代,可能是被人嫌弃的小摊贩,到了90年代,可能运气好,撞上大运,赶上商业大浪潮,成为了千万富翁。然后,他又可能在千禧年,因为投资错误,破产,一蹶不振。
请问,他是穷人思维,还是富人思维?
拆迁户,可能他真没什么能力,没什么见识,甚至脑子不好使。但他根据爷爷奶奶的穷人教育。舍不得吃,舍不得穿,根本不存在为教育投资,更完全不读书。他就朴素的抠门的存钱,和知乎的富人思维完全反着来,他从不消费,从不花钱买时间,他就买房。然后几十年下来,他有一百套房子,身价几十亿。
请问,他是穷人思维,还是富人思维?富人思维破产的,穷人思维发财暴富的,这世界少了吗?
知乎上,或者说网络上,最蠢的一种思维,就是认为穷人和富人,是因为思维上的不同。

幻想改变下思维,就能暴富,世界上哪有这么简单的事情。

我不像其他人一样故弄玄虚,更不鼓吹什么富人有什么特殊素质,瞎扯淡。
睁眼看看现实,每年多少富过的老板返贫,永远爬不起身来,每年多少什么都不懂的人,靠拆迁致富。
发财根本就是一个小概率事件,跟思维关系真不大。
最后,我告诉一个比富人思维更有价值的东西,发财只有两种方式,收租或者收税。

富人思维只有一条:发财靠收租食利(政策经济红利),发财靠收税(权力税,智商税)

人一天只有24小时,除掉吃饭睡觉,只有10小时,一天能专注的时间,只有3-4小时。
你能做的别人都能做,靠加班,靠努力工作,永远别想发财。
那些富人,发财,从来不是靠什么狗屁思维。
人的差别,永远在于他们做了什么,而不是他们怎么看待世界。
大多数时候,富人之所以成为富人。是因为他们赶上了一个可以收租食利(政策经济红利),可以收税(权力税,智商税)的红利风口,然后就像风口的猪一样,被吹上了天。
他们上了天之后,花钱找了穷人写文章,鼓吹他们是因为思维而致富,然后把更多人赶上歧途。

 
3 months ago

解决pycharm无法开启问题

今天pycharm关闭之后再也无法开启,甚至电脑重启后都无济于事
刚好赶上自己项目比较着急,就在我准备重新从官网下载安装pycharm时,网上一篇答案提醒了我

你下载的应该是官方版的,然后自己加了网上下载的.jar破解插件,并添加了这个插件的路径到.vmoptions文件。
打不开是因为你修改了pycharm路径上的某个文件夹名,导致一开始添加的破解插件路径改变,
你只要在.vmoptions中修改为正确的插件路径即可恢复正常。

突然想起来上周确实做过这个操作,当时是从网上看到的“永久激活pycharm的方法”
但是永久激活失败了,文中介绍的是windows方法,我以为mac不适用,于是没有在意
于是马上到pycharm下的bin文件夹中打开.vmoptions文件,发现最后一行手工添加的.jar破解插件路径敲错了
经过更正后,pycharm启动正常

pycharm永久激活

网上介绍的永久激活方法都是针对windows版本,这里整理一下mac版本

1.下载破解插件

下载https://pan.baidu.com/s/119UO4SGIEW_cxf0LmZzx3w 
并将 JetbrainsCrack-3.1-release-enc.jar 放置到 pycharm安装目录的\bin目录下
(位置可随意,只要配置文件填写相对应的路径,放在这里同时也是为了防止误删除)
mac下查找pycharm安装目录的\bin目录下的方法:finder/应用程序/pycharm/右键/显示包内容/Contents/bin

2.修改启动文件:99%的激活失败都可能是因为这一步不正确

在 Pycharm安装目录的\bin目录下找到 pycharm.vmoptions
以文本格式打开并同时在两个文件最后追加 -javaagent:./JetbrainsCrack-3.1-release-enc.jar,然后保存

3.pycharm中输入激活码

打开pycharm输入激活码窗口Help/Register.../Activation code
复制以下内容输入窗口

 
ThisCrackLicenseId-{
"licenseId":"11011",
"licenseeName":"Wechat",
"assigneeName":"Naked sleep of pig",
"assigneeEmail":"1113449881@qq.com",
"licenseRestriction":"",
"checkConcurrentUse":false,
"products":[
{"code":"II","paidUpTo":"2099-12-31"},
{"code":"DM","paidUpTo":"2099-12-31"},
{"code":"AC","paidUpTo":"2099-12-31"},
{"code":"RS0","paidUpTo":"2099-12-31"},
{"code":"WS","paidUpTo":"2099-12-31"},
{"code":"DPN","paidUpTo":"2099-12-31"},
{"code":"RC","paidUpTo":"2099-12-31"},
{"code":"PS","paidUpTo":"2099-12-31"},
{"code":"DC","paidUpTo":"2099-12-31"},
{"code":"RM","paidUpTo":"2099-12-31"},
{"code":"CL","paidUpTo":"2099-12-31"},
{"code":"PC","paidUpTo":"2099-12-31"}
],
"hash":"2911276/0",
"gracePeriodDays":7,
"autoProlongated":false}

激活成功,可以用到2100年,那一天我们应该都老的敲不动代码了吧

参考资料:
双击PyCharm后鼠标转一圈就没反应了打不开,怎么办?
pyCharm最新2018激活码

 
3 months ago

1.初遇问题

在爬取果壳网详情页时,打算将所有的提问和答案(包括文本和图片)都爬取下来
于是写了一个Xpath语句./p/text()
检查结果后发现对p标签行内内嵌img标签无能为力

<p>林伽是梵文 लिङ्गं (liṅgaṁ) 的音译,其含义为“标志”,“记号”。也有男性生殖器的含义,但是通常特指印度教三大主神之一湿婆 शिव (Śiva) 的生殖器。通常而言,林伽就代表了湿婆,特别是代表精力与不熄之火。下图就是曼谷卧佛寺中的林伽(原图来自wikipedia)<br><img src="https://1-im.guokr.com/nExWJ98SU6v9o5FdT0mm7hnGhbppK5KbxgJXRuqN4ks8AgAAgAMAAEpQ.jpg"></p>

于是使用Xpath|命令增加选择项./p/text() | ./p/img/@src,没有获取到img标签
突然想起某教材说过:使用Xpath是不能以Chrome/右键/检查/Elements里的数据为准
这里显示的数据是服务器针对不同的浏览器做了动态渲染,应当以:Chrome/右键/显示网页源代码里的数据为准
于是得到以下源代码

<p>林伽是梵文 लिङ्गं (liṅgaṁ) 的音译,其含义为“标志”,“记号”。也有男性生殖器的含义,但是通常特指印度教三大主神之一湿婆 शिव (Śiva) 的生殖器。通常而言,林伽就代表了湿婆,特别是代表精力与不熄之火。下图就是曼谷卧佛寺中的林伽(原图来自wikipedia)<br><noscript data-image="https://1-im.guokr.com/nExWJ98SU6v9o5FdT0mm7hnGhbppK5KbxgJXRuqN4ks8AgAAgAMAAEpQ.jpg"><img src="https://1-im.guokr.com/nExWJ98SU6v9o5FdT0mm7hnGhbppK5KbxgJXRuqN4ks8AgAAgAMAAEpQ.jpg"></noscript></p>

源代码中果然多出来一些标签
立马修改Xpath语句./p/text() | ./p/noscript/img/@src,依然没有获取img标签
顿时百思不得其解,于是想到了暴力方法//,直接绕过这些烦人的html标签,./p/text() | ./p//img/@src
结果不言自明,世界顿时安静了好多

我以为问题已经完美解决,直到遇到这个p标签

<p><br><noscript data-image="https://3-im.guokr.com/GtC-qYDT6YAdXVVrHFsFJlc92wdbdRTn18tH5sSRmacABAAABAMAAFBO.png"><img src="https://3-im.guokr.com/GtC-qYDT6YAdXVVrHFsFJlc92wdbdRTn18tH5sSRmacABAAABAMAAFBO.png?imageView2/1/w/600/h/452"></noscript><br>显然林伽和约尼是来源于生殖崇拜。在印度,也经常把林伽和约尼放到一起,如下图(来自wikipedia),即从不熄之火中创生宇宙。</p>

这次直接连文本信息都无法获取到了,于是开启了新的探索里程

2.初识br标签

经过观察发现,前后两段无法完整获取信息的源码中间都有个br标签的存在,问题应该出现在这个标签上
网上一搜索,果然Xpath跟br标签自古就存在深仇大恨


然后认识了following语法:选取文档中当前节点的结束标签之后的所有节点
顺带复习了一下开始标签结束标签的概念

HTML 标签由开始标签和结束标签组成
开始标签是被括号包围的元素名,比如<h1><div><p>
结束标签是被括号包围的斜杠和元素名,比如</h1></div></p>
某些 HTML 元素没有结束标签,比如 <br>(可以理解为<br>本身既是开始标签,又是结束标签)

于是,问题自然迎刃而解了'./p//text() | .//img/@src | ./p/br/following::text()[1]
虽然产生了后遗症————产生了一些空白元素,但是很容易处理

3.xpath语法升级

顺便学习了一个终极语法descendant-or-self:选取当前节点的所有后代元素(子、孙等)以及当前节点本身
于是之前长长的Xpath语句得到终极简化./descendant-or-self::text() | ./p//@src
注意:这里没有用到p标签,而是他的父类标签

*************10.23补充**************

4.正则匹配全部标签内容

然后使用
分割内容(字符串strip方法)
或者直接用正则替换掉所有不想要的内容 re.sub(r"<p> | </p> | <br> | \s ", "")
无意中从冯斗志同学那里学到了整个暴力方法,我只能送一个大写的服!

参考资料:
使用xpath匹配的结果却为空
XPath学习:轴(8)——following-sibling
基本的html标签

 
3 months ago

在网络抓包和数据库过程中,会遇到一些数据让人感觉特别凌乱,比如这样的

{"success":false,"version":"0","errmsg":"FailedToSpellCheck","origtxt":" ","correctxt":" ","origidx":[],"corridx":[]}

这样的数据可读性非常差
哪怕是输入时结构排的好好的

a = {
    "count": 18,
    "start": 0,
    "subject_collection": {"subject_count": 500},
    "subject_collection_items": [{"original_price": "null", "rating": {"count": 4486, "max": 10, "value": 9.5}, "actions": [], "year": "2018"}],
    "total": 500
    }

用Python默认的print打印出来的结果也不尽如人意

{'subject_collection_items': [{'actions': [], 'original_price': 'null', 'year': '2018', 'rating': {'count': 4486, 'value': 9.5, 'max': 10}}], 'count': 18, 'start': 0, 'subject_collection': {'subject_count': 500}, 'total': 500}

观察发现其实这些数据本身是结构化数据,难道没办法结构化输出么

然后了解到pprint命令,俗称“美化打印机”
用法非常友好

from pprint import pprint
test_data = {}
pprint(test_data)

下面举个栗子,小试牛刀

from pprint import pprint

data_test = {"success":False, "version": "0", "errmsg": "FailedToSpellCheck", "origtxt": " ", "correctxt": " ", "origidx":[], "corridx":[]}

print("*"*30,"print","*"*30)
print(data_test)
print("*"*30,"pprint","*"*30)
pprint(data_test)

结果非常完美

****************************** print ******************************
{'correctxt': ' ', 'origidx': [], 'errmsg': 'FailedToSpellCheck', 'success': False, 'corridx': [], 'origtxt': ' ', 'version': '0'}
****************************** pprint ******************************
{'correctxt': ' ',
 'corridx': [],
 'errmsg': 'FailedToSpellCheck',
 'origidx': [],
 'origtxt': ' ',
 'success': False,
 'version': '0'}

参考资料:
[Python标准库]pprint——美观打印数据结构
python pprint模块