python爬取身份证信息、爬取ip代理池

 

匹配的分类

按照匹配内容进行匹配

              我们在匹配的过程当中,按照要匹配的内容的类型和数量进行匹配

              比如:

                     匹配手机号:匹配以1开头的11位数字

              Re

       按照匹配结构进行匹配    

              我们我们在匹配的过程当中,按照要匹配的内容在整个数据当中的结构进行匹配

              比如:

                     匹配手机号:匹配phone:之后的值

              Xpath

       Beautifulsoup 是一个匹配的结合体,我们使用beautifulsoup可以完成内容和结构任意匹配。

       内容匹配,匹配繁琐,匹配精度高

       机构匹配,匹配精度不高,匹配效率高,一定是成结构的字符

re正则

正则是通过对字符串内容描述进行数据筛选的高级字符串处理方式

在学习Python爬虫的时候,初学同学会认为非正则不可,其实一部分简单的匹配结构用的最多的方法是字符串的:split、replace方法

内容的类型

       #每个类型默认匹配1次

       \d 匹配数字

       \D 匹配非数字

       \s 匹配空格

       \S 匹配非空格

       \w 匹配字母、数字、下划线

       \W 匹配非字母、数字、下划线

       []  匹配任意字符

       |  匹配任意一端

       [^] 匹配非

       .  匹配任意非换行的字符

       ^ 匹配开头

       $ 匹配结尾

       () 组匹配

内容的长度

       长度描述居于内容描述之后

       如果有多次,指尽量多的匹配

       如果匹配0次,代表没有匹配到

                     *  匹配0到多次

                     +  匹配1到多次

                     ? 匹配0到1次

                     {} 匹配指定值或者范围次

              贪婪匹配

匹配的方法

       Findall

       Search

       Match

正则例子:

       例1:

              一个正常的正则匹配,匹配一个网页上所有的身份证号,最简单

              匹配身份证号,一般是匹配数字,但是要小心最后有x

              首先编写如下代码:

import re
import requests
# 请求地址
url = "http://sfz.ckd.cc/"
# 请求头
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.80 Safari/537.36"
}
# 获取响应
response = requests.get(url = url,headers = headers)
# 获取内容,这里返回的是字节,所以需要decode进行解析
content = response.content.decode()
# print(content)
# 利用正则粗糙的匹配
res = re.findall(r'\d+',content)
for re in res:
    # 打印内容
    print(re)

效果如下:

效果差强人意,所以改进,我们认真研究发现,身份证有18,但是数字个数是17-18位,因为最后一位可能是大小写的X

代码如下:

import re
import requests
# 请求地址
url = "http://sfz.ckd.cc/"
# 请求头
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.80 Safari/537.36"
}
# 获取响应
response = requests.get(url = url,headers = headers)
# 获取内容,这里返回的是字节,所以需要decode进行解析
content = response.content.decode()
# print(content)
# 利用正则粗糙的匹配
# res = re.findall(r'\d+',content)
res = re.findall(r"\d{17}x|\d{17}X|\d{18}",content)
for re in res:
    # 打印内容
    print(re)

效果如下:

其实上面的正则可以写成这样:

res = re.findall(r"\d{17}[xX]|\d{18}",content)

效果如下:

一个组匹配

              需要获取完整的身份证信息

              如下:

爬虫的正则匹配和其他的正则匹配区别在于,我们可以借助HTML结构进行匹配

res = re.findall(r"<td>(.*?)</td><td>(.*?)</td><td>(.*)",content,re.M)

效果如下:

Search与match

  1. 区别(是python 2015年度北京市爬虫面试第一频繁的面试题)

Search是从全文查找符合匹配的,match是从开头查找符合的,二者如果查找到都需要用group来解析内容,如果查找不到,都返回None

     2. Group和groups

res = re.search(r"<td>(.*?)</td><td>(.*?)</td><td>(.*)",content,re.M)
print(res.group())
print(res.groups())

效果如下:

Lxml匹配

       Python的xpath是通过lxml模块进行定义的,不论用beautifulsoup还是scrapy都需要我们下载lxml包。

       pip install lxml

通过lxml我们进行爬虫匹配大概分为2步

  1. 构建HTML结构,将返回的字符串从新转换为HTML
  2. 进行匹配

      匹配的常用语法

     1.节点名称匹配

     直接描述HTML节点

       P div

     2. 子节点描述

      /Html/body/div

      这样的表述必须是相邻父子关系,禁止夸层

   3. 节点描述

      []

   可以通过索引或者属性描述节点

    Html/body/div[1]  HTML下的body下的第一个div

    4. 节点属性描述

     [@属性=“值”]

     Html/body/div[@id=“name”]  HTML下的body下的第一个id属性为name的div

       Xpath关注的点:

  1. xpath对普通字符串无效
  2. xpath匹配不论是匹配到一个对象,还是多个,都以列表返回
  3. xpath返回的是xpath对象,如果需要调用匹配到的具体内容常用一下三个属性
  1. text 返回文本
  2. attrib 返回属性
  3. tag 返回标签

    当我们发现一下格式要注意

    如果遇到以下问题,直接text匹配不到内容

   <p>

         Hello<span>while</span>

   </p>

   我写一个xpath的例子

              http://www.xicidaili.com/

              尝试爬取代理ip

    我们首先查看网站结构

这个时候我们尝试写一下我们的lxml匹配规则

from lxml import etree
import requests

url = "http://www.xicidaili.com/"

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.80 Safari/537.36"
}

response = requests.get(url = url,headers = headers)

response_body = response.content.decode()

