前一篇文章, 我们使用 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 的意思是表示原生字符串
实际上我们在使用正则表达式的时候, 通常先将其编译成 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)
可以看出来, 正则使用起来并不简单在上面的规则中, 我们是用了三个子组, 如果我们在网页上用 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 处理器自定义 openerpython 异常处理正则匹配 ip 等一系列的知识点任何知识, 用多了才会熟练
可以看到它运行成功, 并且找到一个可用 IP 后会问你是否继续爬取当然, 我们可以手动构建一个 IPPOOL 即 IP 池, 自定义一个函数, 把可以用的 IP 写入一个文件保存起来, 这里就不作赘述了在 github 上有成熟的 ip 池代码, 大家可以下载下来阅读, 这里只是把前面讲的一些用法做一个简单的试验, 因此并没有把这段代码完善
来源: http://www.bubuko.com/infodetail-2500314.html