python web 笔记

这些都是自己学习笔记和一些信得体会,写的比较笼统,不适合看,主要为了纪录

1.当往容器中放类时需要使能够执行深拷贝,提供一个无参数的构造函数,和拷贝构造函数,和等号运数符的重载,深拷贝和浅拷贝的区别主要是当编译器释放指针指向内存时同一块内粗会释放两次,

2.STL算法入门要明确知道每一个算法返回的是一个迭代器还是一个一个函数对象

3.指针类型根据所占用的字节根据操作系统决定

4.数组a[]这样写原因类似*a+n=a[n}=n[a],这样写主要让程序员敲代码更方便

5.char数据类型中ascii码最高到0127,不同类型的指针跳动需要字节相同如char*一次性需要跳动一个字节,int*一次性需要跳动四个字节,当*出值时char*是一个字节的值,而int是四个字节的值,indent缩进的意思,在传统的=号赋值是属于深拷贝,

6.Python中元组不可以修改 ,而数组可以被修改,其他元组和数组都一样

7.当元组含一个元素的时候默认是int类型的如果多个是tuple(元组)类型的,字典是无序的只能按照他的key值寻找他的键值,当用for循环遍历字典所有的键和键值时,键会变成下标索引,

8.地址分为5部分http://...............com/        /     /    路径 ?参数

9.浮动的元素永远不会超过他爹浮动元素回音响到他的弟弟;一个元素想要浮动先看他的哥哥的浮动情况边框融合是融合到自己长宽中html)

10.一个元素想定位position,必须不是static静态定位;想定位参照父亲,如果父亲的定位没打开参照爷爷的,爷爷也没打开参照祖宗的,relative相对自己本身的位置去动,fix定位完全依照浏览器窗体,固定定位

11.js中打印一个函数名是把函数里面的都打出来;this谁调用this就是谁

js中变量定义在方法调用前就可以用,对一个方法没有的属性,如果给这个属性赋值,则添加方法中,其中window是最大包含,没有指明谁调用方法默认是window调用;

12.宏定义就是一个替换的过程,逗号是一个选择的过程,如a=5,6,7;得到a=7;脚本里面不能套脚本,应该是添加脚本标签

13.服务器分为三部分路由:根据不同地址的展现不同界面,数据库或者缓存,界面

14.Python有两个内置的函数,locals() 和globals(),它们提供了基于字典的访问局部和全局变量的方式。

print ("-------Python中的三角函数-------")

15.script  console.log()打印输出。Php  $是定义和使用变量,输出打印print_r。Python  弱类型语言无需定义变量类型,print()输出打印

15.所有从 QObject 或其子类 ( 例如 Qwidget ) 派生的类都能够包含信号和槽。因为信号与槽的连接是通过 QObject 的 connect() 成员函数来实现的。

connect(sender, SIGNAL(signal  sender对象做的动作比如说click), receiver, SLOT(slot  接受者对象做的动作相当于函数调用));

不借助第三个变量交换两个值

a=10;

b=12;
a=b-a; //a=2;b=12
b=b-a; //a=2;b=10
a=b+a; //a=10;b=10

或者

a=5;

b=6;

a=a+b;//a=11

b=a-b;//b=5;

a=a-b;//a=6;

可能出现的问题是a+b可能溢出;

*编程中逐个分析小问题,然后合并成一个大问题;

*for循环和while循环的灵活应用

*一个类中初始化函数为__init__,默认在类中定义方法中必须传self参数,调用的时候默认有

内存五大分区a = 5;

a在栈中    5在常量区中,

*元组与列表的区别就在于,元组是一种不可变序列。元组变量的赋值要在定义时就进行,这就像C语言中的const变量或是C++的引用,定义时赋值之后就不允许有修改。元组存在的意义是:

· 元组在映射中可以作为键使用,因为要保证键的不变性。

· 元组作为很多内置函数和方法的返回值存在。

A = [1,3,4,5,6];

C,*B,D = A;

C 就是,D就是6,B就是345;

*B就是[3,4,5]

b = 6;a = 5;

 

c = 7;

mac = (a if a > b else b) if (a if a > b else b) > c else c;

print(mac);

Mac = 7;

List  排序用sort

字典无序可以排序用sorted

1017

模块

Import的工作机制先找到模块路径翻译成位码,然后加载位码中的数据

位码:编译后的代码

模块导入只有第一次有效

但是重载后可以导入第二次

模块搜索顺序有主目录,python的环境路径;安装目录

模块导入中也可以导入.zip,.c,.cpp,.java的文件后缀

From   模块(a)  import  属性(b);意思是从模块a中引入属性B

From   模块    import   *  引入全部属性

模块的重载再次加载内容改变后的模块

先引入from imp import reload

然后reload(模块);

a = 模块名

动态导入模块exec(import+ a)

Help中可以装类型,类,还有个文件对象

包含一个或多个模块,包就是一个文件夹,文件夹中多一个__init__.py文件

import 模块a  as  名字b,这个是把模块a改名b,解决模块冲突问题

当添加一个包的时候路径不在上面中的时候,可以添加如sys.path.append(路径);

python 3.x里面,// 是地板除,/ 不管两边是不是整数得到的都是小数。

1019:

类名也是对象,类是模块里面的属性,print(lei.__dict__)打印出类中的所有属性方法,类属性用于对改变所有建立的对象都起作用

Print (lei.__base__)打印出父类,duixiang.__class__则是对象属于那个类

Lei.__name__打印类名

if __name__ == "__main__":主要用于测试代码,当本身的代码执行的时候if语句将会成立,当代码文件被别人使用的时候,__name__则等于文件名,

Shelve模块对象序列化

类的扩展:子类对像中调用父类的方法,

代理:子类对象调用父类方法这个方法调用的是子类方法

