lzb1001 发表于 2022-5-5 01:14:26

子组不捕获匹配的内容--结果与实际不符呢

import urllib.request
import re

def open_url(url):
    req = urllib.request.Request(url) # urllib.request.Request讲解见14.2.1、14.3.1,举例见p14_4.py、p14_5.py
    req.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36') # add_header讲解见14.3.1,举例见爬取猪八戒词条
    response = urllib.request.urlopen(req)
    #response
    #print(response)
    html = response.read().decode('utf-8')

    return html

def get_img(html):
    p = r'(?:(?:?\d?\d|2\d|25)\.){3}(?:?\d?\d|2\d|25)' # ip由四段数字组成:XXX.XXX.XXX.XXX
    iplist = re.findall(p, html)
   
    for each in iplist:
      print(each)
   
      
if __name__ == '__main__': # 见13.4(P147-149)
    url = 'https://proxy.seofangfa.com'
    get_img(open_url(url)) # 看不懂???!!!

运行后获得:

36.134.91.82
117.157.197.18
103.59.151.99
111.23.16.25
203.34.48.10
45.189.254.70
43.255.113.23
43.255.113.23
43.255.113.23
43.255.113.23

与实际网页对比如下:



红框处不同,是不是正则表达式有错造成的呢?完全按小甲鱼教学视频上敲的哦

isdkz 发表于 2022-5-5 06:19:59

本帖最后由 isdkz 于 2022-5-5 11:16 编辑

这个正则表达式确实有点问题,

因为第一种情况 ?\d?\d 可以匹配两位且第一位不是 0,1开头的,

250 就不是 以 0、1 开头的,所以只匹配了两位就不匹配了,你可以把正则的位置换一下

对你的代码修改如下:


import urllib.request
import re

def open_url(url):
    req = urllib.request.Request(url) # urllib.request.Request讲解见14.2.1、14.3.1,举例见p14_4.py、p14_5.py
    req.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36') # add_header讲解见14.3.1,举例见爬取猪八戒词条
    response = urllib.request.urlopen(req)
    #response
    #print(response)
    html = response.read().decode('utf-8')

    return html

def get_img(html):
    p = r'(?:(?:?\d?\d|2\d|25)\.){3}(?:2\d|25|?\d?\d)' # 改了这里最后一段的位置,把 ?\d?\d 放到最后
    iplist = re.findall(p, html)
   
    for each in iplist:
      print(each)
   
      
if __name__ == '__main__': # 见13.4(P147-149)
    url = 'https://proxy.seofangfa.com'
    get_img(open_url(url)) # 看不懂???!!!

lzb1001 发表于 2022-5-5 10:54:30

isdkz 发表于 2022-5-5 06:19
这个正则表达式确实有点问题,

因为第一种情况 ?\d?\d 可以匹配两位且第一位不是 0,1开头的,


感谢,按大神指点的修改后确实可以了。

不过我想继续问下:

大神你说:因为第一种情况 ?\d?\d 可以匹配两位且第一位不是 0,1开头的,

而我记得小甲鱼在教材里14.5.4说:\d\d表示可以匹配0或1开头的

所以我想问的是:

1、 ?\d?\d 是不是应该等同于?\d?\d

2、如果等同的话,大神的说法不是和小甲鱼的说法不一致了吗?

isdkz 发表于 2022-5-5 11:15:38

lzb1001 发表于 2022-5-5 10:54
感谢,按大神指点的修改后确实可以了。

不过我想继续问下:


?\d?\d 不等同于 ?\d?\d 也不等同于 \d\d,
比 多出一个 逗号字符,


在中括号里表示范围应该用 -,即 ?\d?\d
等同于 ?\d?\d,

那个 ?表示匹配 0 次或 1 次,

也就是说 0 或 1 不一定要匹配上,这时候就少了 1 位,

也就是说 ?\d?\d 除了可以匹配以0或1开头的三位数以外,

还可以匹配不以0或1开头的两位数,

这样的话就没有后边的 2\d 或 25什么事了,