#print(response_body)
html = etree.HTML(response_body)

tr_list = html.xpath('//tr[@class="odd"]')
for tr in tr_list:
    ip = tr.xpath("td[2]")[0].text
    port = tr.xpath("td[3]")[0].text
    address = tr.xpath("td[4]")[0].text
    nm = tr.xpath("td[5]")[0].text
    types = tr.xpath("td[6]")[0].text
    time = tr.xpath("td[7]")[0].text
    valid = tr.xpath("td[8]")[0].text
    result_dict = {
        "ip": ip,
        "port": port,
        "address": address,
        "nm": nm,
        "types": types,
        "time": time,
        "valid": valid
    }
    print(result_dict)

效果如下: 

思考1:

              完成正则例1的正则优化

思考2:

              使用xpath匹配以下格式当中的hello

<p>

Hello<span>while</span>

</p>

思考3:

              筛选出最新的5个透明的代理ip

              用冒泡法对已有的ip按照存活的时间进行排序

请对以上3个问题进行思考,我将会在近期对以上被人进行更新,如果有好的答案,欢迎私信我


思考1中的优化:

res = re.findall(r"\d{17}.",content)

效果如下:

思考2:

from lxml import etree
text_str = '''
    <p>
		Hello<span>while</span>
    </p>
'''

html = etree.HTML(text_str)
res = html.xpath('//p/text()')[0].strip()
print(res)

效果如下:

 

思考3:

import re
from lxml import etree
import requests

ip_list = []
all_list = []
url = "http://www.xicidaili.com/"
headers = {
     "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.80 Safari/537.36"
}
response = requests.get(url = url,headers = headers)
response_body = response.content.decode()
#print(response_body)
html = etree.HTML(response_body)
tr_list = html.xpath('//tr[@class="odd"] | //tr[@class=""]')
for tr in tr_list:
    ip = tr.xpath("td[2]")[0].text
    port = tr.xpath("td[3]")[0].text
    address = tr.xpath("td[4]")[0].text
    nm = tr.xpath("td[5]")[0].text
    types = tr.xpath("td[6]")[0].text
    time = tr.xpath("td[7]")[0].text
    valid = tr.xpath("td[8]")[0].text
    result_dict = {
        "ip": ip,
        "port": port,
        "address": address,
        "nm": nm,
        "types": types,
        "time": time,
        "valid": valid
    }
    all_list.append(result_dict)
    niming = result_dict.get("nm")
    if niming == "透明":
        ip_list.append(result_dict)
# 利用冒泡对存活时间进行排序
def cunhuo(ls):
    for j in range(len(ls)):
        for i in range(len(ls)-1-j):
            if int((re.findall(r'(\d+)',ls[i]['time']))[0]) < int((re.findall(r'(\d+)',ls[i+1]['time']))[0]):
                ls[i],ls[i+1] = ls[i+1],ls[i]
    for j in range(len(ls)):
        for i in range(len(ls) - 1 - j):
            if '分' in ls[i]['time']:
                ls[i], ls[i + 1] = ls[i + 1], ls[i]
    for j in range(len(ls)):
        for i in range(len(ls) - 1 - j):
            if '时' in ls[i]['time']:
                ls[i], ls[i + 1] = ls[i + 1], ls[i]
    for j in range(len(ls)):
        for i in range(len(ls) - 1 - j):
            if '天' in ls[i]['time']:
                ls[i], ls[i + 1] = ls[i + 1], ls[i]
    return ls
# 最新的五个透明代理ip
def mostNew(lt):
    for j in range(len(lt)):
        for i in range(len(lt)-1-j):
            if int((re.findall(r'(\d+)',lt[i]['valid']))[0]) < int((re.findall(r'(\d+)',lt[i+1]['valid']))[0]):
                lt[i],lt[i+1] = lt[i+1],lt[i]
    for j in range(len(lt)):
        for i in range(len(lt) - 1 - j):
            if '不到' in lt[i]['valid']:
                lt[i], lt[i + 1] = lt[i + 1], lt[i]
    for j in range(len(lt)):
        for i in range(len(lt) - 1 - j):
            if '分' in lt[i]['valid']:
                lt[i], lt[i + 1] = lt[i + 1], lt[i]
    for j in range(len(lt)):
        for i in range(len(lt) - 1 - j):
            if '小时' in lt[i]['valid']:
                lt[i], lt[i + 1] = lt[i + 1], lt[i]
    for j in range(len(lt)):
        for i in range(len(lt) - 1 - j):
            if '天' in lt[i]['valid']:
                lt[i], lt[i + 1] = lt[i + 1], lt[i]
    for j in range(len(lt)):
        for i in range(len(lt) - 1 - j):
            if '月' in lt[i]['valid']:
                lt[i], lt[i + 1] = lt[i + 1], lt[i]
    for j in range(len(lt)):
        for i in range(len(lt) - 1 - j):
            if '年' in lt[i]['valid']:
                lt[i], lt[i + 1] = lt[i + 1], lt[i]
    return lt
if __name__ == "__main__":
    print('==========' * 8)
    print('最新5个透明代理ip如下:')
    sort_list = mostNew(ip_list)
    for i in range(1, 6):
        print(sort_list[i])
    print('=========='*8)
    print('冒泡存活时间排序如下:')
    statistics = cunhuo(all_list)
    for i in statistics:
        print(i)

效果如下:

以上的做法还可以继续优化,存活时间还需要比较时间单位并不只是数字的大小,希望各位小伙伴们按照我的思路再思考思考

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

猜你喜欢

转载自blog.csdn.net/ALLENsakaru/article/details/85280970