抽象类必须含有抽象方法

assert和raise  报错提示;

u代表utf8编码,r为正则表达式

状态码   12345,300表示地址重定向

Js对象到jquery对象,$(对象);

jquery对象到js对象,对象[0];

地址中传参数 有三种  默认为path   还有int类型  再有float类型

Form表单的文件直接包含request中

Python  中的数据库链接主要是利用模块pymysql

Db = pymysql.connect(主机名 ,用户名 , 密码 ,数据库名字);

建立游标来执行语句

Cursor = db.cursor();

Python2用MySqldb,python3用pymysql ,如果数据库中数据发生了改变需要cursor.commit();不然不生效

*args可以当作可容纳多个变量组成的list  

感觉**kwargs可以当作容纳多个key和value的dictionary

filter函数是通过一个函数来过滤一个list函数,参数一是一个函数,参数二是一个可迭代的对象,如list,dic,把一个元素传到函数中,如果符合函数规则返回

Example

def is_odd(n):

    return n % 2 == 1

newlist = filter(is_odd, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])

print(newlist)

super() 函数是用于调用父类(超类)的一个方法。

super 是用来解决多重继承问题的,直接用类名调用父类方法在使用单继承的时候没问题,但是如果使用多继承,会涉及到查找

#意思就是把RmSpider的对象转化为父类对象

Js中typeof  是打印出一个变量的数据类型

*kwargs一个星表示传参数的可以传多个,**kwargs同样可以传多个参数但是传入参数的时候需要有对应的变量名如(a = 8,b = 10)

Yield可以生成一个迭代器,而迭代器一次生成一个,yield出现的时候代码会暂停,并记录暂停的位置,当调用next()函数的时候并从纪录的位置开始再走

框架pygame  flask   scrapy django

自学爬虫以来稍作总结,python中的爬虫框架为scrapy,这个框架更好用一点(别人这样说的我也不知道毕竟这是我学的第一个 框架)

在爬虫scrapy中开启item管道主要吧原来的数组包装成字典的形式,目前就知道这些后期再写,

爬虫部署的 先下载了scrapyd模块在dos中运行命令scrapyd命令这时侯在浏览器中localhost:6800 , 可以得到自己部署的站点,然后就是把你的爬虫部署到你的站点上去,在这里就是需要在你的爬虫项目里面的scrapy.cfg文件中的url打开,需要在deploy中加入一个名称(deploy的名称),还要拷贝一个scrapyd-deploy(这个文件主要识别输入的命令)文件到项目中与spider文件夹平级,上述是部署站点,然后是部署项目到你的站点中需要安装scrapy-client文件然后输入命令,scrapyd-deploy <target> -p <project> 
* target就是配置文件的deploy的名称,针对上面的配置就是demo 
* project如果不输就是配置文件中的project

然后就是页面管理自己的爬虫,终端中运行命令python scrapyd-deploy --build 文件名.egg 你的文件名.egg在项目夹中生成一个output.egg文件导入spiderkeeper运行的服务器上就可以管理自己项目了

参考地址:http://blog.csdn.net/u013708440/article/details/53425655

css中要为一些奇数偶数添加不同的样式的时候要用nth-child(2n)偶数,奇数用nth-child(2n+1)

url编码规则:除英文字母,数字和部分符号以外,其他的全部使用百分号+十六进制码值进行编码

js中的事件冒泡中需要利用event.stopPropagation();来阻止事件穿透到下一层,

Django当利用Ajax 请求数据的时候,总是报403的错误

参考博客http://blog.csdn.net/shangliuyan/article/details/7406876

项目的总结:

经历了大约三周的时间,跌跌撞撞的写着项目,废话不不多说,直接纪录自己学的知识,

1. 图片的预览在H5中有自带的filereader()类来定义一个对象,来进行图片的预览功能,具体使用具体百度,还有个方法比较麻烦就是利用windowURL中的createObjectURL但是好像都是利用浏览器的缓存来的

2. 关于预加载的标签添加点击事件的问题,js添加标签后再为此部件添加点击事件然后加入事件队列,如果在之间添加不能实现,然后还有个方法利用delegate委托时间给父标签来判断,这个方法有点麻烦

3. 一个html中不能有相同的id名,id为唯一标识符,

4. 在进行写项目的时候,遇到方法多处用到的时候请把方法进行封装,比如说Ajax请求数据,为了提高代码的健壮性多用if判断,考虑要严谨多方面考虑

5. 分页处理的时候则是利用了插件jquery.twbsPagination.js,但是进行分页的时候难免利用到Ajax请求数据,但是请求数据的时候不能分页的总数不能及时更新,这就要把 装分页的标签动态的删除添加来刷新页面,但是在Ajax中改变标签的时候遇到了类似document.write()写入或者更新标签的的时候会发生死循环刷新页面,比如说insert HTML函数和html()函数,参考博客:http://www.cnblogs.com/dh616854836/articles/2140349.html,我用的方法是在使用js改变标签代码之前添加判断,这个问题只针对我的问题,可能对大家帮助很少,

6. Js中定义变量用var 和不用是一个全局变量一个是局部的,当数据库中一个存放图片字段需要存多个图片地址的时候,可以每个图片地址之间添加分割符进行取出和存入的时候通过字符串的操作对多个图片地址解析来使用,这只是一个方法,js中的indexof()函数判断字符串中是否含有子字符串,没有返回-1,有的话返回下标位置,pop()函数对数组操作是删除所有元素返回最后一个元素,

 

