Python爬虫小白教程(三)——使用正则表达式分析网页

正则表达式

正则表达式是对字符串操作的逻辑公式,在某些情况下通过使用正则表达式我们可以轻易地获取到我们想要的结果,下面先学习简单的正则表达式后就开始实战练习。

模式概述模式概述
.匹配任意字符,除了换行符\s匹配空白字符
*匹配前一个字符 0 次或多次\S匹配任何非空白字符
+匹配前一个字符 1 次或多次\d匹配数字,等价于 [0-9]
?匹配前一个字符 0 次或 1 次\D匹配任何非数字
^匹配字符串开头\n匹配一个换行符
$匹配字符串末尾\w匹配字母数字
()对正则表达式分组并记住匹配的文本\W匹配非字母数字
[…]表示一组字符。例:[amk] 匹配 ‘a’,‘m’或’k’[^…]不在[]中的字符:[^abc] 匹配除了a,b,c之外的字符。

以上只是一些基本的正则表达式,想更深入了解可以百度。

基本方法

re.match 方法

re.match尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none。
函数用法为:

re.match(pattern, string, flags=0)
参数描述
pattern匹配的正则表达式
string匹配的字符串
flags标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。

flags的选择如下

修饰符描述
re.I使匹配对大小写不敏感
re.L做本地化识别(locale-aware)匹配
re.M多行匹配,影响 ^ 和 $
re.S使 . 匹配包括换行在内的所有字符
re.U根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B.
re.X该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。

举个例子:

import re

string = 'Big bilibili is a learning website haha'
r = re.match(r'(.*) is (.*?) website', string)
print("匹配的整句话:", r.group(0))
print("匹配的第一个结果:", r.group(1))
print("匹配的第二个结果:", r.group(2))
print("匹配的结果列表:", r.groups())

得到的结果如下:

匹配的整句话: Big bilibili is a learning website
匹配的第一个结果: Big bilibili
匹配的第二个结果: a learning
匹配的结果列表: (‘Big bilibili’, ‘a learning’)

为什么要在正则表达式前加上r呢?
r'(.*) is (.*?) website'前面的r意思是raw string,代表纯粹的字符串,这样就不会对引号里面的反斜杠\进行特殊处理。因为在正则表达式中有一些类似于\d的模式,所以模式中的单个反斜杠\都要进行转译。

re.search 方法

re.search 扫描整个字符串并返回第一个成功的匹配。
函数用法为:

re.search(pattern, string, flags=0)

它和re.match方法有什么区别呢?
re.match尝试从字符串的起始位置匹配一个模式,而re.search 扫描整个字符串并返回第一个成功的匹配。举个简单的例子:

import re

string = 'Big 6 bilibili is a learning website haha'
r = re.search(r'\d (.*) is (.*?) website', string)
print("匹配的整句话:", r.group(0))
print("匹配的第一个结果:", r.group(1))
print("匹配的第二个结果:", r.group(2))
print("匹配的结果列表:", r.groups())

使用re.search得到结果如下:

匹配的整句话: 6 bilibili is a learning website
匹配的第一个结果: bilibili
匹配的第二个结果: a learning
匹配的结果列表: (‘bilibili’, ‘a learning’)

使用re.match方法

import re

string = 'Big 6 bilibili is a learning website haha'
r = re.match(r'\d (.*) is (.*?) website', string)
print(r)

因为字符串开头不是数字,故无法匹配,得到结果为None
因此我个人认为match方法用到的地方可能会比较少。

re.findall 方法

在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表。
举个例子和上面两种方法做个比较:

import re

r_match = re.match(r'\d+', '1234 is the first number, 6666 is the second.')
r_search = re.search(r'\d+', 'The first number is 1234, the second number is 6666.')
r_findall = re.findall(r'\d+', 'The first number is 1234, the second number is 6666.')

print("r_match:", r_match.group())
print("r_search:", r_search.group())
print("r_findall:", r_findall)

得到的结果如下:

r_match: 1234
r_search: 1234
r_findall: [‘1234’, ‘6666’]

获取自己的IP地址

下面我们通过查看自己IP的网站来看一下使用正则表达式的优越性。
我们使用 http://httpbin.org/get 来查看自己的IP地址。
首先分析网页。
在这里插入图片描述
打码处为我的电脑现在的IP地址。通过分析网页可知IP地址在一堆字符中的某一处,这样使用以前的方法一层一层分析已经不行了,所以我们现在使用正则表达式来获取一下IP地址。
我们定义一下获取页面的函数。

def get_page(url,params=None,headers=None,proxies=None):

    response = requests.get(url, headers=headers, params=params, proxies=proxies)
    print("解析网址:",response.url)
    page = BeautifulSoup(response.text, 'lxml')
    print("响应状态码:", response.status_code)
    
    return page

然后就可以获取页面的源码了:

url = 'http://httpbin.org/get'
headers = {
    'Host': 'httpbin.org',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.79 Safari/537.36'
    }

page = get_page(url, headers=headers)

使用

page.text

来看一下结果(打码处为IP地址):
在这里插入图片描述
然后我们分析一下IP地址的特点:
IP地址为由.分隔开的四组数字组成,每组数字有1-3位数字,这样我们便可以定义IP地址的正则表达式r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}',其中\.匹配字符串中的.。因此可得获得IP地址的代码如下:

ip = re.findall(r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}', page.text)
print(ip[0])

这样便可以得到本机的IP地址了。

爬虫系列

Python爬虫小白教程(一)—— 静态网页抓取
Python爬虫小白教程(二)—— 爬取豆瓣评分TOP250电影
Python爬虫小白教程(三)——使用正则表达式分析网页
Python爬虫小白教程(四)—— 反反爬之IP代理池
Python爬虫小白教程(五)—— 多线程爬虫

  • 20
    点赞
  • 85
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值