Python Notebook
look
think
cover
write
check
目录
[TOC]
#串
IPO
P:算法 是核心
流程图:
顺序
选择 if elif
循环 while/ for
切割/重用:
function:
def, return
传参,局部参数
缺点:无记忆
class:
三段:类名,data,method
动作:instance实例化→
对象:
不存类的method和data,但有自己的data。两段:对象名,data
33个保留字
False假 def定义函数 if如果函数 raise
None del import调用 return返回
True真 elif或如果 in在里面 try尝试函数
and条件和 else否则 is while循环
as except不然 lambda简单的匿名函数 with
assert finally最后执行 nonlocal非本地 yield
break终止 for循环 not反
class类 from从 or或
continue global全局函数 pass空函数
###控制流语句if while for
1.if-elif-else语句
if 判断1:
如果判断1为真,就执行这个
elif 判断2:
如果判断1为假,就会执行elif 如果判断2为真,就执行这个
else:
如果前面全为假,就会执行这个
tip:要有冒号。else后面不用再判断了
2.while-else语句
while 判断:
如果判断为真,就做这个 做啊做啊做
到某时候令判断=假
else:
判断为假,就执行这个
3.for-in循环语句
for 数 in range(最小的数,最大的数,步长):
数从最小的数一直变到最大的数(但不包含最大的数!!),每取一个值执行一次这一块
else:
for结束后执行这个
4.break
跳过最内层循环(包括else的内容)
5.continue
跳过这一次循环中的剩余语句而直接开始下一轮新的循环
函数
def 函数名(变量1,变量2=1):
这里就是函数的内容了。函数其实就是可以随时调用的程序段,比如len()就是内建函数
若不写变量2,它会默认为1
nonlocal 变量
global 变量
参数传递
虚实结合,拷贝
可变对象与不可变对象
类型属于对象,变量没有类型
a=2
2是整数型,是对象;a是变量,没有类型,是对象的引用
可变:list dict
list里的list是指针,list里放的全是指针
a=[1,2]
b=a
则指向同一个list对象,而list是可变对象,所以改b也变a
浅拷贝b=a[:],能拷贝一层,第二层还是指向同一个对象
a=[1,[2,3]]
a=2
b=a
则指向同一个int对象,而int是不可变对象,若b=3,是改变b的指向,则a不变
默认参数必须指向不变对象
函数在定义的时候,默认参数
lang
的值就已经声明了,即空的[]
,也就是说默认参数
指向对象[]
,在多次调用默认参数的情况下,就改变了默认参数
指向对象的数据,默认参数
指向对象的数据变了,下次再调用时,默认参数已经变了,即不再是你希望的空的[]
(4,) 一个数字的tuple
eval()
到数值
pow(x,y)
x^y
变量作用域
local->enclosing->global->built-in
闭包函数(嵌套函数)
函数内套函数,内函数会用到外函数的变量,外函数返回内函数的引用
特征:外函数的变量由于会被用到而不会被轻易释放
注意:每次调用外函数都会创建一个新的内函数的实例对象,但是闭包变量却只有同一个
用途:装饰器:取执行时间;校验输入
js中用闭包实现面向对象
内部变量修改全局变量,用global
但不建议,因为函数的目的就是封装隔离;若需要使用global变量,请使用形参传参
nonlocal 关键字声明 一个变量, 表示这个变量不是局部变量空间的变量,需要向上一层变量空间找这个变量。
函数可以当变量赋值
函数可以当参数传递
递归函数
内部调用自身
必须有基例,也就是有if
写来简单但执行效果差
习惯:
函数名用小写字母加下划线,
大写字母用在类中
函数之间加空行
类
类名首字母大写的驼峰命名法;函数名用动宾短语,全小写,_连接
类之间空两行
attribute属性 是变量
method方法 是函数
继承有副作用
类是模板,对象是类的实例instance
类的四个特性
抽象
封装 信息隐藏 提供接口
继承 在类的基础上定义新类,抽象性降低,实现多态
鸭子类型的多态
鸭子类型:
鸭子测试:当一只鸟走起来像鸭子,游泳像鸭子,叫起来像鸭子,那这只鸟就可以称为鸭子
在python中,一个对象有效的语义,不取决于继承的接口,而取决于它本身的data和method
只要有这个方法我就调用,管你是个啥
靠精确的文档和try/except处理异常
装饰器
@classmethod cls 用类名调用,而不是对象
@staticmethod 静态方法,不关注对象和对象内部属性
像访问属性一样调用方法,方法就像属性了 下跟一个跟属性同名的函数
@property 只读
def age(self,a): if xxx: return "don't!!" else: self.__age=a
@方法名.setter:可写
@方法名.deleter: 可删除
也可用property函数来把已经定义好的setter、deleter等绑定给变量
id()查看内存地址
__dict__
查看类和对象的内部参数
不允许看到对象里面的东西?
dict对象的时候看不到类里的attribute
dict类的时候看不到method里的变量
magic method 内部留的
__str__
__add__
a=3
isinstance(a,int) 判断是否某类型 这个好啊
不提倡用这个判断某对象是否某类(自定义的) 而是直接调用 用try/except处理异常
类的继承(白盒)
1 | class Developer(Employee): def __init__(,,,,): super().__init__(,,,) |
支持但不建议用多重继承
3.x版本从深度优先变为广度优先。先从父代所有类找,再从父代的父代找
多用聚合/组合(黑盒)
类中传进一个新类,则删它无涉
在类的内部新生成一个类,则前者删,后者也无
types模块
def prt():
pass
e1.prt=types.MethodType(prt,e1)
不许用。
__私有变量 方法,不可访问
但可以绕过去,君子约定😑
Turtle库
函数:
setup(width,height,startx,starty)
penup()or pu
pendown()or pd
pensize()
pencolor()
fd()or forward
seth()or setheading
circle(radius,extent=None)
##一些赋值上的点