Django基础学习,我感觉 有一个学习的网站自强学堂的基础Django的教程非常好,这里我们主要熟悉的是各个命令,通过pip install Django 直接安装Django ,建立工程的时候利用django-admin startproject projectname 来创建项目,一个说的非常好,一个项目中可以有多个应用,一个应用可以在多个项目中,在项目中建立应用需要在你的项目中打开终端命令执行python manage.py startapp testapp或 django-admin.py startapp app_name; 这样一个基础的Django的项目就完成了,在这里view 和urls就不多说了,建立app的时候一定要吧你的appname加入到INSTALLED_APPS的字典中。

运行项目的命令为 python manage.py runserver IP地址(可以不填默认locahost) 端口号(可以不填默认8000);

python manage.py makemigrations 这个命令是你的models中的数据发生改变需要更新一下吧(还不确定)python manage.py migrate命令把数据改导出生成一个db.splite3文件,如果想导出别的类型的参数给是在后面加相应的参数(python manage.py dumpdata > mysite_all_data.json应该在这里吧记不清了);django链接MySQL数据,在项目setting中的DATABASES中来设置字段ENGINE字段是是使用数据库引擎如django.db.backends.mysql或者django.db.backends.sqlite3

模板的引用需要自己建立templates文件夹来存放HTML,然后需要在setting中的TEMPLATES字典变量中加入templates的路径'DIRS':[os.path.join(BASE_DIR , "templates")],类似这样,BASE_DIR=os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

os.path.abspath(__file__)指的是你这句话在那个文件中写的返回这个文件夹完全路径并且还带这个文件的名字,os.path.dirname()这个意思是返回你文件/文件夹所在的文件夹的路径,关于静态问价就是如js,css,imges,font等文件需要放入你app中文件夹中的static文件夹中,但是前端页面需要用到{% load  static %}的时候需要在setting中加入STATIC_URL = '/static/'变量,如果在项目需要用到全局变量可以在setting中定义然后再引入,

关于django自带的数据库的使用,在你自己的app下有一个model.py的文件,在里面定义你需要的表,定义的格式是一个表就是一个类,类名就是表名,没定义一个变量就是一个字段,格式如id = models.CharField(max_length=100 , primary_key=True); # id,当所有的都建立好后执行命名python manage.py makemigrate 再执行python manage.py migrate,生成你做建立的表

数据库我们建立好了,然后就是使用,当然当你使用那个表先在上面引入from appname.models import tablename,然后利用Queryset API 进行对数据的增删改查等等数据库的操作,具体请看这是自强学堂上的Django基础教程https://code.ziqiangxuetang.com/django/django-models.html

关于自带数据库自定义Field的用法主要是当你表中存一个自己想要的数据类型的时候可以自定义来存放,如list,方法就是自定义一个类来继承models.TextField类,然后填一些规定的内部方法来创建,成功后就像CharField一样来使用这个Field,

# session 设置在setting.py中

SESSION_COOKIE_AGE = 60 * 30 # 30分钟

SESSION_SAVE_EVERY_REQUEST = True

SESSION_EXPIRE_AT_BROWSER_CLOSE = True # 关闭浏览器,则COOKIE失效

关于Django传参数

1 urlpatterns = [

2     url(r'^admin/', admin.site.urls),

3     url(r'^test/', views.test),

4     url(r'^page/(\d+)/(\d+)/', views.div_page),

5 ]

6 def div_page(request,page,page1):

7     print(page,page1)

8     return HttpResponse(page+page1)

如果web需要即使通讯,需要用Django含有dwebsocket模块,web页面也支持这种协议

关于Django的笔记暂时就到这里,以后还会补充,下面是轻量级的flask

Flask

安装flask用pip install flask , 然后建立一个flask的项目,在创建flask的项目的时候不需要命令来创建,直接引用flask中的Flask然后创建app = Flask(__name__)对象,然后路由的定义需要@app.route(/路由名字)然后定义路由执行的函数,route() 装饰器把一个函数绑定到对应的 URL 上。example

from flask import Flask

app = Flask(__name__);

@app.route('/dddd')

def hello():

return "kkkkk";

if __name__ == "__main__":

app.run();

run中可以执行指定的IP和端口app.run(host=0.0.0.0,port=8000 , debug=ture);其中的debug参数是开启调试模式当访问出错的时候不用重启服务器,并且改变的时候会自动检测更新,当产生语法错误的时候服务器会自己中断,还需要自己重启来运行,

关于路由中传参数的问题格式则为/urlname/<variabletype:variablename>如/hello/<int:user_id>,参数类型:int(整型)、float(浮点型)、path(包括“/”的字符串)、string(匹配不包含“/”的字符串)

对于路由被请求的方式则是有路由自己规定的在route()中指定参数methods=[GET,POST],example

@app.route('/login', methods=['GET', 'POST']),默认为GET

当前端请求路由带有form表单数据的时候我们需要用request.form[variablename]俩拿变量如果是文件需要用request.file[filename],但是这样拿数据不太好,如果没有这个名字怎么办呢,所以用searchword = request.args.get('q', '')这一点还没理解好

当返回html文件的时候引用了render_template(”name.html,name=name , title=title)name可以页面传输参数,title可以指定页面标题,当HTML有传入的参数的时候用{{参数}}的方式来解析参数

{%...%}     #运行Jinja2的语句;如简单的for循环

{{…}}      #在页面中打印Jinja2运行的结果

