2023年网络爬虫实训(第五天)

任务1:掌握re.match和re.search的用法,完成课堂代码.掌握基础通配符的用法如\w \s \d [] * + ^ $.并完成作业4.

1.re.match()

re.match()的是从头匹配一个符合规则的字符串,从起始位置开始匹配,匹配成功返回一个对象,未匹配成功返回None。包含的参数如下:

1.pattern: 正则模型   2.string : 要匹配的字符串   3.falgs : 匹配模式

match() 方法一旦匹配成功,就是一个match object对象,match object对象有以下方法:

1.group() 返回被 RE 匹配的字符串

2.start() 返回匹配开始的位置

3.end() 返回匹配结束的位置

4.span()返回一个元组包含匹配 (开始,结束) 的位置

案例:

import re

result = re.match("hello","hello,world")

if result:

    print(result.group())

else:

    print("匹配失败!")

输出结果:

hello

2.re.search()

re.search()函数会在字符串内查找模式匹配,只要找到第一个匹配然后返回;如果字符串没有匹配,则返回None。

格式:re.search(pattern, string, flags=0)

案例:匹配出文章阅读的次数

import re

ret = re.search(r"\d+", "阅读次数为 9999")

print(ret.group())

输出结果:

9999

3.match()和search()的区别:

match()函数只检测RE是不是在string的开始位置匹配,

search()会扫描整个string查找匹配

match()只有在0位置匹配成功的话才有返回,如果不是开始位置匹配成功的话,match()就返回none

举例说明:

import re

print(re.match('super', 'superstition').span())

(0, 5)

print(re.match('super','insuperable'))

None

print(re.search('super','superstition').span())

(0, 5)

print(re.search('super','insuperable').span())

(2, 7)

 

 

 

import re
import requests
# 针对结构化数据(主要以json为主),数据解析的方式就是对应的结构化数据解析,多以json解析为主,xml解析为辅
# 针对非结构化数据,数据解析方式可以选择正则解析或者xpath解析,当然还有一些第三方解析:BeautifulSoup


# 正则表达式
# 通常用来检索、替换和控制文本。

# re.match()
# 从字符串的起始位置匹配,如果匹配就返回匹配结果,不匹配就返回None
# 场景1:从键盘上输入一个字符串,验证用户输入的字符串是否以hello开头
# user_input = input('请输入任意字符串:\n')
# 规则1:匹配hello
# pattern1 = 'hello'
# 规则2:匹配hello + 任意的串
# pattern2 = r'hello\s\w*'
# print(re.match(pattern2, user_input).group())  # <re.Match object; span=(0, 5), match='hello'>

# 场景2:模拟简单注册,检验用户输入的账号是否合法
# 要求:
#   1.账号必须以数字开头 0 1 2 3 4 5 6 7 8 9
#   2.长度至少是7位数
# user_account = input('请输入账号:\n')
# # 定义规则
# pattern3 = r'[0-9]\w{6}'
# if re.match(pattern3, user_account) is None:
#     print("您输入的不符合规则,请检查!")

# 场景3:模拟注册
# 要求:
# 1.必须以大写字母开头,小写字母结尾
# 2.长度要求:7-10
# user_account = input('请输入账号:\n')
# # 定义规则
# pattern4 = r'[A-Z]\w{5,8}[a-z]$'  # 7-1-1 = 5   10-1-1 = 8   $表示结尾号
# if re.match(pattern4, user_account) is None:
#     print("您输入的不符合规则,请检查!")


# re.search
# 从整个字符串检索,如果匹配返回第一个匹配项;如果不匹配,则返回none
# txt = '我叫张三,今年19岁,我的电话是13877888899,我妈妈的电话是15222115566'
# # search的用法,在一段文本中提取我们想要的信息,比如在上段文本中我们提取电话号码
#
# # 手机号码的规范 13 15 16 17 18 19,长度11位
# pattern5 = r'1[356789]\d{9}'
# print(re.search(pattern5, txt).group())