a='s'
b=['p','a']
c='m'
*b是列表


spam='s'
ham='h'
1 in [0,1] == True: False
因为它等于
1 in [0,1] and [0,1] == True
后者错了
str.split:use the comma to divide the str and return a list, useful.
range(a,b)is from a to b-1 !!!! so ugly.
random库
1 | print( random.randint(1,10) ) # 产生 1 到 10 的一个整数型随机数 print( random.random() ) # 产生 0 到 1 之间的随机浮点数print( random.uniform(1.1,5.4) ) # 产生 1.1 到 5.4 之间的随机浮点数,区间可以不是整数print( random.choice('tomorrow') ) # 从序列中随机选取一个元素print( random.randrange(1,100,2) ) # 生成从1到100的间隔为2的随机整数a=[1,3,5,6,7] # 将序列a中的元素顺序打乱random.shuffle(a) |
数据处理的常用语句
str
str.isnumeric()当所有都是数字,返回True
str.split(sep=None) 分割 按sep分割,返回列表。默认sep为空格
str.replace(old,new[,count]) 替换并返回副本
str.join(i)将i中元素连接,用str分隔
ord() transform str into ascii chr() contrast
print('aaa'.center(50,'-'))在某长度中居中显示
time库
time.clock()计时开始、结束并返回时间差
即覆盖输出 棒呆
==神tm字母可以直接比大小==
文件读写
with open('hahaha.txt','r') as f:
os模块 处理文件和目录
shutil更高级的
GLOB模块 文件路径查找
glob.glob('')
*
匹配多个字符
?
匹配单个字符
[0~9]
eyed3 修改mp3文件标签
import xxx as x
pil库
文档格式转换
CSV
程序之间转移表格数据
纯文本
HTML
Json
爬取的地址: https://api.douban.com/v2/book/isbn/+isbn
豆瓣 根据isbn得图书信息
1 | { "rating": { "max":10, "numRaters":1204, "average":"9.1", "min":0 }, "subtitle":"", "author":["[法]米兰·昆德拉"], "pubdate":"2014-6", "tags": [ {"count":239, "name":"米兰·昆德拉", "title":"米兰·昆德拉"}, {"count":167, "name":"哲学", "title":"哲学"}, {"count":153, "name":"米兰・昆德拉", "title":"米兰・昆德拉"}, {"count":147, "name":"小说", "title":"小说"}, {"count":145, "name":"外国文学", "title":"外国文学"}, {"count":119, "name":"爱情", "title":"爱情"}, {"count":98, "name":"捷克", "title":"捷克"}, {"count":93, "name":"人生", "title":"人生"} ], "origin_title":"", "image":"https://img1.doubanio.com\/view\/subject\/m\/public\/s27471968.jpg", "binding":"精装", "translator":["许钧"], "catalog":"第一部 轻与重\n第二部 灵与肉\n第三部 不解之词\n第四部 灵与肉\n第五部 轻与重\n第六部 伟大的进军\n第七部 卡列宁的微笑\n大写的牧歌与小写的牧歌 弗朗索瓦·里卡尔", "pages":"427", "images":{"small":"https://img1.doubanio.com\/view\/subject\/s\/public\/s27471968.jpg","large":"https://img1.doubanio.com\/view\/subject\/l\/public\/s27471968.jpg","medium":"https://img1.doubanio.com\/view\/subject\/m\/public\/s27471968.jpg"}, "alt":"https:\/\/book.douban.com\/subject\/25900384\/", "id":"25900384", "publisher":"上海译文出版社", "isbn10":"7532766632", "isbn13":"9787532766635", "title":"不能承受的生命之轻", "url":"https:\/\/api.douban.com\/v2\/book\/25900384", "alt_title":"", "author_intro":"", "summary":"《不能承受的生命之轻》是米兰·昆德拉最负盛名的作品。小说描写了托马斯与特丽莎、萨丽娜之间的感情生活。但它不是一个男人和两个女人的三角性爱故事,它是一部哲理小说,小说从“永恒轮回”的讨论开始,把读者带入了对一系列问题的思考中,比如轻与重、灵与肉。\n《不能承受的生命之轻》是一部意象繁复的书,其中装载了多种涵义:被政治化了的社会内涵的揭示、人性考察、个人命运在特定历史与政治语境下的呈现,以及对两性关系本质上的探索等。昆德拉将这些元素糅合在一起,写成一部非同凡响的小说——其中既有隐喻式的哲学思考,也有人的悲欢离合的生命历程的展现。", "series": {"id":"24318", "title":"米兰·昆德拉作品全新系列"}, "price":"46.00元"} |
http://mall.baicizhan.com/ws/search?w=apple
百词斩 单词信息
https://api.douban.com/v2/book/isbn/9787532766635,9787508618852,9787540225353
re 正则表达式 极其强大 有点复杂
可以通过 name 属性获取命名空间的名字:

主文件的命名空间是叫做 'main',而模块的命名空间就是模块名
requests库
put、post一个字符串,自动放到'data'key下
放几个键值对,自动放到'form'(表单)下
patch比put节省带宽,put必须把整个字段写完整,patch只用写需上图中一处错误:
post是不删除的情况下新增
r=requests.get('http://product.dangdang.com/20357456.html')
1 | >> r.encoding |

BeautifulSoup库
可以把html文件输入进来,并且自己整理成好看的格式
soup.select('.xxx')直接nmdcss选择器!!!
from bs4 import BeautifulSoup
大小写敏感,BeautifulSoup是一个类
html文档=标签树=BeautifulSoup类
soup=BeautifulSoup(demo,'html.parser')
解析所有标签格式的源代码
html.parser是自带的html格式的解析器,此外还可以pip一些别的解析器
以下是可以用BeautifulSoup.xx来引用的元素:


如果有多个相同标签,如多个<p>
,只能引用第一个
还可以用soup.a.parent 找标签的父级标签
soup.a.attrs标签属性
soup.a.attrs['class'] 具体某属性
soup.a.name标签名
soup.a.string文字内容 text可以跨越多个标签层次,直接打出里面的文字
这里如果有注释的话,也会直接出来,而没有注释的提示,要区分的话就看type
###html内容遍历
- 上行: .parent .parents(用于遍历)
- 下行:contents(儿子标签,返回列表) children(用于遍历,每次返回一个标签) descendants(所有次级节点?)
- 平行:next_sibling previous_sibling next_siblings previous_siblings
用于遍历的是迭代类型,只能用在for循环中
只有同一个父亲底下的才是平行关系
prettify
bs4将任何文件转换成utf-8
信息标记
让信息具有结构
三种标记形式:
- xml(基于html的通用标记表达形式)繁琐
- json:有类型的键值对,都有双引号;多值用[,]表示;键值对可嵌套,用{}。适合程序
- YAML:键值对,无双引号;所属关系用缩进表达;用-表达并列;|表示整块数据;#是注释。适合阅读
1 | key : valuekey : #comment-value1-value2key : subkey : value |
信息提取方法
- 标签解析器
- 直接搜索
- 结合
find_all():
bs4中有find_all(‘a’) 对标签名字的检索 ,返回所有标签的列表 如果是true 则显示所有标签名
find_all(name,attribute,是否搜索所有子孙=true,string)
还可以用正则表达式搜索不完全名字
可以用标签()
代替标签.find_all()
因为太常用了

