关于python爬虫的学习总结

爬虫的五个步骤

  • 明确需求,想想爬什么数据
  • 确定含有需要数据的网站
  • 分析请求类别,请求时所携带的参数,模拟发送请求
  • 下载页面,分析页面,通过re,xpath来过滤response中返回的数据
  • 将数据储存起来

正则表达式

正则表达式的定义

描述了一种字符串的匹配模式,可以用来检查一个串是否含有某种字串,见匹配到的字串替换成其他的字符或者取出

应用场景

测试字符串的是否符合某个模式

批量替换文本中符合某个模式的字符

正则表达式的使用

re.match 尝试从字符串的起始位置匹配

re.search 扫描整个字符串,匹配一次

re.findall 扫描整个字符串,匹配出所有符合模式的子串,返回列表

re.finditer 扫描方法是和findall相似,只是返回的结果是一个生成器

re.compile 在匹配模式不变,但是被匹配对象变化的时候使用

# compile 的使用
compile(pattern,flags=0)
pet = r'^1(([3597]\d)|(47))\d{8}$'
print(re.match(pet,'13600000000'))

re_telephone = re.compile(pet)
print(re_telephone.match('13600000000'))

re.sub:

re.sub(pattern, repl, string, count=0, flags=0) 匹配目标串,将目标串中被匹配到的子串替换成指定的字符串,可以指定替换次数,不指定将替换所有

re.subn:

re.subn(pattern, repl, string, count=0, flags=0):

和re.sub一样,前者返回的是被替换的字符串,后者返回一个元组,第一个元素表示被替换的字符串,第二个元素表示被替换的次数

匹配模式

模式描述
^匹配字符串的开头
$匹配字符串的末尾。
.匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符。
[…]用来表示一组字符,单独列出:[amk] 匹配 ‘a’,‘m’或’k’
[^…]不在[]中的字符:[^abc] 匹配除了a,b,c之外的字符。
re*匹配0个或多个的表达式。
re+匹配1个或多个的表达式。
re?匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式
re{ n}精确匹配 n 个前面表达式。例如, o{2} 不能匹配 “Bob” 中的 “o”,但是能匹配 “food” 中的两个 o。
re{ n,}匹配 n 个前面表达式。例如, o{2,} 不能匹配"Bob"中的"o",但能匹配 "foooood"中的所有 o。“o{1,}” 等价于 “o+”。“o{0,}” 则等价于 “o*”。
re{ n, m}匹配 n 到 m 次由前面的正则表达式定义的片段,贪婪方式
a| b匹配a或b
(re)匹配括号内的表达式,也表示一个组
(?imx)正则表达式包含三种可选标志:i, m, 或 x 。只影响括号中的区域。
(?-imx)正则表达式关闭 i, m, 或 x 可选标志。只影响括号中的区域。
(?: re)类似 (…), 但是不表示一个组
(?imx: re)在括号中使用i, m, 或 x 可选标志
(?-imx: re)在括号中不使用i, m, 或 x 可选标志
(?#…)注释.
(?= re)前向肯定界定符。如果所含正则表达式,以 … 表示,在当前位置成功匹配时成功,否则失败。但一旦所含表达式已经尝试,匹配引擎根本没有提高;模式的剩余部分还要尝试界定符的右边。
(?! re)前向否定界定符。与肯定界定符相反;当所含表达式不能在字符串当前位置匹配时成功
(?> re)匹配的独立模式,省去回溯。
\w匹配字母数字及下划线
\W匹配非字母数字及下划线
\s匹配任意空白字符,等价于 [\t\n\r\f].
\S匹配任意非空字符
\d匹配任意数字,等价于 [0-9].
\D匹配任意非数字
\A匹配字符串开始
\Z匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串。
\z匹配字符串结束
\G匹配最后匹配完成的位置。
\b匹配一个单词边界,也就是指单词和空格间的位置。例如, ‘er\b’ 可以匹配"never" 中的 ‘er’,但不能匹配 “verb” 中的 ‘er’。
\B匹配非单词边界。‘er\B’ 能匹配 “verb” 中的 ‘er’,但不能匹配 “never” 中的 ‘er’。
\n, \t, 等.匹配一个换行符。匹配一个制表符。等
\1…\9匹配第n个分组的内容。
\10匹配第n个分组的内容,如果它经匹配。否则指的是八进制字符码的表达式。

正则匹配列表

# 校检数字

数字:^[0-9]*$
n位的数字:^\d{n}$
至少n位的数字:^\d{n,}$
m-n位的数字:^\d{m,n}$
零和非零开头的数字:^(0|1-9*)$
非零开头的最多带两位小数的数字:^(1-9*)+(.[0-9]{1,2})?$
带1-2位小数的正数或负数:^(-)?\d+(.\d{1,2})?$
正数、负数、和小数:^(-|+)?\d+(.\d+)?$
有两位小数的正实数:^[0-9]+(.[0-9]{2})?$
有1~3位小数的正实数:^[0-9]+(.[0-9]{1,3})?$
非零的正整数:^[1-9]\d$ 或 ^(1-9){1,3}^\+?[1-9][0-9]*
非零的负整数:^-1-90-9"$ 或 ^-[1-9]\d$
非负整数:^\d+^[1-9]\d*|0
非正整数:^-[1-9]\d*|0^((-\d+)|(0+))
非负浮点数:^\d+(.\d+)? 或 ^[1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0
非正浮点数:^((-\d+(.\d+)?)|(0+(.0+)?))^(-([1-9]\d*\.\d*|0\.\d*[1-9]\d*))|0?\.0+|0
正浮点数:^[1-9]\d.\d|0.\d[1-9]\d 或 ^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))
负浮点数:^-([1-9]\d.\d|0.\d[1-9]\d)^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))
浮点数:^(-?\d+)(.\d+)? 或 ^-?([1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0)

# 校检字符
汉字:^[\u4e00-\u9fa5]{0,}$
英文和数字:^[A-Za-z0-9]+$ 或 ^[A-Za-z0-9]{4,40}$
长度为3-20的所有字符:^.{3,20}$
由26个英文字母组成的字符串:^[A-Za-z]+$
由26个大写英文字母组成的字符串:^[A-Z]+$
由26个小写英文字母组成的字符串:^[a-z]+$
由数字和26个英文字母组成的字符串:^[A-Za-z0-9]+$
由数字、26个英文字母或者下划线组成的字符串:^\w+$ 或 ^\w{3,20}$
中文、英文、数字包括下划线:^[\u4E00-\u9FA5A-Za-z0-9_]+$
中文、英文、数字但不包括下划线等符号:^[\u4E00-\u9FA5A-Za-z0-9]+$ 或 ^[\u4E00-\u9FA5A-Za-z0-9]{2,20}$
可以输入含有^%&',;=?$\"等字符:[^%&',;=?$\x22]+
禁止输入含有~的字符:[^~\x22]+