# 练习:
# txt = '我叫王梓权,今年19岁,我的电话是18551001858,邮箱地址是3340989484@qq.com,身份证号码是:320703200308010511'
# # 在上述文本中提取电话,邮箱地址,身份证号码
# # 手机号码的规范 13 15 16 17 18 19,长度11位
# pattern5 = r'1[356789]\d{9}'
# pattern6 = r'[a-z|A-Z|0-9][\w]+@\w+([.]\w+)+'
# pattern7 = r'\d{18}'
# print("电话:", re.search(pattern5, txt, flags=0).group())
# print("邮箱地址:", re.search(pattern6, txt, flags=0).group())
# print("身份证号码:", re.search(pattern7, txt, flags=0).group())

任务2: 完成re.compile函数的代码.掌握正则表达式中的贪婪与非贪婪用法.

import re
import requests

# 正则表达式在html页面中提取数据
# proxy = {"HTTP": "117.41.38.19:9000"}  # 代理
# print(requests.get('https://wwww.baidu.com', proxies=proxy).status_code)

# 假设存在下列网页结构
html = '''
<td data-title="IP">117.41.38.19</td>
<td data-title="IP">117.41.38.29</td>
'''

# 提取ip地址
# 1.利用re.match提取(行不通)
# pattern = r'<td.*>(.*)<'
# print(re.match(pattern, html, re.S).group())  # 报错

# 2.利用re.search提取
pattern = r'<td.*>(.*)<'
result = re.search(pattern, html, re.S).group()  # re.S 使匹配包括换行符在内的所有字符
# print(result)
# <td data-title="IP">117.41.38.19</td>
# <td data-title="IP">117.41.38.29<
first_ip = result.split('>')[1][:-4]  # split后:['<td data-title="IP"', '117.41.38.19</td', '\n<td data-title="IP"', '117.41.38.29<']
second_ip = result.split('>')[-1][:-1]
print(first_ip, second_ip)  # 117.41.38.19 117.41.38.29

# 3. 利用re.compile
pattern = r'<td.*?>(.*?)<'  # ()中的内容就是要获取的内容
result = re.compile(pattern, re.S).findall(html)
print(result)   # ['117.41.38.19', '117.41.38.29'] (放在列表里)

# 正则的两种匹配模式,贪婪模式/非贪婪模式
# 假设存在下列网页结构
html = '''
    <html>
        <div class="application" id="book">
            <book><p>c语言</p></book>
            <book><p>python从入门到精通</p></book>
            <book><p>mongoDB精选</p></book>
        </div>
    </html>
'''
# 贪婪模式(一次匹配中尽可能 多 的匹配)
# 需求:匹配所有书籍
# 贪1:获取最后一本书 div  1个(.*)
pattern = r'<div.*p>(.*)</p>'
print(re.compile(pattern, re.S).findall(html))  # ['mongoDB精选']
# 贪2:获取所有书籍 div  3个(.*)
pattern = r'<div.*p>(.*)</p>.*p>(.*)</p>.*p>(.*)</p>'  # .*是一个整体     p>(.*)</p> 是一个整体
print(re.compile(pattern, re.S).findall(html))  # [('c语言', 'python从入门到精通', 'mongoDB精选')]
# 贪3:获取最后一本书 book  1个(.*)
pattern = r'<book.*p>(.*)</p>'
print(re.compile(pattern, re.S).findall(html))  # ['mongoDB精选']
# 贪4:获取所有书籍 book  3个(.*)
pattern = r'<book.*p>(.*)</p>.*p>(.*)</p>.*p>(.*)</p>'
print(re.compile(pattern, re.S).findall(html))  # [('c语言', 'python从入门到精通', 'mongoDB精选')]

# 非贪婪模式,一次匹配中尽可能的 少 匹配     格式:.*后加上?
# 非贪1:获取所有书籍 div (与贪婪模式效果相同)
pattern = r'<div.*?p>(.*?)</p>'
print(re.compile(pattern, re.S).findall(html))  #['c语言']