中文输出对齐问题
用中文空格chr(12288)来填充
正则表达式
通用的字符串表达框架
在字符串的范围内表达「简洁」与「特征」
操作符
操作符 | 说明 | 例子 |
---|---|---|
. | 单个字符 | |
[] | 字符集,给出单个字符的取值范围 | [abc]表示a、b、c,[a-z]表示a到z单个字符 |
[^] | 非,给出单个字符的排除范围 | |
* | 前一个字符0或多次扩展 | py*:p |
+ | 前一个字符1或多次扩展 | py+:py |
? | 前一个字符0或1次 | py?:p |
| | 左右表达式的任意一个 | abc|def:abc或def |
{m} | 前一个字符m次扩展 | py{2}t:pyyt |
{m,n} | 前一个字符m至n次扩展(包括n) | py{1,2}thon:python |
^ | 匹配字符串的开头 | ^py:字符串开头有py |
$ | 匹配字符串结尾 | |
() | 分组,内部只能用| | (py)(py|yp) |
数字,即[0-9] | ||
单个字符,即[A-Za-z0-9]以及下划线 |
^[A-Za-z]+$
由26个字母组成的字符串
^-?\d+$
整数
^[0-9]*[1-9][0-9]*$
正整数(必须要有1以上)
[1-9]\d{5}
中国境内邮政编码
[\u4e00-\u9fa5]
所有中文
\d{3}-\d{8}|\d{4}-\d{7}
国内电话号码
( ([1-9]?\d|1[0-9]{2}|2[0-4][0-9]|25[0-5]).){3}([0-9]{1,2}|1[0-9]{1,2}|2[0-4][0-9]|25[0-5])
IP地址
re库的功能函数
###re.search(正则表达式,string,flags=0 控制标记)
在字符串中搜索匹配的第一个位置,返回match对象
控制标记:
re.I (IGNORECASE)忽视大小写
re.M (MULTILINE) ^可以将每一行当做开头
re.S(DOTALL) .可以匹配所有字符
###re.match(正则表达式,string,flags=0 控制标记)
从起始位置起匹配正则表达式,返回match对象
###re.findall(正则表达式,string,flags=0)
列表类型返回全部能匹配的串
###re.split(正则表达式,string,maxsplit=0最大分割数,flags=0)
将字符串按匹配结果进行分割(匹配的部分去掉并作为分割之处),返回列表类型
###re.finditer(pattern,string,flags=0)
返回字符串匹配结果的迭代类型,每个迭代元素是match对象
###re.sub(pattern,repl,string,count=0,flags=0)
repl:用来替换的字符串
count:最大替换次数
在字符串中替换所有匹配正则表达式的子串,返回替换后的字符串
###pat=re.compile(pattern,flags=0)
将正则表达式从字符串编译成对象
###match对象
可以用if match: 判断是否匹配
match.group(0)第一个匹配的元素
重要属性
.string 用来匹配的原文本
.re 匹配时用的pattern(是compile之后的)
.pos 开始搜索文本的位置
.endpos 结束搜索文本的位置
重要方法
.group(0) 获得字符串
.start() 匹配字符串在原字符串的开始位置
.end() 结束位置
.span() 返回(.start(),.end())
re的用法
- 一次性操作可以用函数式用法,match=re.search('xx','xx')
- 编译后的多次操作用面向对象用法,pat=re.compile(r'pattern') match=pat.search('string')
表示类型
raw string原生字符串类型 r‘text‘:不包含转义符,这样斜杠就是斜杠,比较方便
贪婪匹配和最小匹配
默认采用贪婪匹配方式,从多个匹配的子串中返回最长的那个
例如,match=re.search(r'PY.*N','PYANBNCNDN')
(PY开头,N结尾)
会得到'PYANBNCNDN'
如果想用最小匹配,只要加个?,即'PY.*?N'
最小匹配操作符:*? +? ?? {m,n}?
序列化
序列化:将数据转成文本存到文件中,方便下次取用
方法:模块cPickle or pickle
pickle.dumps(dictA)='xxxxxxx' 将dictA转换成文本
pickle.dump(dictA,fileF) 将dictA转换成文本并且直接存储进fileF
反序列化:loads or load
还是序列化成json比较好
多进程与多线程
根本区别:进程是操作系统资源分配的基本单位,而线程是任务调度和执行的基本单位
在开销方面:每个进程都有独立的代码和数据空间(程序上下文),程序之间的切换会有较大的开销;线程可以看做轻量级的进程,同一类线程共享代码和数据空间,每个线程都有自己独立的运行栈和程序计数器(PC),线程之间切换的开销小。
所处环境:在操作系统中能同时运行多个进程(程序);而在同一个进程(程序)中有多个线程同时执行(通过CPU调度,在每个时间片中只有一个线程执行)
内存分配方面:系统在运行的时候会为每个进程分配不同的内存空间;而对线程而言,除了CPU外,系统不会为线程分配内存(线程所使用的资源来自其所属进程的资源),线程组之间只能共享资源。
包含关系:没有线程的进程可以看做是单线程的,如果一个进程内有多个线程,则执行过程不是一条线的,而是多条线(线程)共同完成的;线程是进程的一部分,所以线程也被称为轻权进程或者轻量级进程。
多线程的优点:
- 把运行时间长的任务放到后台去处理
- 用户界面可以做进度条来显示处理的进度
- 加快程序速度
- 在一些需要等待的任务实现上很有用,释放珍贵资源,如内存占用
multiprocessing.Pool
用multiprocessing库的Pool类可以创建多进程,
p=Pool(processes=3)
创建3个进程
p.apply_async(runTask, args=(i,))
让进程执行runTask,args是输入的变量们,i是第i个进程
os.getpid()
可获得当前进程的id
p.close()
进程结束 p.join()
进程间同步 这俩好像最后都得写
multip.Queue
用Queue类实现多进程间的通讯
在一开始用q=Queue()
创建Queue类,并且传递给各进程
然后在进程中用q.put(url)
q.get()
读和写东西进去
它俩有两个参数 blocked和timeout 我没看懂
debug
磨刀不误砍柴工
###调试
####输出
assert断言 条件,“不符合条件时抛出的错误”
assertpy 第三方库
可用参数关闭
logging库 可以输出到email、其他文件 等
####文本调试工具
PDB 内置库 pdb.set_trace()然后在这儿随便调变量
IPDB jupyter中
PUDB 可视化全屏调试工具
####图形调试工具
idle
pycharm
微软的一个
测试
单元测试
unitest标准库,pytest第三方库特别火
mock
假对象
FAKER库模拟数据
Vue.js是js的一个库
UI框架
echart 百度给的
动态爬虫
数据处理相关库
Numpy 基于NDarray数据类型
pandas 基于series和dataframe数据类型
scipy高级的机器学习库 很多子模块
matplotlib 画图 但有点丑
tushare 财经数据接口库 返回的绝大部分数据是pandas的dataframe类型
vpython
IO
input() 括号里别乱加东西
eval() 把引号去掉
ls=input().split() 默认以空格分割
a=ls[0]
b=ls[1]
print('a is {}'.format(* **))
数据结构
####基本类型:int float str 都是只读的
强制转换 int()
str.split() strip slice ...都是返回一个copy
####复合类型:list (tuple) set dict
可改 只读 无序无重
list s[::step] 尽可能多掌握 index
for i in ls:
j=ls.index(i) 拿到元素的下标if i in ls[j+1:] …….
tuple: a,b,c (a,b,c) (2,) 只读
dict:{'key':'value'}
list.sort 内部排序 排完还是它本身
sorted(__,key=lambda x:x[0])返回新的
####if elif else while for
s2=s for s in ss if s>2
####函数
def fname(a,b=20,*,**):
return a,b,c
语言简单,难在算法!
XPath
表达式 | 描述 | 例子 |
---|---|---|
nodename | 选取此节点的所有子节点 | classroom |
/ | 从根节点选取 | /classroom |
// | 选择任意位置的某个节点 | //student |
. | 选取当前节点 | |
.. | 选取当前的父节点 | |
@ | 选取属性 | //@name |
谓语:用来选取某个特定节点
用法:方括号
- 第n个元素 [n]
- 最后一个 [last()]
- 倒数第二个[last()-1]
- 前两个[position()<3]
- 拥有属性name的所有student元素 //student[@name]
- 拥有属性name为Zhu的所有student元素 //student[@name='Zhu']
通配符:*
任意元素
多条路径:|
//div/ul[@class='show']
string(.)
CSS选择器
::attr(href)
选择href属性