他匹配够两位就不继续往下匹配了,

所以我换了一下顺序,先看 2\d 或 25 能不能匹配上,

再来看 ?\d?\d

lzb1001 发表于 2022-5-5 11:56:21

本帖最后由 lzb1001 于 2022-5-5 12:00 编辑

isdkz 发表于 2022-5-5 11:15
?\d?\d 不等同于 ?\d?\d 也不等同于 \d\d,
比 多出一个 逗号字符,



有点绕,三个的区别看晕了,整理下:

                      等同于             表示含义
\d\d                  ?                可以匹配两位且第一位不是 0,1开头的?

\d\d           \d\d                ?

\d\d             \d\d                 ?

isdkz 发表于 2022-5-5 12:06:14

lzb1001 发表于 2022-5-5 11:56
有点绕,三个的区别看晕了,整理下:

                      等同于             表示含义



\d\d 等同于 \d\d,

而 \d\d 中的 “,” 就是一个普通的逗号字符,所以除了 0 或 1 还可以匹配逗号,

是 ?\d?\d 可以匹配两位数字且第一位不是 0,1开头的,

关于正则表达式中 “?” 的用法你可以去查一下,

正则表达式是需要系统地去学习的,刚开始接触可能确实不太好理解

lzb1001 发表于 2022-5-5 12:08:09

本帖最后由 lzb1001 于 2022-5-5 12:09 编辑

三种表达式运行的结果为什么都一样?更晕了:


第一种:p = r'(?:(?:2\d|25|?\d?\d)\.){3}(?:2\d|25|?\d?\d)'
103.133.177.141
47.115.6.196
183.247.194.203
175.178.89.245
39.174.28.139
45.167.89.93
112.78.14.152
112.78.14.4
181.129.2.90
112.78.14.23

第二种:p = r'(?:(?:2\d|25|?\d?\d)\.){3}(?:2\d|25|?\d?\d)'

103.133.177.141
47.115.6.196
183.247.194.203
175.178.89.245
39.174.28.139
45.167.89.93
112.78.14.152
112.78.14.4
181.129.2.90
112.78.14.23

第三种:p = r'(?:(?:2\d|25|?\d?\d)\.){3}(?:2\d|25|?\d?\d)'

103.133.177.141
47.115.6.196
183.247.194.203
175.178.89.245
39.174.28.139
45.167.89.93
112.78.14.152
112.78.14.4
181.129.2.90
112.78.14.23

第二种和第三种的写法其实是一样的,对吗?

isdkz 发表于 2022-5-5 17:43:46

lzb1001 发表于 2022-5-5 12:08
三种表达式运行的结果为什么都一样?更晕了:




嗯嗯,第二种和第三种是一样的,

而 第一种可以匹配逗号字符,也就是说你这里没有逗号自然没有区别了,

你把最后一段的第一个数字换成逗号你就可以看出区别了

lzb1001 发表于 2022-5-5 20:11:23

isdkz 发表于 2022-5-5 17:43
嗯嗯,第二种和第三种是一样的,

而 第一种可以匹配逗号字符,也就是说你这里没有逗号自然没有区别了 ...

最后一段的第一个数字换成逗号?

没看懂是指哪一段的第一个数字,请明示,谢谢大神

isdkz 发表于 2022-5-5 20:40:52

lzb1001 发表于 2022-5-5 20:11
最后一段的第一个数字换成逗号?

没看懂是指哪一段的第一个数字,请明示,谢谢大神

>>> import re
>>> p = r'(?:(?:2\d|25|?\d?\d)\.){3}(?:2\d|25|?\d?\d)'
>>> re.match(p, "103.133.177.,41")
<re.Match object; span=(0, 15), match='103.133.177.,41'>
>>> p = r'(?:(?:2\d|25|?\d?\d)\.){3}(?:2\d|25|?\d?\d)'
>>> re.match(p, "103.133.177.,41")
>>>
页: [1]
查看完整版本: 子组不捕获匹配的内容--结果与实际不符呢