# 特殊需求的匹配
Email地址:^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
域名:[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(/.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+/.?
InternetURL:[a-zA-z]+://[^\s]*^http://([\w-]+\.)+[\w-]+(/[\w-./?%&=]*)?$
手机号码:^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$
电话号码("XXX-XXXXXXX""XXXX-XXXXXXXX""XXX-XXXXXXX""XXX-XXXXXXXX""XXXXXXX"和"XXXXXXXX)^(\(\d{3,4}-)|\d{3.4}-)?\d{7,8}$ 
国内电话号码(0511-4405222021-87888822):\d{3}-\d{8}|\d{4}-\d{7}
身份证号(15位、18位数字)^\d{15}|\d{18}$
短身份证号码(数字、字母x结尾)^([0-9]){7,18}(x|X)?$ 或 ^\d{8,18}|[0-9x]{8,18}|[0-9X]{8,18}?$
帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线)^[a-zA-Z][a-zA-Z0-9_]{4,15}$
密码(以字母开头,长度在6~18之间,只能包含字母、数字和下划线)^[a-zA-Z]\w{5,17}$
强密码(必须包含大小写字母和数字的组合,不能使用特殊字符,长度在8-10之间)^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,10}$  
日期格式:^\d{4}-\d{1,2}-\d{1,2}
一年的12个月(0109112)^(0?[1-9]|1[0-2])$
一个月的31(0109131)^((0?[1-9])|((1|2)[0-9])|30|31)$ 
钱的输入格式:
有四种钱的表示形式我们可以接受:"10000.00""10,000.00", 和没有 "分""10000""10,000"^[1-9][0-9]*$ 
这表示任意一个不以0开头的数字,但是,这也意味着一个字符"0"不通过,所以我们采用下面的形式:^(0|[1-9][0-9]*)$ 
一个0或者一个不以0开头的数字.我们还可以允许开头有一个负号:^(0|-?[1-9][0-9]*)$ 
这表示一个0或者一个可能为负的开头不为0的数字.让用户以0开头好了.把负号的也去掉,因为钱总不能是负的吧.下面我们要加的是说明可能的小数部分:^[0-9]+(.[0-9]+)?$ 
必须说明的是,小数点后面至少应该有1位数,所以"10."是不通过的,但是 "10""10.2" 是通过的:^[0-9]+(.[0-9]{2})?$ 
这样我们规定小数点后面必须有两位,如果你认为太苛刻了,可以这样:^[0-9]+(.[0-9]{1,2})?$ 
这样就允许用户只写一位小数.下面我们该考虑数字中的逗号了,我们可以这样:^[0-9]{1,3}(,[0-9]{3})*(.[0-9]{1,2})?$ 
13个数字,后面跟着任意个 逗号+3个数字,逗号成为可选,而不是必须:^([0-9]+|[0-9]{1,3}(,[0-9]{3})*)(.[0-9]{1,2})?$ <br>
备注:这就是最终结果了,别忘了"+"可以用"\*"替代如果你觉得空字符串也可以接受的话(奇怪,为什么?)最后,别忘了在用函数时去掉去掉那个反斜杠,一般的错误都在这里
xml文件:^([a-zA-Z]+-?)+[a-zA-Z0-9]+\\.[x|X][m|M][l|L]$
中文字符的正则表达式:[\u4e00-\u9fa5]
双字节字符:[^\x00-\xff]    (包括汉字在内,可以用来计算字符串的长度(一个双字节字符长度计2,ASCII字符计1))
空白行的正则表达式:\n\s*\r    (可以用来删除空白行)
HTML标记的正则表达式:<(\S*?)[^>]*>.*?</\1>|<.*? />    (网上流传的版本太糟糕,上面这个也仅仅能部分,对于复杂的嵌套标记依旧无能为力)
首尾空白字符的正则表达式:^\s*|\s*$或(^\s*)|(\s*$)    (可以用来删除行首行尾的空白字符(包括空格、制表符、换页符等等),非常有用的表达式)
腾讯QQ号:[1-9][0-9]{4,}    (腾讯QQ号从10000开始)
中国邮政编码:[1-9]\d{5}(?!\d)    (中国邮政编码为6位数字)
IP地址:\d+\.\d+\.\d+\.\d+    (提取IP地址时有用)
IP地址:((?:(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d))

进程,线程,协程

进程

一个任务就是一个进程,拥有自己独立的堆栈段,代码段,数据段以及状态的保存,进程是系统中程序执行和资源分配的基本单位

进程在计算机系统中是按照固定的时常轮播调度执行的

进程和进程之间通过内核,网络,或者文件的方式来相互通信

线程

一个进程任务的完成需要一个或者多个子任务组合成完成,所以一个进程至少有一个线程,子任务就是这个进程的线程

线程共享进程的数据,多线程变相的延长了这个进程在计算机系统中所执行的时间

进程和线程的区别

  • 进程是计算机系统进行资源分配和调度的独立单位,是数据层面,然而去实现进程中任务的是线程,线程是进程的实体,是进程的生命所在,是CPU调度和分配的基本单位,线程本身没有资源或者只拥有很少的一部分资源(线程计数器,寄存器,栈),但是它与其他线程共享所属进程的所有资源

  • 一个程序至少需要一个进程,而一个进程至少需要用有一个线程

  • 线程划分尺度小于进程,所以多线程的程序并发性高

  • 进程执行的时候拥有独立的寄存单元,多线程共享进程的内存,提高了程序的运行效率

  • 线程没有只能共享进程的资源,所以线程不能单独存在

  • 优缺点:

    • 多线程执行效率高,但是高并发不利于数据的管理和保护
    • 进程中如果只有一个线程,实现便于数的保护,但是效率低

协程

微线程,比线程更小,是用户态的轻量级的线程

协程 拥有自己的寄存器,上下文和栈,完全由用户控制调度,调度时会将自己的状态保存到寄存器,当重新切换回来的时候,还可以继续这调度之前

的状态执行

协程的优缺点:

  • 无需线程上下文切换的开销,避免了无意义 的调度,提高性能,但是程序员必须自己承担调度任务,而且失去了标准线程使用多CPU的能力
  • 无需原子操作,同步锁,减低开销
  • 无需切换控制流程,简化编程
  • 高并发,高扩展,低成本 一个CPU支持上万的协程不是问题,很适合用于高并发的处理
  • 缺点:
    • 无法利用多核,协程还是在单线程的层面上运行,所以想利用多核,还需要和线程配合
    • 发生阻塞操作的时候会阻塞整个程序

scrapy框架

scrpay中,数据流的走向:

  1. spider中 的start_url或者start_requests形成初始的request对象发送给Engine
  2. Engine判断出是request对象,将对象发送给Schedue
  3. Engine将从Schedule中获取request对象
  4. 获取到的request对象经过Download Middle Wares发送给Downloader
  5. Downloader从网络上获取数据后会生成response,这个response会再次经过Downloader Middle Ware 将response发送个Engine
  6. Engine获取到response之后,将response经过Spider Middle Ware 发送给Spiders,Spiders会处理response中的数据
  7. Spiders将处理之后的结果经过spider Middle Ware 发送给Engine
  8. Engine接收到Spider发送的结果之后进行判断:
    1. 如果结果是Item,那么发送个Item Pipeline处理这个Item
    2. 如果结果是request,那么发送给Schedule,重新进入请求循环

所涉及到的模块的作用

Scrapy Engine

负责整个数据流的控制以及事件触发的作用

Schedule

存储request

Downloader

负责request请求网络后的下载工作

Spiders

负责数据清洗,用户验证,以及数据储存的业务逻辑****

Download Middle Ware

处理发送到Downloader的request以及从Downloader返回的response

应用场景:

  • 下载器下载前,必须添加一些信息
  • 一个request想要生成另一个request
  • 需要删除一部分拥有某个特征的request的时候

Spiders Middle Ware

介于Engine 和 Spiders之间

处理 Request,Response以及Item

应用场景:

  • 处理输出的Item或者request
  • 隐藏输入的response的错误
  • 继续处理start_request中的内容
  • 自定义去重算法

分布式爬虫

将scrapy中的Schedule更换成为Redis数据库,实现将Spider输出的request请求共享

共享的request请求就可以在多台机器上处理,这就实现了分布式

优点:

  • 充分利用多台机器的带宽
  • 充分利用多台机器的IP
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值