div:contains("str")
文本包含了str的div
Scrapy
1 | import scrapyclass |
scrapy runspider somefile.py -o xx.csv
start_urls
作为初始链接,并默认把parse()
作为回调函数
在parse中用css选择器获得目标url,并注册parse_question()
作为目标url的回调函数
command line
scrapy crawl xxxspider -s JOBDIR=job1
可以让任务随时中断又恢复,按ctrl+c就中断,下次再点开这个就继续
--help
version
version -v
startproject xxx
创建一个工程,包括创建一系列文件结构
genspider xxx xxx.com
general spider在一个工程中创建一个爬虫,可产生多个爬虫,名字不同
list
查看本工程中有哪些spider
view url
用浏览器查看当前爬下来的网页
parse url
解析,用工程中写好的parse来解析url
shell
首先执行scrapy shell url
进入,然后常用的是response
对象,用response.css('h a::text').extract()
直接看到东西有没有
runspider
运行一个自包含的爬虫 不用这个,用crawl
bench
基准测试,看scrapy有否安装成功
main kits
###Spider
类
定义了爬取、追踪、提取网站数据的全过程
属性:
name、allowed_domains、start_urls、
custom_settings个性化设置,会覆盖全局settings.py
中的设置
crawler抓取器,spider会绑定在上面
settings配置实例,包含project中所有配置变量
logging日志实例
方法
from_crawler() 创建spiders
start_requests() 生成初始requests
make_requests_from_url(url) 根据url生成一个request
parse(response)解析网页内容
self.logger.info('xxx')记录日志
closed(reason) 关闭spider时使用
子类
CrawlSpider XMLFeedSpider CSVFeedSpider SitemapSpider
Selecter
类
extract_first(default='not found')
可以解决没找到值而终止循环的问题
Item
类
完整定义:
1 | import scrapyclass Product(scrapy.Item): |
Item Pipeline
类
1 | from scrapy.exceptions |
启用Item Pipeline:在settings中设置:
1 | ITEM_PIPELINES = { 'myproject.pipelines.PricePipeline': 300, 'myproject.pipelines.DuplicatesPipeline': 800 # pipeline : 优先级(0~1000,小的先)} |
Feed Exports
类
保存为csv:
writeToCsv.py
1 | import csv from PROJECT_NAME import settings class WriteToCsv(object): def process_item(self, item, spider): writer = csv.writer(open(settings.csv_file_path, 'a'), lineterminator='\n') writer.writerow([item[key] for key in item.keys()]) return item |
settings.py
1 | ITEM_PIPELINES = { 'project.pipelines_path.writeToCsv.WriteToCsv' : A_NUMBER_HIGHER_THAN_ALL_OTHER_PIPELINES} csv_file_path = PATH_TO_CSV |
main object
Requests
object
class scrapy.http.Requests(url,[callback,method='GET',headers,body,cookies,meta,encoding='utf-8',priority=0,don't_filter=False,errback])
copy() 返回一个和原requests一模一样的
replace() 返回一个可以自己定制的
return scrapy.Request(url,meta={'theitem': item})
item = response.meta['theitem']
可以在两个parse 函数中传递item对象
重要子类:FormRequest 用来实现登录 参数:url,[formdata]
登录的例子:
1 | import scrapyclass LoginSpider(scrapy.spider): name = 'xxx' start_urls = ['xxx'] def parse(self,response): return scrapy.FormRequest.from_response( response, formdata={'username':'xxx','password':'xxx'}, callback=self.after_login ) def after_login(self,response): #check login succeed before going on if 'authontication failed' in response.body: self.logger.error('Login failed') return #continue.... |
Response
对象
一般不实例化,只是使用,是Request返回的一个对象
urljoin(url)一般从网页中抽取的都是相对链接,用这个生成绝对链接
inner service
logging
import logging
logging.warning('xxx')
logging.log(logging.WARNING,'xxx')
但在scrapy中,scrapy.Spider类已经内置了logger类,而MySpider又会继承它,所以直接用self.logger.info('xxx')
就行
还可以在settings中配置logger,主要有LOG_FILE
确定log文件,这个一设置,就会产生日志文件了
1 | divs=response.css('xxx')if not divs: self.logger.info('Page error. {}'.format(url)) |
1 | try: item['xx']=xxx;except Exception,e: print('Error:',e) |
Stats Collector
Sending Email
import:from scrapy.mail import Mailsender
start:mailer=MailSender(host,from,user,password,port)
ormailer=MailSender.from_settings(settings)
use:mailer.send(to=['xxx@163.com'],subject='xxx',body='xxx',cc=['xx@a.com'])
settings:MAIL_FROM MAIL_HOST MAIL_PORT MAIL_USER MAIL_PASS MAIL_TLS MAIL_SSL
Architecture


下载图片
使用内置的pipeline。在settings中写:
1 | ITEM_PIPELINES = {'scrapy.pipelines.images.ImagePipeline':1}IMAGES_URLS_FIELD = 'xxx' # the name of the image's url field in the itemIMAGES_STORE = r'.' # 存储在当前路径 |
proxy
爬取西刺网站上的ip列表,存到csv文件中
一个proxy.py文件~实现对ip的获取和检查
将meta中的proxy填充好,并且在settings中添加proxy相关的middleware,就可以使用了
http: 4 https: 5 {'http': [['110.52.235.222', '9999', 'HTTP'], ['27.155.84.233', '8081', 'HTTP'], ['121.61.2.154', '9999', 'HTTP'], ['116.209.57.232', '9999', 'HTTP']], 'https': [['121.61.2.185', '9999', 'HTTPS'], ['121.61.0.33', '9999', 'HTTPS'], ['110.52.235.154', '9999', 'HTTPS'], ['111.77.197.133', '9999', 'HTTPS'], ['221.224.136.211', '35101', 'HTTPS']]}
selenium
from selenium import webdriver
driver=webdriver.Chrome()
driver.get(url)
driver.page_source
常用属性和方法:
1 | from selenium.webdriver.common.by import By |
- find_element_by_id # ID
- find_elements_by_class_name # class
- find_elements_by_tag_name # 标签名
- find_elements_by_name # name
- find_elements_by_link_text # a标签中的text查找(精确匹配)
- find_elements_by_partial_link_text #a标签中的text查找(部分匹配即可)
- find_elements_by_css_selector # css选择器查找
- find_elements_by_xpath # find_elements_by_xpath("//input"),请翻阅文档
scrapyd
command line:scrapyd
to execute it.
###部署
upload a spider: cd into the local
配置服务器和项目信息, 需要编辑scrapy.cfg文件,添加如下内容
[deploy:主机名]url=http://localhost:6800/
可以用scrapyd-deploy -l
列出所有可用主机target
scrapyd-deploy target主机地址 -p 工程名
我们也可以把项目信息写入到配置文件中,部署时就不用指定项目信息,编辑scrapy.cfg文件,添加项目信息
[deploy:server-douban]url=http://localhost:6800/project=douban-movies
下次部署可以直接执行
$ scrapyd-deploy
###调度
调度工具:curl
shedule api:curl http://localhost:6800/schedule.json -d project=xxx -d spider=somespider
cancel api:curl http://localhost:6800/cancel.json -d project=xxx -d job=之前的任务的id
list:curl http://129.28.28.203/listprojects.json
curl http://129.28.28.203:6800/schedule.json -d project=zhihu -d spider=topicfollower
curl http://129.28.28.203:6800/delproject.json -d project=zhihu
SQLite3
1 | import sqlite3conn = sqlite3.connect('myquotes.db')curr = conn.cursor()curr.execute("""create table quotes_tb( title text, author text, tag text )""")curr.execute("""insert into quote_tb values( xxx,zhu,notag )""")conn.commit()conn.close() |

use sqlite3 in scrapy pipelines:
1 | import sqlite3class SavetoSQLitePipeline(object): def __init__(self): self.create_connection() self.create_table() def create_connection(self): self.conn=sqlite3.connect('mydatabase.db') self.curr=self.conn.cursor() def create_table(self): self.curr.execute("""drop table if exists my_tb""") self.curr.execute("""create table my_tb( aaa text, bbb text, ccc text )""") def process_item(self,item,spider): self.store_db(item) print('Pipeline :'+item['title']) return item def store_db(self,item): self.curr.execute("""insert into my_tb values(?,?,?)""".( item['aaa'], item['bbb'], item['ccc'] )) self.conn.commit() |
Machine Learning
classify
- Supervised Learning: data is labeled and the program learns to predict the output from the input data
- Regression : predict a continuous-valued output.
- Classification: predict a discrete number of values.
- Unsupervised Learning: data is unlabeled and the program learns to recognize the inherent structure in the input data
- Clustering is a common unsupervised machine learning approach that finds patterns and structures in unlabeled data by grouping them into clusters.
scikit-learn
Scikit-learn is a library in Python that provides many unsupervised and supervised learning algorithms. It's built upon some of the technology you might already be familiar with, like NumPy, pandas, and Matplotlib!
As you build robust Machine Learning programs, it's helpful to have all the sklearn
commands all in one place in case you forget.
Linear Regression
Import and create the model:
1 | from sklearn.linear_model import LinearRegressionyour_model = LinearRegression() |
Fit:
1 | your_model.fit(x_training_data, y_training_data) |
.coef_
: contains the coefficients.intercept_
: contains the intercept
Predict:
1 | predictions = your_model.predict(your_x_data) |
.score()
: returns the coefficient of determination R²
Naive Bayes
Import and create the model:
1 | from sklearn.naive_bayes import MultinomialNByour_model = MultinomialNB() |
Fit:
1 | your_model.fit(x_training_data, y_training_data) |
Predict:
1 | # Returns a list of predicted classes - one prediction for every data pointpredictions = your_model.predict(your_x_data)# For every data point, returns a list of probabilities of each classprobabilities = your_model.predict_proba(your_x_data) |
K-Nearest Neighbors
Import and create the model:
1 | from sklearn.neigbors import KNeighborsClassifieryour_model = KNeighborsClassifier() |
Fit:
1 | your_model.fit(x_training_data, y_training_data) |
Predict:
1 | # Returns a list of predicted classes - one prediction for every data pointpredictions = your_model.predict(your_x_data)# For every data point, returns a list of probabilities of each classprobabilities = your_model.predict_proba(your_x_data) |
K-Means
Import and create the model:
1 | from sklearn.cluster import KMeansyour_model = KMeans(n_clusters=4, init='random') |
n_clusters
: number of clusters to form and number of centroids to generateinit
: method for initializationk-means++
: K-Means++ [default]random
: K-Means
random_state
: the seed used by the random number generator [optional]
Fit:
1 | your_model.fit(x_training_data) |
Predict:
1 | predictions = your_model.predict(your_x_data) |
Validating the Model
Import and print accuracy, recall, precision, and F1 score:
1 | from sklearn.metrics import accuracy_score, recall_score, precision_score, f1_scoreprint(accuracy_score(true_labels, guesses))print(recall_score(true_labels, guesses))print(precision_score(true_labels, guesses))print(f1_score(true_labels, guesses)) |
Import and print the confusion matrix:
1 | from sklearn.metrics import confusion_matrixprint(confusion_matrix(true_labels, guesses)) |
Training Sets and Test Sets
1 | from sklearn.model_selection import train_test_splitx_train, x_test, y_train, y_test = train_test_split(x, y, train_size=0.8, test_size=0.2) |
train_size
: the proportion of the dataset to include in the train splittest_size
: the proportion of the dataset to include in the test splitrandom_state
: the seed used by the random number generator [optional]
Matplotlib
##Objects
Figure
:一张布,可以放很多张图
Axes
: 一张图,表示一个数据关系,可以放很多个坐标轴
Axis
: 一个坐标轴
Artist
: 所有可见的东西,包括前面那些,还有文字、标签等等。不能在Axes之间共享
##Input
input type: np.array
or np.ma.masked_array
to convert a pandas.DataFrame
1 | a = pandas.DataFrame(np.random.rand(4,5), columns = list('abcde'))a_asarray = a.values |
and to convert a np.matrix
1 | b = np.matrix([[1,2],[3,4]])b_asarray = np.asarray(b) |
##Backends
If your script depends on a specific backend you can use the use()
function:
1 | import matplotlibmatplotlib.use('PS') # generate postscript output by default |
If you use the use()
function, this must be done before importing matplotlib.pyplot
.
###matplotlib renderers:
Renderer | Filetypes | Description |
---|---|---|
AGG | png | raster graphics -- high quality images using the Anti-Grain Geometry engine |
PS | ps eps | vector graphics -- Postscript output |
vector graphics -- Portable Document Format | ||
SVG | svg | vector graphics -- Scalable Vector Graphics |
Cairo | png ps pdf svg | raster graphics and vector graphics -- using the Cairo graphics library |
Backend | Description |
---|---|
TkAgg | Agg rendering to a Tk canvas (requires TkInter). This backend can be activated in IPython with %matplotlib tk . |
nbAgg | Embed an interactive figure in a Jupyter classic notebook. This backend can be enabled in Jupyter notebooks via %matplotlib notebook . |
Pyplot
Plot
versitile
1 | plt.plot([1, 2, 3, 4]) |
默认输入是y,x会从0开始,自己长。折线图
1 | plt.plot([1, 2, 3, 4], [1, 4, 9, 16]) |
x-y
1 | plt.plot([1, 2, 3, 4], [1, 4, 9, 16], 'ro')plt.axis([0, 6, 0, 20]) |
第三个参数是可选的格式配置参数,默认是'b-' Blue line;现在的'ro'是Red Circle
axis指定x轴范围和y
Pandas
data structure
1. Series
s=pd.Series([1,2,3,4],index=['a','b','c','d']
一维,带标签,可以装任何类型数据。可以用列表转换,也可以重新指定索引s.index()
2. DataFrame
1 | d={'a':[1,2,3], 'b':[4,5,6], 'c':[7,8,9]}df=pd.DataFrame(d,columns=['a','b','c']) |
二维。可以用字典转换.f.columns()
Selection

列名选择
1 | selected_cols = ['2010', '2011', '2012']date_df = df[selected_cols] |
:robot:
Happy Coding!