# 非贪2:获取所有书籍 div (与贪婪模式效果相同)
pattern = r'<div.*?p>(.*?)</p>.*?p>(.*?)</p>.*?p>(.*?)</p>'
print(re.compile(pattern, re.S).findall(html))  # [('c语言', 'python从入门到精通', 'mongoDB精选')]

# 非贪3:获取所有书籍 book(最好的方法)
pattern = r'<book.*?p>(.*?)</p>'
print(re.compile(pattern, re.S).findall(html))  # ['c语言', 'python从入门到精通', 'mongoDB精选']

 

任务3:完成快代理网站的正则解析。

import json
import requests
import re
import time

"""
<thead>
              <tr>
                <th>IP</th>
                <th>PORT</th>
                <th>匿名度</th>
                <th>类型</th>
                <th>位置</th>
                <th>响应速度</th>
                <th>最后验证时间</th>
              </tr>
            </thead>
            <tbody>
                
                <tr>
                    <td data-title="IP">120.24.76.81</td>
                    <td data-title="PORT">8123</td>
                    <td data-title="匿名度">高匿名</td>
                    <td data-title="类型">HTTP</td>
                    <td data-title="位置">广东省深圳市 阿里云计算有限公司 阿里云</td>
                    <td data-title="响应速度">5秒</td>
                    <td data-title="最后验证时间">2023-01-07 23:31:01</td>
                </tr>
                
                <tr>
                    <td data-title="IP">202.109.157.66</td>
                    <td data-title="PORT">9000</td>
                    <td data-title="匿名度">高匿名</td>
                    <td data-title="类型">HTTP</td>
                    <td data-title="位置">江西省赣州市  电信</td>
                    <td data-title="响应速度">0.6秒</td>
                    <td data-title="最后验证时间">2023-01-07 22:31:01</td>
                </tr>
                
                <tr>
                    <td data-title="IP">210.5.10.87</td>
                    <td data-title="PORT">53281</td>
                    <td data-title="匿名度">高匿名</td>
                    <td data-title="类型">HTTP</td>
                    <td data-title="位置">中国 上海  联通</td>
                    <td data-title="响应速度">5秒</td>
                    <td data-title="最后验证时间">2023-01-07 21:31:01</td>
                </tr>
                
                <tr>
                    <td data-title="IP">113.124.86.24</td>
                    <td data-title="PORT">9999</td>
                    <td data-title="匿名度">高匿名</td>
                    <td data-title="类型">HTTP</td>
                    <td data-title="位置">中国 山东 烟台 电信</td>
                    <td data-title="响应速度">0.6秒</td>
                    <td data-title="最后验证时间">2023-01-07 20:31:01</td>
                </tr>
                
                <tr>
                    <td data-title="IP">121.13.252.62</td>
                    <td data-title="PORT">41564</td>
                    <td data-title="匿名度">高匿名</td>
                    <td data-title="类型">HTTP</td>
                    <td data-title="位置">广东省东莞市  电信</td>
                    <td data-title="响应速度">4秒</td>
                    <td data-title="最后验证时间">2023-01-07 19:31:01</td>
                </tr>
                
                <tr>
                    <td data-title="IP">112.14.47.6</td>
                    <td data-title="PORT">52024</td>
                    <td data-title="匿名度">高匿名</td>
                    <td data-title="类型">HTTP</td>
                    <td data-title="位置">浙江省宁波市  移动</td>
                    <td data-title="响应速度">8秒</td>
                    <td data-title="最后验证时间">2023-01-07 18:31:02</td>
                </tr>
                
                <tr>
                    <td data-title="IP">222.74.73.202</td>
                    <td data-title="PORT">42055</td>
                    <td data-title="匿名度">高匿名</td>
                    <td data-title="类型">HTTP</td>
                    <td data-title="位置">内蒙古自治区赤峰市  电信</td>
                    <td data-title="响应速度">1秒</td>
                    <td data-title="最后验证时间">2023-01-07 17:31:01</td>
                </tr>
                
                <tr>
                    <td data-title="IP">121.13.252.58</td>
                    <td data-title="PORT">41564</td>
                    <td data-title="匿名度">高匿名</td>
                    <td data-title="类型">HTTP</td>
                    <td data-title="位置">广东省东莞市  电信</td>
                    <td data-title="响应速度">1秒</td>
                    <td data-title="最后验证时间">2023-01-07 16:31:01</td>
                </tr>
                
                <tr>
                    <td data-title="IP">182.34.17.104</td>
                    <td data-title="PORT">9999</td>
                    <td data-title="匿名度">高匿名</td>
                    <td data-title="类型">HTTP</td>
                    <td data-title="位置">中国 山东 烟台 电信</td>
                    <td data-title="响应速度">1秒</td>
                    <td data-title="最后验证时间">2023-01-07 15:31:01</td>
                </tr>
                
                <tr>
                    <td data-title="IP">117.114.149.66</td>
                    <td data-title="PORT">55443</td>
                    <td data-title="匿名度">高匿名</td>
                    <td data-title="类型">HTTP</td>
                    <td data-title="位置">北京市海淀区 BJENET宽带网络 BGP多线</td>
                    <td data-title="响应速度">3秒</td>
                    <td data-title="最后验证时间">2023-01-07 14:31:01</td>
                </tr>
                
                <tr>
                    <td data-title="IP">202.109.157.60</td>
                    <td data-title="PORT">9000</td>
                    <td data-title="匿名度">高匿名</td>
                    <td data-title="类型">HTTP</td>
                    <td data-title="位置">江西省赣州市  电信</td>
                    <td data-title="响应速度">0.1秒</td>
                    <td data-title="最后验证时间">2023-01-07 13:31:01</td>
                </tr>
                
                <tr>
                    <td data-title="IP">27.42.168.46</td>
                    <td data-title="PORT">55481</td>
                    <td data-title="匿名度">高匿名</td>
                    <td data-title="类型">HTTP</td>
                    <td data-title="位置">中国 广东 中山 联通</td>
                    <td data-title="响应速度">2秒</td>
                    <td data-title="最后验证时间">2023-01-07 12:31:01</td>
                </tr>
                
                <tr>
                    <td data-title="IP">121.13.252.61</td>
                    <td data-title="PORT">41564</td>
                    <td data-title="匿名度">高匿名</td>
                    <td data-title="类型">HTTP</td>
                    <td data-title="位置">广东省东莞市  电信</td>
                    <td data-title="响应速度">4秒</td>
                    <td data-title="最后验证时间">2023-01-07 11:31:02</td>
                </tr>
                
                <tr>
                    <td data-title="IP">183.236.232.160</td>
                    <td data-title="PORT">8080</td>
                    <td data-title="匿名度">高匿名</td>
                    <td data-title="类型">HTTP</td>
                    <td data-title="位置">中国 广东 江门 移动</td>
                    <td data-title="响应速度">6秒</td>
                    <td data-title="最后验证时间">2023-01-07 10:31:01</td>
                </tr>
                
                <tr>
                    <td data-title="IP">117.41.38.16</td>
                    <td data-title="PORT">9000</td>
                    <td data-title="匿名度">高匿名</td>
                    <td data-title="类型">HTTP</td>
                    <td data-title="位置">江西省赣州市  电信</td>
                    <td data-title="响应速度">0.4秒</td>
                    <td data-title="最后验证时间">2023-01-07 09:31:01</td>
                </tr>
                
            </tbody>
        </table>
"""
# 地址分析
# 第一页:https://www.kuaidaili.com/free/inha/1/
# 第二页:https://www.kuaidaili.com/free/inha/2/
# 第三页:https://www.kuaidaili.com/free/inha/3/
class QuickProxy:
    """
    快代理爬虫
    """
    def __init__(self):
        """初始化方法"""
        # 请求地址
        self.url = 'https://www.kuaidaili.com/free/inha/{}/'
        # 请求头
        self.header = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"}
        # 数据源
        self.data = []

    def get_response(self, url):  # 此处的url为构造好的url,不是self.url
        """发送请求地址并获取响应"""
        return requests.get(url, headers=self.header).content.decode('utf-8')

    def parse_data(self, html):
        """解析数据"""
        # print(html)  如下所示:
        """
        <tr>
                    <td data-title="IP">202.109.157.67</td>
                    <td data-title="PORT">9000</td>
                    <td data-title="匿名度">高匿名</td>
                    <td data-title="类型">HTTP</td>
                    <td data-title="位置">中国 江西 赣州 电信</td>
                    <td data-title="响应速度">0.4秒</td>
                    <td data-title="最后验证时间">2023-01-08 01:31:01</td>
                </tr>
        """
        # 1.定义请求规则
        pattern = r'<tr.*?title="IP">(.*?)</td>.*?"PORT">(.*?)</td>.*?"类型">(.*?)</td>'
        # .*?是一个整体   title="IP">(.*?)</td>是一个整体   "PORT">(.*?)</td>是一个整体   "类型">(.*?)</td>是一个整体
        # 2.根据规则提取数据
        results = re.compile(pattern, re.S).findall(html)
        # print(results)  如下所示:
        """
        [('121.13.252.60', '41564', 'HTTP'), ('120.24.76.81', '8123', 'HTTP'), ('113.124.86.24', '9999', 'HTTP'), ('210.5.10.87', '53281', 'HTTP'), ('121.13.252.62', '41564', 'HTTP'), ('112.14.47.6', '52024', 'HTTP'), ('117.41.38.19', '9000', 'HTTP'), ('222.74.73.202', '42055', 'HTTP'), ('121.13.252.58', '41564', 'HTTP'), ('117.114.149.66', '55443', 'HTTP'), ('27.42.168.46', '55481', 'HTTP'), ('121.13.252.61', '41564', 'HTTP'), ('183.236.232.160', '8080', 'HTTP'), ('61.216.156.222', '60808', 'HTTP'), ('61.216.185.88', '60808', 'HTTP')]
[('121.13.252.60', '41564', 'HTTP'), ('120.24.76.81', '8123', 'HTTP'), ('202.109.157.66', '9000', 'HTTP'), ('210.5.10.87', '53281', 'HTTP'), ('113.124.86.24', '9999', 'HTTP'), ('121.13.252.62', '41564', 'HTTP'), ('112.14.47.6', '52024', 'HTTP'), ('222.74.73.202', '42055', 'HTTP'), ('121.13.252.58', '41564', 'HTTP'), ('182.34.17.104', '9999', 'HTTP'), ('117.114.149.66', '55443', 'HTTP'), ('202.109.157.60', '9000', 'HTTP'), ('27.42.168.46', '55481', 'HTTP'), ('121.13.252.61', '41564', 'HTTP'), ('183.236.232.160', '8080', 'HTTP')]
        """
        # 3.保护机制
        if len(results) == 0:
            print('没有提取出结果,请检查html或正则表达式pattern!')
            return
        # 4.遍历
        for result in results:
            # 4.1 建立 字典 数据存储模型
            model = dict()
            model[result[2]] = result[0] + ":" + result[1]  # model中内容格式为:{"HTTP": "121.13.252.60:41564"}...
            # 4.2 将存储好的数据放到数据源中
            self.data.append(model)

    def write_to_json(self):
        """写到文件中"""
        # 1.定义字典
        temp = {"data": self.data}  # self.data数据源为一个列表[],里面放字典model{}
        # 2.将字典对象temp转化为json字符串
        content = json.dumps(temp, ensure_ascii=False, indent=4)
        # 3.写入文件
        with open('./代理/proxy.json', 'w', encoding='utf-8') as f:
            f.write(content)

    def run(self, page_index):
        """爬虫启动程序"""
        # 拼接请求地址
        for index in range(1, page_index + 1):  # 爬取3页内容
            # 构造地址
            url = self.url.format(index)
            # 发送请求并获取响应
            html = self.get_response(url)
            # 解析数据
            self.parse_data(html)
            # 增加一个时间间隔
            time.sleep(1.0)
        # 写入json文件中
        self.write_to_json()


if __name__ == '__main__':
    QuickProxy().run(page_index=3)
    print('已成功保存到proxy.json中!')

 

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值