{#...#}     #注释

如果想输入原始的Jinja2语句,而不是作为特殊字符进行解析,可以包含在{%raw%语句{%endraw%}中,更多jinja2模板的用法参考博客http://blog.csdn.net/kikaylee/article/details/53540352

看下面的例子:

 

@app.route('/req5')

def req5():

abort(500)

return '<h1>Test</h1>'

其中abort函数指定返回错误码,交给web来处理,

路由的重定向

@app.route('/redirect')

def redirectTest():

return redirect("/hello")

redirect中的参数可以是路由的名字字符串,也可以是与路由绑定的函数名,也可以是一个url地址,类型均为字符串

关于templates和static文件夹的创建 ,则是和应用同级目录下,利用url_for(函数)可以有效的访问一下路径

当制定api接口返回json数据的时候需要引用from flask import jsonify

Example:@app.route('/mylist')def mylist():

    l = ['xmr', 18]

    return jsonify(l)

关于token当后台登陆成功后生一个token.,然后存放在浏览器的cookie中,服务端存到session中,然后用户每次访问数据和打开网页的时候都携带这token,当服务端验证这个token是否过期,如果过期则从新登陆,不过期返回数据并且更新session的过期时间,token生成的方式,可以是随机字符串,或者时间戳加用户名,来进行机密处理,当登陆成功后可以根据解密然后得到用户名,来识别用户

@app.errorhandler(404)

def pageError(error):

return render_template('404.html')

调用errorhandler路由何以没有url都重定向到这个页面,

关于flask的flash消息闪现,就是向前端页面传一句话,然后利用规定的格式去显示出来(个人理解),给我感觉是不会用的因为感觉麻烦,直接在前端来做提示效果更好吧

app.config.from_object('config'),在项目的同级目录下建立config.py装入配置文件,然后import config,在用上面一句话来加载配置文件,这样做的原因不知道啊

关于g变量的使用,一句话g对象是专门用来保存用户的数据或者其他变量。

g对象在一次请求中的所有的代码的地方,都是可以使用的。

before_first_request:处理第一次请求之前执行。

例如以下代码:

@app.before_first_request

def first_request():

print 'first time request'

before_request:在每次请求之前执行。通常可以用这个装饰器来给视图函数增加一些变量。

例如以下代码:

@app.before_request

def before_request():

    if not hasattr(g,'user'):

teardown_appcontext:不管是否有异常,注册的函数都会在每次请求之后执行。

@app.teardown_appcontext

def teardown(exc=None):

    if exc is None:

        db.session.commit()

    else:

        db.session.rollback()

        db.session.remove()       setattr(g,'user','xxxx')

关于flask蓝图的使用就是把一个大项目功能模块分开多个文件进行编写来提高效率和方便,具体参考知乎https://www.zhihu.com/question/31748237/answer/55313054

贼好理解flask就先理解到这吧

Scrapy

通过pip install Scrapy 来安装爬虫框架,在安装Scrapy的时候还需要下载pywin32的文件。来配合使用,当需要创建一个爬虫的工程的时候需要命令 scrapy startproject projectname

来建立一个项目,一个项目可以建立多个小爬虫来爬取,cd到与spider.py同级目录下然后在shell中运行命令scrapy genspider spidername(小爬虫的名字) domain(域名)来生成一个小爬虫

当生成一个爬虫的时候就可以进行爬虫了,当然有些网站需要在setting中设置header中的cookie来模仿浏览去访问,还有需要把ROBOTSTXT_OBEY = False

这好像是不要遵循一些爬虫的协议,不然不走parse()方法

使用选择器也可以简写为:response.xpath() / response.css(),可以用extract()提取全部,extract_first提取首个,就是说,包含关系用中括号[],从属关系用斜杠 /,在xpath()中,选取标签属性的时候@+属性名如response.xpath('//a/@href').extract()

css()选择器中取出标签的属性用attr(属性名);如response.css('a::attr(href)').extract()

Scrapy 允许使用 .re() 方法正则表达式来提取数据,在parse()方法中得到选择器选择的内容然后,yield(相当于return,如果yield在for循环中每次yield都会执行完yield的代码然后,在次回到这里执行下面的代码,类似迭代生成器)出去了然后item当成了参数进入了items.py 中的process_item(self, item, spider)函数,你可以对item数据进行处理然后打印出来

scrapy response.meta参数必须是个字典类型

中间件的使用,主要是当request请求的时候,中间件类有三个方法分别是process_request(self , request , spider) , process_response(request, response, spider

),

1. process_request 在请求传递给下载器前可以处理请求对象

2. process_response 在响应传递给引擎前处理响应数据

3. process_exception 处理异步调用时发生的异常情况

4. 下面这个图片阐述的非常好a

5. 

6. 1,引擎从Spiders中获取到最初的要爬取的请求(Requests)。

7. 2,引擎安排请求(Requests)到调度器中,并向调度器请求下一个要爬取的请求(Requests)。

8. 3,调度器返回下一个要爬取的请求(Requests)给引擎。

9. 4,引擎将上步中得到的请求(Requests)通过下载器中间件(Downloader Middlewares)发送给下载器(Downloader ),这个过程中下载器中间件(Downloader Middlewares)中的process_request()函数会被调用到。

10. 5,一旦页面下载完毕,下载器生成一个该页面的Response,并将其通过下载中间件(Downloader Middlewares)发送给引擎,这个过程中下载器中间件(Downloader Middlewares)中的process_response()函数会被调用到。

11. 6,引擎从下载器中得到上步中的Response并通过Spider中间件(Spider Middlewares)发送给Spider处理,这个过程中Spider中间件(Spider Middlewares)中的process_spider_input()函数会被调用到。

12. 7,Spider处理Response并通过Spider中间件(Spider Middlewares)返回爬取到的Item及(跟进的)新的Request给引擎,这个过程中Spider中间件(Spider Middlewares)的process_spider_output()函数会被调用到。

13. 8,引擎将上步中Spider处理的其爬取到的Item给Item 管道(Pipeline),将Spider处理的Request发送给调度器,并向调度器请求可能存在的下一个要爬取的请求(Requests)。

14. 9,(从第二步)重复直到调度器中没有更多的请求(Requests)。

15. 当在scrapy中需要用post请求数据的时候,而是利用了from scrapy.http import FormRequest,把post数据包装到url中,然后返回的是一个包装数据的url然后就是利用Request再去请求这个url,然后回调parse函数,在爬取过程中的可能会被ban的情况,这个过程中需要 的就是添加headers,在添加headers中可能参数不一定,所以要去测试需要那些是必须的参数,要么就是利用浏览器驱动去加载一些动态数据,还有一个利用rule规则去提取页面的url 然后去爬取,这个还没仔细看

16. 关于爬出的东西导入文件中是利用feed_export,

想要导出文件首先在setting中设置必须配置有FEED_URI,表示你要导出的路径,导入的地方一般使用两种本地系统或者服务器,如果要是服务器主要写服务器地址,和登陆密码,FEED_FORMAT这是指定要导出的文件类型,FEED_STORAGES_BASE,支持的导出设备的类型,FEED_EXPORT_FIELDS是可以设置字段,FEED_EXPORTERS_BASE,支持的导出的格式,不用设置的话自定义是cvs格式的,scrapy crawl  name -o result.csv 命令是到出文件的命令,如果想要其他格式,后缀名改变,

关于rules规则提取链接这一切是scrapy自动实现的,具体过程是:

 

scrapy crawl spidername开始运行,程序自动使用start_urls构造Request并发送请求,然后调用parse函数对其进行解析,在这个解析过程中使用rules中的规则从html(或xml)文本中提取匹配的链接,通过这个链接再次生成Request,如此不断循环,直到返回的文本中再也没有匹配的链接,或调度器中的Request对象用尽,程序才停止。

 

rules中的规则如果callback没有指定,则使用默认的parse函数进行解析,如果指定了,那么使用自定义的解析函数。

rules的提取链接的规则主要你正则表达想要匹配的内容

 

  如果起始的url解析方式有所不同,那么可以重写CrawlSpider中的另一个函数parse_start_url(self, response)用来解析第一个url返回的Response,但这不是必须的。

 

Rule对象的follow参数的作用是:指定了根据该规则从response提取的链接是否需要跟进。

rule解析规则

引入类

from scrapy.spiders import CrawlSpider, Rule

from scrapy.linkextractors import LinkExtractor

rules: Rule对象的集合,用于匹配目标网站并排除干扰

parse_start_url: 用于爬取起始响应,必须要返回ItemRequest中的一个。

因为rulesRule对象的集合,所以这里也要介绍一下Rule。它有几个参数:link_extractorcallback=Nonecb_kwargs=Nonefollow=Noneprocess_links=Noneprocess_request=None

其中的link_extractor既可以自己定义,也可以使用已有LinkExtractor类,主要参数为:

 

allow:满足括号中“正则表达式”的值会被提取,如果为空,则全部匹配。

deny:与这个正则表达式(或正则表达式列表)不匹配的URL一定不提取。

allow_domains:会被提取的链接的domains

deny_domains:一定不会被提取链接的domains

restrict_xpaths:使用xpath表达式,和allow共同作用过滤链接。还有一个类似的restrict_css

关于分布式,就是一份代码在多个电脑上跑,redis_key,都会从指定的Key中找到request队列然后请求,master上面只跑request的管理,

想要建立一个分布式爬虫项目,

一先建立一个scrapy 的项目,和爬虫

然后修改爬虫的继承关系,继承from scrapy_redis.spiders import RedisSpider

可以重写构造方法,然后super函数转化为父类对象(这一步应该不是必须的吧)

最后就是在setting中设置必须的配置

这个设置是启用自己的调度器

SCHEDULER = "scrapy_redis.scheduler.Scheduler"

启动自己的去重方式

DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"

#最大空闲时间防止分布式爬虫因为等待而关闭,选填

#SCHEDULER_IDLE_BEFORE_CLOSE = 10

#将清除的项目在redis进行处理,一般不填(我think

ITEM_PIPELINES = {

    'scrapy_redis.pipelines.RedisPipeline': 300

}

已设置SCHEDULER_PERSIST = True,爬取结束后,仍自动清空redis库。

#使用优先级调度请求队列 (默认使用)三种任选一个

#SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.PriorityQueue'

#可选用的其它队列

#SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.FifoQueue'

#SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.LifoQueue'

#指定连接到redis时使用的端口和地址(可选)

#REDIS_HOST = 'localhost'

#REDIS_PORT = 6379

#指定用于连接redisURL(可选)

#如果设置此项,则此项优先级高于设置的REDIS_HOST REDIS_PORT

REDIS_URL = 'redis://@localhost:6379'

客服端的爬虫代码都是同一份代码,从而能在队列中拿到不同类型的request而进行解析,因为当yield Request的时候给这个url绑定了规定的回调函数,然后压入队列中,这样每当弹出队列的时候,都能执行相应的回调函数,关于全站爬取就是一个页面的所有url然后进行分类然后分别yield,然后在每个分类的parse回调函数中进行再次分析,或者提取url

爬虫的部署scrapyd

首先安装pip scapyd  scrapyd-client,还有curl来控制爬虫,

然后在scrapy.cfg中配置你的爬虫信息

[deploy:name]

url = http://scrapyd.mydomain.com/api/scrapyd/#scrapy运行的服务器地址

username = john

password = secret

project = project1

version = GIT

然后就是部署自己的项目,在scrapy项目的根目录中与文件.cfg同级目录,执行命令scrapyd-deploy name(这个是.cfg文件中deploy:name),

这样项目就部署到了服务器上面了

然后就是爬虫的api

1、获取状态

http://127.0.0.1:6800/daemonstatus.json

2、获取项目列表

http://127.0.0.1:6800/listprojects.json

3、获取项目下已发布的爬虫列表

http://127.0.0.1:6800/listspiders.json?project=myproject

4、获取项目下已发布的爬虫版本列表

http://127.0.0.1:6800/listversions.json?project=myproject

5、获取爬虫运行状态

http://127.0.0.1:6800/listjobs.json?project=myproject

 6、启动服务器上某一爬虫(必须是已发布到服务器的爬虫)

http://localhost:6800/schedule.json post方式,data={"project":myproject,"spider":myspider}

7、删除某一版本爬虫

http://127.0.0.1:6800/delversion.json post方式,data={"project":myproject,"version":myversion}

8、删除某一工程,包括该工程下的各版本爬虫  

http://127.0.0.1:6800/delproject.jsonpost方式,data={"project":myproject}

 

Mongodb

17. 关于这个非关系数据库的存储,意思就是python字典的存储,而values值是支持多类型,也类似json数据叫bson数据,但是比json数据支持的更多数据类型

18. 文档就类似一个数据,然后keys值是字段,values是值的意思,只是这个值支持的类型更多而已,然而更多的文档就组成了一个集合了,然后也就形成了一个表

19.  什么是原子性,什么是原子性操作?

举个例子:

 

A想要从自己的帐户中转1000块钱到B的帐户里。那个从A开始转帐,到转帐结束的这一个过程,称之为一个事务。在这个事务里,要做如下操作:

 1. 从A的帐户中减去1000块钱。如果A的帐户原来有3000块钱,现在就变成2000块钱了。

 2. 在B的帐户里加1000块钱。如果B的帐户如果原来有2000块钱,现在则变成3000块钱了。如果在A的帐户已经减去了1000块钱的时候,忽然发生了意外,比如停电什么的,导致转帐事务意外终止了,而此时B的帐户里还没有增加1000块钱。那么,我们称这个操作失败了,要进行回滚。回滚就是回到事务开始之前的状态,也就是回到A的帐户还没减1000块的状态,B的帐户的原来的状态。此时A的帐户仍然有3000块,B的帐户仍然有2000块。

我们把这种要么一起成功(A帐户成功减少1000,同时B帐户成功增加1000),要么一起失败(A帐户回到原来状态,B帐户也回到原来状态)的操作叫原子性操作。如果把一个事务可看作是一个程序,它要么完整的被执行,要么完全不执行。这种特性就叫原子性。

 

Python复习

dir() 函数不带参数时,返回当前范围内的变量、方法和定义的类型列表;带参数时,返回参数的属性、方法列表。如果参数包含方法__dir__(),该方法将被调用。如果参数不包含__dir__(),该方法将最大限度地收集参数信息

a = "hhh";

b = help(type(a));

print(b);这样能打印出具体方法的简略信息

lambda 表达式创建简单的函数

创建方式:函数名称(有点像变量名称),lambda(表达式关键字),形式参数,:功能模块f1 = lambda a,b:a + b   #lambda 表达式定义函数

F1是函数名,a,b是参数,a+b,是功能模块,并且返回

 

 

函数装饰器,给一些函数增加功能,但是不改变原来函数的代码,,被装饰的函数有点回调函数的意思,或者理解在调用被装饰函数执勤做那些事和执行完做那些事,比如说纪录这个函数的执行时间和结束时间,或者纪录这个函数执行的日志

#装饰器函数

def zh(sh):     #定义装饰器函数,接收被装饰函数的名称

    def zhshi(a1,a2):   #定义装饰器功能函数,接收被装饰函数的形式参数,注意这里的形式参数可以不给被装饰函数的形式参数一样,但个数要一样

        print("在执行被装饰函数前添加功能")

        r =  sh(a1,a2)  #接收被装饰函数的形式参数并且执行被装饰函数

        print("在执行被装饰函数后添加功能")

        return r    #将被装饰函数返回结果给,装饰器功能函数

    return zhshi    #将装饰器功能函数名称返回给,装饰器函数

 

@zh     #调用执行装饰器

#被装饰函数

def f1(a1,a2):

    a3 = a1 + a2

    return a3

#执行f1函数

s1 = f1(3,5)

print(s1)

# 最后打印结果

# 在执行被装饰函数前添加功能

# 在执行被装饰函数后添加功能

# 8

 

字符串格式化输出常用

# -*- coding:utf8 -*-

tp1 = "i am %s" % ("alex")

print(tp1)

tp2 = "i am %s age %d" % ("alex", 18)

print(tp2)

tp3 = "i am %(name)s age %(age)d" % {"name": "alex", "age": 18}

print(tp3)

tp4 = "percent %.2f" % 99.97623

print(tp4)

tp5 = "i am %(pp).2f" % {"pp": 123.425556, }

print(tp5)

tp6 = "i am %(pp).2f %%" % {"pp": 123.425556, }

print(tp6)

#输出

# i am alex

# i am alex age 18

# i am alex age 18

# percent 99.98

# i am 123.43

# i am 123.43 %

更多看博客http://www.cnblogs.com/adc8868/p/5805258.html

文件、文件夹、压缩包、处理模块shutil

python执行系命令的相关的模块和函数的功能均在 subprocess 模块中实现,并提供了丰富的功能

assert 条件,条件成立就成立继续执行,条件不成立就报错,一般用于测试14

当需要服务器时间的时候在响应头中会有时间可以获得

Csrf攻击与防御解释

http://blog.csdn.net/stpeace/article/details/53512283

Python2和3的区别主要有print由关键字转为了函数,还有input函数,再有就是网路请求模块urllib 和urllib2合成了一个urllib 这是网路请求模块的区别,具体看官方文档去吧,

关于加载模块的路径根据sys.path可以打印出要查询模块所有路径路径,sys.path.append(url)可以添加自己的路径

二、类间的关系判断

isinstance() 判断是否是实例

issubclass() 判断是否是子类

isinstance(c1,Child1)

issubclass(Child1,Parent)

issubclass(Child1,object)

next() 返回迭代器的下一个项目。 iterator - 可迭代对象.  default - 可选,用于设置在没有下一个元素时返回该默认值,如果不设置,又没有下一个元素则会触发 StopIteration 异常。返回对象帮助信息。

关于不用服务器框架搭建一个简单的服务器,主要就是利用socket,当用浏览器访问socket的时候,浏览器的请请求头就会当作数据发给socket的服务器,然后服务端接收的即使请求头然后可以打印出来

Django  BUG :

Django POST请求错误forbidden(403) CSRF verification failed. Request aborted

settings.py 中的MIDDLEWARE_CLASSES 设置下 添加

'django.middleware.csrf.CsrfResponseMiddleware',重新 runserver.   OK

我用的是django1.2.3,当使用session时,也会像上面出错,这时把下面注释掉即可:'django.middleware.csrf.CsrfViewMiddleware',               #这段代码理应注释掉,在使用session的时候(待测试)

2.Session 陷阱:django的session虽然类似字典,但是,如果你直接赋值字典给它会出现丢失数据的状况。原因:请参考 https://docs.djangoproject.com/en/1.8/topics/http/sessions/

当你添加字典到session时候,初次添加会更新session,但是当后面修改字典里面内容时候,不会触发更新session,只更新字典本身,所以会出现字典中某个更新值丢失状况。

解决方法:在settings中设置以下代码,这样在每次request中修改,都会更新session信息。

SESSION_SAVE_EVERY_REQUEST=True

Flask bug

关于flask路由装饰问题,需要在装饰函数加修饰@functools.wraps,不然会返回函数名都是一样的AssertionError: View function mapping is overwriting an existing endpoint function: basedata.wrapper

2.2  Flask-RESTful 使用经验

(Edit)

强制以 utf-8 而不是 Unicode 字符输出

Flask-RESTful 在以 json 格式输出数据时,会把 Unicode 原样输出,而不会自动做编码转换。就可能导致以其他编程语言实现的客户端在数据解析时出现困难。

 

 

 

 

 

 

 

 

 

 

 

 

 

 


# 函数 描述
# acos(x) 返回x的反余弦弧度值。
# asin(x) 返回x的反正弦弧度值。
# atan(x) 返回x的反正切弧度值。
# atan2(y, x) 返回给定的 X 及 Y 坐标值的反正切值。
# cos(x) 返回x的弧度的余弦值。
# hypot(x, y) 返回欧几里德范数 sqrt(x*x + y*y)。
# sin(x) 返回的x弧度的正弦值。
# tan(x) 返回x弧度的正切值。
# degrees(x) 将弧度转换为角度,如math.degrees(math.tan(1.0)) ,返回30.0
# radians(x) 将角度转换为弧度

print ("-------Python中的数学函数-------");
# 函数 返回值 ( 描述 )
# abs(x) 返回数字的绝对值,如abs(-10) 返回 10
# ceil(x) 返回数字的上入整数,如math.ceil(4.1) 返回 5
# cmp(x, y) 如果 x < y 返回 -1, 如果 x == y 返回 0, 如果 x > y 返回 1
# exp(x) 返回e的x次幂(ex),如math.exp(1) 返回2.718281828459045
# fabs(x) 返回数字的绝对值,如math.fabs(-10) 返回10.0
# floor(x) 返回数字的下舍整数,如math.floor(4.9)返回 4
# log(x) 如math.log(math.e)返回1.0,math.log(100,10)返回2.0
# log10(x) 返回以10为基数的x的对数,如math.log10(100)返回 2.0
# max(x1, x2,...) 返回给定参数的最大值,参数可以为序列。
# min(x1, x2,...) 返回给定参数的最小值,参数可以为序列。
# modf(x) 返回x的整数部分与小数部分,两部分的数值符号与x相同,整数部分以浮点型表示。
# pow(x, y) x**y 运算后的值。
# round(x [,n]) 返回浮点数x的四舍五入值,如给出n值,则代表舍入到小数点后的位数。
# sqrt(x) 返回数字x的平方根,数字可以为负数,返回类型为实数,如math.sqrt(4)返回 2+0j
【传说】aiXiaol 2017/8/27 10:20:14

# 字符串方法
# 方法 描述
# string.capitalize()
# 把字符串的第一个字符大写
# string.center(width)
# 返回一个原字符串居中,并使用空格填充至长度 width 的新字符串
# string.count(str, beg=0, end=len(string))
# 返回 str 在 string 里面出现的次数,如果 beg 或者 end 指定则返回指定范围内 str 出现的次数
# string.decode(encoding='UTF-8', errors='strict')
# 以 encoding 指定的编码格式解码 string,如果出错默认报一个 ValueError 的 异 常 , 除 非 errors 指 定 的 是 'ignore' 或 者'replace'
# string.encode(encoding='UTF-8', errors='strict')
# 以 encoding 指定的编码格式编码 string,如果出错默认报一个ValueError 的异常,除非 errors 指定的是'ignore'或者'replace'
# string.endswith(obj, beg=0, end=len(string))
# 检查字符串是否以 obj 结束,如果beg 或者 end 指定则检查指定的范围内是否以 obj 结束,如果是,返回 True,否则返回 False.
# string.expandtabs(tabsize=8)
# 把字符串 string 中的 tab 符号转为空格,默认的空格数 tabsize 是 8.
# string.find(str, beg=0, end=len(string))
# 检测 str 是否包含在 string 中,如果 beg 和 end 指定范围,则检查是否包含在指定范围内,如果是返回开始的索引值,否则返回-1
# string.index(str, beg=0, end=len(string))
# 跟find()方法一样,只不过如果str不在 string中会报一个异常.
# string.isalnum()
# 如果 string 至少有一个字符并且所有字符都是字母或数字则返
# 回 True,否则返回 False
# string.isalpha()
# 如果 string 至少有一个字符并且所有字符都是字母则返回 True,
# 否则返回 False
# string.isdecimal()
# 如果 string 只包含十进制数字则返回 True 否则返回 False.
# string.isdigit()
# 如果 string 只包含数字则返回 True 否则返回 False.
# string.islower()
# 如果 string 中包含至少一个区分大小写的字符,并且所有这些(区分大小写的)字符都是小写,则返回 True,否则返回 False
# string.isnumeric()
# 如果 string 中只包含数字字符,则返回 True,否则返回 False
# string.isspace()
# 如果 string 中只包含空格,则返回 True,否则返回 False.
# string.istitle()
# 如果 string 是标题化的(见 title())则返回 True,否则返回 False
# string.isupper()
# 如果 string 中包含至少一个区分大小写的字符,并且所有这些(区分大小写的)字符都是大写,则返回 True,否则返回 False
# string.join(seq)
# Merges (concatenates)以 string 作为分隔符,将 seq 中所有的元素(的字符串表示)合并为一个新的字符串
# string.ljust(width)
# 返回一个原字符串左对齐,并使用空格填充至长度 width 的新字符串
# string.lower()
# 转换 string 中所有大写字符为小写.
# string.lstrip()
# 截掉 string 左边的空格
# string.maketrans(intab, outtab])
# maketrans() 方法用于创建字符映射的转换表,对于接受两个参数的最简单的调用方式,第一个参数是字符串,表示需要转换的字符,第二个参数也是字符串表示转换的目标。
# max(str)
# 返回字符串 str 中最大的字母。
# min(str)
# 返回字符串 str 中最小的字母。
# string.partition(str)
# 有 点像 find()和 split()的结合体,从 str 出现的第一个位置起,把 字 符 串 string 分 成 一 个 3 元 素 的 元 组 (string_pre_str,str,string_post_str),如果 string 中不包含str 则 string_pre_str == string.
# string.replace(str1, str2,  num=string.count(str1))
# 把 string 中的 str1 替换成 str2,如果 num 指定,则替换不超过 num 次.
# string.rfind(str, beg=0,end=len(string) )
# 类似于 find()函数,不过是从右边开始查找.
# string.rindex( str, beg=0,end=len(string))
# 类似于 index(),不过是从右边开始.
# string.rjust(width)
# 返回一个原字符串右对齐,并使用空格填充至长度 width 的新字符串
# string.rpartition(str)
# 类似于 partition()函数,不过是从右边开始查找.
# string.rstrip()
# 删除 string 字符串末尾的空格.
# string.split(str="", num=string.count(str))
# 以 str 为分隔符切片 string,如果 num有指定值,则仅分隔 num 个子字符串
# string.splitlines(num=string.count('\n'))
# 按照行分隔,返回一个包含各行作为元素的列表,如果 num 指定则仅切片 num 个行.
# string.startswith(obj, beg=0,end=len(string))
# 检查字符串是否是以 obj 开头,是则返回 True,否则返回 False。如果beg 和 end 指定值,则在指定范围内检查.
# string.strip([obj])
# 在 string 上执行 lstrip()和 rstrip()
# string.swapcase()
# 翻转 string 中的大小写
# string.title()
# 返回"标题化"的 string,就是说所有单词都是以大写开始,其余字母均为小写(见 istitle())
# string.translate(str, del="")
# 根据 str 给出的表(包含 256 个字符)转换 string 的字符,
# 要过滤掉的字符放到 del 参数中
# string.upper()
# 转换 string 中的小写字母为大写
# string.zfill(width)
# 返回长度为 width 的字符串,原字符串 string 右对齐,前面填充0
# string.isdecimal()
# isdecimal()方法检查字符串是否只包含十进制字符。这种方法只存在于unicode对象。
【传说】aiXiaol 2017/8/27 10:20:24

print("----------列表方法---------");
# del list1[2];
# 删除列表元素

# Python列表脚本操作符
# Python 表达式 结果 描述
# len([1, 2, 3]) 3 长度
# [1, 2, 3] + [4, 5, 6] [1, 2, 3, 4, 5, 6] 组合
# ['Hi!'] * 4 ['Hi!', 'Hi!', 'Hi!', 'Hi!'] 重复
# 3 in [1, 2, 3] True 元素是否存在于列表中
# for x in [1, 2, 3]: print x, 1 2 3 迭代

# Python列表截取
# L = ['spam', 'Spam', 'SPAM!']
# Python 表达式 结果 描述
# L[2] 'SPAM!' 读取列表中第三个元素
# L[-2] 'Spam' 读取列表中倒数第二个元素
# L[1:] ['Spam', 'SPAM!'] 从第二个元素开始截取列表

# Python列表函数&方法
# cmp(list1, list2)
# 比较两个列表的元素
# len(list)
# 列表元素个数
#  max(list)
# 返回列表元素最大值
#  min(list)
# 返回列表元素最小值
#  list(seq)
# 将元组转换为列表
#  list.append(obj)
# 在列表末尾添加新的对象
# list.count(obj)
# 统计某个元素在列表中出现的次数
# list.extend(seq)
# 在列表末尾一次性追加另一个序列中的多个值(用新列表扩展原来的列表)
# list.index(obj)
# 从列表中找出某个值第一个匹配项的索引位置
# list.insert(index, obj)
# 将对象插入列表
# list.pop([index])
# 移除列表中的一个元素(默认最后一个元素),并且返回该元素的值
# list.remove(obj)
# 移除列表中某个值的第一个匹配项
#  list.reverse()
# 反向列表中元素
# list.sort([func])
# 对原列表进行排序

16.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值