《从菜鸟到大师-杨老师课程笔记》Python工程师之 爬虫基础 04

零.文章出处

https://blog.csdn.net/Eastmount/article/details/108887652

  • 文本仅仅是个人对于杨老师的文章的学习笔记总结,请支持原文

一、正则的相关知识

0.理解和使用

  • 1.正则就是一个表达式
  • 2.表达式可以由一个或者多个pattern组成
  • 3.pattern由符号组成,且遵循特定的规则

pattern就是要回答:谁+多少+在哪里

所以Pattern = 代词 + 量词 + 定位介词

0.1代词

代词就是用来指代某一个特定字符,只指代一个字符的范围。

^:表示从头开始校验,$:表示校验到最后一位

常用的代词(大写一般都是取反):

  • []::表示的是一个字符的范围
  • [0-9]:表示0-9之间的一个数字
  • [a-zA-Z]:表示一个大小写的字母
  • \d: 数字
  • \D: 非数字
  • \w == [0-9a-zA-Z_] :匹配字母或数字或下划线或汉字
  • \W== [^0-9a-zA-Z_]:非匹配字母或数字或下划线或汉字
  • \s: 空格
  • \S: 非空格
  • . :表示除了换行\n之外的任意字符
  • [0-9a-zA-Z_] : 字符集
  • [^xyz] :
  • [[:alpha:]] 任何字母
  • [[:digit:]] 任何数字
  • [[:alnum:]] 任何字母和数字
  • [[:space:]] 任何空白字符
  • [[:upper:]] 任何大写字母
  • [[:lower:]] 任何小写字母
  • [[:punct:]] 任何标点符号
  • [[:xdigit:]] 任何16进制的数字,相当于[0-9a-fA-F]

0.2量词

量词,就是有多少个代词。
在这里插入图片描述
*有无出现都可以,+至少出现一次,?表示1次或者0次,{}限定出现的次数

0.3 定位词

  • ^ : 行首
  • $ : 行尾
  • \b : 单词边界
  • \B : 非单词边界

0.4 选择器:

用来捕获匹配字符串,或者组合多种模式进行匹配

(pattern)

  • (?:pattern) :匹配 pattern 但不获取匹配结果,hello|Hello 可以写成 (H|h)ello
  • (?=pattern) :正向肯定预查(look ahead positive assert), Windows(?!95|98|NT|2000) 不匹配 Windows3.1
  • (?!pattern) :正向否定预查(negative assert), Windows(?!95|98|NT|2000) 匹配 Windows3.1
  • (?<=pattern) :反向(look behind)肯定预查
  • (?<!pattern) :反向否定预查
    捕获组是通过从左到右计算其开括号来编码,例如,在表达式 ((A)((B©))),对应以下捕获组:

((A)(B©))
(A)
(B©)
©

0.5反向引用:

二义性的符号 ^ : 在代词里表示非,在定位词中表示行首
二义性的符号 ?: 在代词后面表示量词,在量词后面表示非贪婪,在选择器中表示非捕获

1.re模块

python中通re模块实现对于正则表达式的支持

  • import re
    使用步骤:
    1)创建pattern实例
    2)再用pattern创建一个匹配实例(match)
    3)用match实例去匹配文本

    常用的匹配函数;:findall
    findall(string[, pos[, endpos]]) | re.findall(pattern, string[, flags])
    该函数用于对字符串的文本的匹配,将匹配到的文本数据都放在一个列表之中

常见的re参数取值:
1)re.I(re.IGNORECASE):使用匹配忽略大小写
2)re.M(re.MULTILINE):允许多行的匹配
3)re.S(re.DATALL):匹配包换换行在内的所有字符

2.complie方法

re模块中的常用方法

  • compile(pattern[,flags] )
  • 根据包含正则表达式的字符串创建模式对象,返回一个pattern对象。参数flags是匹配模式,可以使用按位或“|”表示同时生效。Pattern对象是不能直接实例化的,只能通过compile方法得到。
>>> import re
>>> string="A1.45,b5,6.45,8.82"
>>> regex = re.compile(r"\d+\.?\d*")
>>> print regex.findall(string)
['1.45', '5', '6.45', '8.82']
>>> 

3.match方法(第一个不对就不行)

match方法是从字符串的pos下标处起开始匹配pattern,如果pattern结束时已经开始匹配,就会返回一个match对象,如果匹配过程中无法匹配,或者匹配结束就会返回一个None:

match(string[, pos[, endpos]]) | re.match(pattern, string[, flags])
参数string表示字符串;pos表示下标,pos和endpos的默认值分别为0和len(string);参数flags用于编译pattern时指定匹配模式。

