python爬虫(5)——正则表达式(二)

时间:2024-07-06 10:35:50

    前一篇文章,我们使用re模块来匹配了一个长的字符串其中的部分内容。下面我们接着来作匹配“1305101765@qq.com   advantage  314159265358 1892673 3.14 little Girl try_your_best 56 123456789@163.com  python3”

    我们的目标是匹配‘56’,其中\d表示匹配数字,{2}表示匹配次数为两次,{M,N},M,N均为非负整数,M<=N,表示匹配M-N次。在匹配规则前面加个r的意思是表示原生字符串。

python爬虫(5)——正则表达式(二)

    实际上我们在使用正则表达式的时候,通常先将其编译成pattern对象,使用re.compile()方法来进行编译。下面我们来匹配IP地址如:192.168.1.1。

   

 import re

 str='192.168.1.1'

 re.search(r'(([01]{0,1}\d{0,1}\d|2[0-4]\d|25[0-5])\.){3}([01]{0,1}\d{0,1}\d|2[0-4]\d|25[0-5])',str)

 python爬虫(5)——正则表达式(二)

    可以看出来,正则使用起来并不简单。在上面的规则中,我们是用了三个子组,如果我们在网页上用findall匹配所有IP,它会把结果给分类了,变成(‘192’,‘168’,‘1’,‘1’)。显然这不是我们想要的。这时候,我们需要用(?:...)来表示非捕获组,即该子组匹配的字符串无法从后面获取。

    有了之前的基础,我尝试着写下了如下的代码,从西刺代理网站上爬取IP地址,并用代理访问网站验证其是否可用。当中用到了python的异常处理机制。虽然代码不成熟,但还是分享出来,慢慢改进。

 import urllib.request
import re url="http://www.xicidaili.com/"
useful_ip=[]
def loadPage(url):
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36"}
response=urllib.request.Request(url,headers=headers)
html=urllib.request.urlopen(response).read().decode("utf-8")
return html def getProxy():
html=loadPage(url)
pattern=re.compile(r'(<td>\d+</td>)')
duankou=pattern.findall(html)
pattern=re.compile(r'(?:(?:[01]{0,1}\d{0,1}\d|2[0-4]\d|25[0-5])\.){3}(?:[01]{0,1}\d{0,1}\d|2[0-4]\d|25[0-5])')
content_list=pattern.findall(html)
list_num=[]
for num in duankou:
list_num.append(num[4:-5])
for i in range(len(list_num)):
ip=content_list[i]+ ":"+list_num[i]
while True:
proxy_support=urllib.request.ProxyHandler({'http':ip})
opener=urllib.request.build_opener(proxy_support)
opener.add_handler=[("User-Agent","Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36")]
urllib.request.install_opener(opener)
try:
print("正在尝试使用 %s 访问..." % ip)
ip_filter="http://www.whatsmyip.org/"
ip_response=urllib.request.urlopen(ip_filter)
except urllib.error.URLError:
print("访问出错,这个IP不能用啦")
break
else:
print("访问成功!")
print("可用IP为: %s " % ip)
useful_ip.append(ip)
if input("继续爬取?")=="N":
print("有效IP如下:")
for key in useful_ip:
print(key)
exit()
else:
break if __name__=="__main__":
getProxy()

    在处理IP地址对应的端口号时,我用的一个非常笨的方法。实际上有更好的办法解决,大家也可以想一想。在上面这段代码中,使用urllib访问网站、Handler处理器自定义opener、python异常处理、正则匹配ip等一系列的知识点。任何知识,用多了才会熟练。

python爬虫(5)——正则表达式(二)

    可以看到它运行成功,并且找到一个可用IP后会问你是否继续爬取。当然,我们可以手动构建一个IPPOOL即IP池,自定义一个函数,把可以用的IP写入一个文件保存起来,这里就不作赘述了。在github上有成熟的ip池代码,大家可以下载下来阅读,这里只是把前面讲的一些用法做一个简单的试验,因此并没有把这段代码完善。