4.search方法(找到一个符合条件的就停下)

search方法用于查找字符串中可以匹配成功的子串。从字符串的pos下标处尝试匹配pattern,如果pattern结束时仍可匹配,则返回一个match对象;若pattern结束时仍无法匹配,则将pos加1后重新尝试匹配;直到pos=endpos时仍无法匹配则返回None。函数原型如下:

search(string[, pos[, endpos]]) | re.search(pattern, string[, flags])
参数string表示字符串;pos表示下标,pos和endpos的默认值分别为0和len(string));参数flags用于编译pattern时指定匹配模式。

import re
s = '娜扎佟丽娅迪丽热巴'
result = re.match('佟丽娅',s)
print(result)

result = re.search('佟丽娅',s)
print(result)

print(result.span())#>>>输出的的位置
print(result.group())#>>>输出的是匹配到的信息

在这里插入图片描述

二 、数据爬取常用的模块

1.urllib模块

urllib中的request 中的urlopen方法

urlopen(uel,data=None,proxies=None)

该方法用于创建一个URL的类的对象,url是路径,data表示以post方式提交数据到网页,proxies表示网页代理。

该方法返回的是一个类的对象,这个类对象可以使用的方法
在这里插入图片描述
案例:

import urllib.request
import webbrowser as web

url = "http://www.baidu.com"
content = urllib.request.urlopen(url)

print(content.read())
print(content.info())
print(content.geturl())
print(content.getcode())

#保存网页
open('baidu.com','wb').write(content.read())


#浏览器打开某个网页
web.open_new_tab('baidu.com')
  • urlretrieve
    urlretrieve(url, filename=None, reporthook=None, data=None)
    在这里插入图片描述
    该函数是将远程数据下载保存到本地,
    参数filename指定了本地的保存路径,如果不设置这个函数就会生存一临时的文件夹
    reporhook是一个回调函数,当连接上一个服务器就会触发回调函数,该函数通常用来保存当前的下载精度。
    data表示上传表单数据

案例:

import urllib.request

#定义一个下载函数,a为已经下载的数据块,b为数据块的大小,c为远程数据
def Download(a,b,c):
	per = 100.0 * a * b / c
	if per > 100:
		print('已经下载 %.2f' % per)
	print('已经下载 %.2f' % per)
url = 'http://www.sina.com'
local = './sina.html'
urllib.request.urlretrieve(url,local,Download)

urllib模块中常用的两个方法,其中urlopen()用于打开网页,urlretrieve()方法是将远程数据下载到本地

2.urlparse模块

在这里插入图片描述

urlparse主要用来对于url的拆分和合并操作,它可以将url拆分为6个元组,并且返回元组,也可以将拆分的url合并成为一个url。主要的函数有urljoin,urlsplit,urlparse等等

-urlparse
urlparse.urlparse(urlstring[, scheme[, allow_fragments]])

该函数将urlstring值解析成6个部分,从urlstring中取得url,并返回元组(scheme, netloc, path, params, query, fragment)。该函数可以用来确定网络协议(HTTP、FTP等)、服务器地址、文件路径等。实例代码如下所示。
案例:

from urllib.parse import urlparse

url = urlparse('http://www.sina.com')

print(url)
print(url.netloc)

在这里插入图片描述
这个网址输出的参数都是无

# coding=utf-8
from urllib.parse import urlparse
url = urlparse('http://www.eastmount.com/index.asp?id=001')

print(url)          #url解析成六部分
print(url.netloc)   #输出网址

老师的输出:
在这里插入图片描述
可以看出确实将网站中的不同参数进行了解析分隔

用以调用urlunparse()函数将一个元组内容构建成一条Url。

  • urlunparse
    urlparse.urlunparse(parts)

案例:

# coding=utf-8
import urllib.parse
url = urllib.parse.urlparse('http://www.eastmount.com/index.asp?id=001')

print(url)           #url解析成六部分
print(url.netloc)    #输出网址

#重组URL
u = urllib.parse.urlunparse(url)
print(u)

正则表达式抓取网络数据

1.抓取标签间的内容

1).抓取得title内容

用(.*?)来自抓取我们需要的内容

<title>(.*?)</title>

案例

import re
import urllib.request
url = "http://www.baidu.com"
content = urllib.request.urlopen(url).read()
title = re.findall(r"<title>(.*?)</title>",content.decode('utf8'))
print(title[0])

直接读出来的content的内容是二进制的编码格式:
在这里插入图片描述
但是将content.decode(‘utf8’)解码后,就还原了原有网页的格式:
在这里插入图片描述
最后用re的findall匹配还原的网页格式中找title:
在这里插入图片描述

2).获取超链接的标签的内容

# coding=utf-8  
import re  
import urllib.request
url = "http://www.baidu.com/"  
content = urllib.request.urlopen(url).read()

#获取完整超链接
res = r"<a.*?href=.*?<\/a>"
urls = re.findall(res, content.decode('utf-8'))
for u in urls:
    print(u)

#获取超链接<a>和</a>之间内容
res = r'<a .*?>(.*?)</a>'  
texts = re.findall(res, content.decode('utf-8'), re.S|re.M)  
for t in texts:
    print(t)

这样获取的是整个的标签的内容,注意 .*?都必须是英文字符,哎,我说我怎么匹配不出来
在这里插入图片描述
这也是获取标签中的内容:
在这里插入图片描述

3).抓取tr (table row)和td(table data)标签

# coding=utf-8  
import re
import urllib.request
content = urllib.request.urlopen("test.html").read() #打开本地文件

#获取<tr></tr>间内容
res = r'<tr>(.*?)</tr>'
texts = re.findall(res, content.decode('utf-8'), re.S|re.M)
for m in texts:
    print(m)

#获取<th></th>间内容
for m in texts:
    res_th = r'<th>(.*?)</th>'
    m_th = re.findall(res_th, m, re.S|re.M)
    for t in m_th:
        print(t)

#直接获取<td></td>间内容
res = r'<td>(.*?)</td><td>(.*?)</td>'    
texts = re.findall(res, content.decode('utf-8'), re.S|re.M)
for m in texts:
    print(m[0],m[1])

2.抓取标签中的参数

1).抓标签中的url

网页中的url基本的格式都是内容,我们要的就是url:
案例:

import re

content = '''
<a href="http://news.baidu.com" name="tj_trnews" class="mnav">新闻</a>
'''

res = r"(?<=href=\").+?(?=\")|(?<=href=\').+?(?=\')"
urls = re.findall(res, content, re.I|re.S|re.M)
for url in urls:
    print(url)

老师这个正则表达式,我就有点看不懂了。去搜了下

正则表达式:(?<=(href=")).{1,200}(?=(">))
解释:(?<=(href=")) 表示 匹配以(href=")开头的字符串,并且捕获(存储)到分组中
(?=(">)) 表示 匹配以(">)结尾的字符串,并且捕获(存储)到分组中
在这里插入图片描述

2.抓取图片


content = '''<img alt="Python" src="http://www.yangxiuzhang.com/eastmount.jpg" />'''
urls = re.findall('src="(.*?)"', content, re.I|re.S|re.M)
print urls
# ['http://www.yangxiuzhang.com/eastmount.jpg']

3.获取最后一个参数


urls = 'http://www..csdn.net/eastmount.jpg'
name = urls.split('/')[-1]  
print name

3.字符串的替换

3.1数据定位

如果数据在一个大的数据框中,可以通过finde函数找到数据的其实位置和结束位置,切片得到数据

star = content.find(r"table class='infobox'")    #起始的位置
end = content.find(r'</table>')                  #终点位置
infobox = text[start:end]    
print infobox

3.2 数据清洗替换

案例:

import re
content = '''
<tr><td>1001</td><td>你好<br /></td></tr>
<tr><td>1002</td><td>世&nbsp;界</td></tr>
<tr><td>1003</td><td><B>Python</B></td></tr>
'''
res = r'<td>(.*?)</td><td>(.*?)</td>'
texts = re.findall(res,content,re.S|re.M)
for text in texts:
	print(text[0],text[1])

在这里插入图片描述
数据的替换和利用正则再次重新提取数据:

# coding=utf-8  
import re
content = '''
<tr><td>1001</td><td>你好<br /></td></tr>
<tr><td>1002</td><td>世&nbsp;界</td></tr>
<tr><td>1003</td><td><B>Python</B></td></tr>
'''
res = r'<td>(.*?)</td><td>(.*?)</td>'    
texts = re.findall(res, content, re.S|re.M)
for text in texts:
    value0 = text[0].replace('<br />', '').replace('&nbsp;', '')
    value1 = text[1].replace('<br />', '').replace('&nbsp;', '')
    if '<B>' in value1:
        m_value = re.findall(r'<B>(.*?)</B>', value1, re.S|re.M)
        print(value0, m_value[0])
    else:
        print(value0, value1)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

驭风少年君

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值