python渗透工具编写学习笔记:10、网络爬虫基础/多功能编写

目录

前言

[10.1 概念](#10.1 概念)

[10.2 调度器/解析器](#10.2 调度器/解析器)

[10.3 存储器/去重器](#10.3 存储器/去重器)

[10.4 日志模块](#10.4 日志模块)

[10.5 反爬模块](#10.5 反爬模块)

[10.6 代理模块](#10.6 代理模块)


前言

在渗透工具中,网络爬虫有着不可忽视的作用,它能够快速而精准的搜寻、提取我们所需要的信息并按照我们所需要的格式排列,那么今天我们就来学习使用python编写实用的爬虫吧!**坚持科技向善,勿跨越法律界限,代码仅供教学目的。**初出茅庐,如有错误望各位不吝赐教。

10.1 概念

网络爬虫是指自动访问互联网上的网页并提取相关信息的程序。Python是一种常用的编程语言,可以用来编写网络爬虫。Python爬虫的架构通常包括以下几个组件:

  1. 调度器(Scheduler):负责管理爬取的URL队列,将待爬取的URL添加到队列中,并根据一定的策略从队列中取出URL进行爬取。

  2. 下载器(Downloader):负责下载URL对应的网页内容,并将下载结果返回给爬虫程序。

  3. 解析器(Parser):负责解析下载下来的网页内容,提取出需要的数据。

  4. 存储器(Storage):负责将解析出的数据进行存储,可以是保存到数据库中、写入文件等。

  5. 去重器(Deduplicator):负责对已下载的URL进行去重,避免重复的爬取。

  6. 调度器、下载器、解析器、存储器之间一般通过消息队列、数据库等通信机制进行交互。

在实际的爬虫项目中,爬虫的整体流程为:调度器从URL队列中取出一个URL,交给下载器下载该URL对应的网页内容,下载完成后将结果交给解析器进行解析,提取出需要的数据,并交给存储器进行存储。同时,去重器会对已下载的URL进行去重,避免重复爬取。

10.2 调度器/解析器

网络爬虫是指自动访问互联网上的网页并提取相关信息的程序。Python是一种常用的编程语言,也可以用来编写网络爬虫。

我们用Python编写一个简单的爬虫调度器:

在Python中,你可以使用requests库来发送HTTP请求获取网页内容,使用BeautifulSoup库来解析网页内容。

python 复制代码
import requests
from bs4 import BeautifulSoup

发送请求获取网页内容:使用requests库发送HTTP请求并获取网页内容。

python 复制代码
url = "https://www.example.com"  # 要爬取的网页地址
response = requests.get(url)
html = response.text  # 获取网页内容

要学习如何编写爬虫的解析器,我们需要先学习正则表达式的编写:

正则表达式是一种用来匹配字符串的工具,可以用来搜索、替换和提取字符串中的特定模式。在Python中,正则表达式的相关函数和模块被封装在re模块中。

下面我们再来学习编写爬虫的解析器,用于筛选出我们需要的信息。我们可以使用re模块来进行字符串的正则表达式匹配。下面是一些常用的re模块函数:

  1. re.match(pattern, string, flags=0):

    • 函数用于尝试从字符串的起始位置匹配一个模式。
    • 如果匹配成功,返回一个匹配对象;如果匹配失败,返回None。
    • pattern:要匹配的正则表达式模式。
    • string:要匹配的字符串。
    • flags:可选参数,用于控制匹配的模式。
  2. re.search(pattern, string, flags=0):

    • 函数用以在字符串中搜索匹配的第一个位置,返回一个匹配对象。
    • pattern:要匹配的正则表达式模式。
    • string:要匹配的字符串。
    • flags:可选参数,用于控制匹配的模式。
  3. re.findall(pattern, string, flags=0):

    • 函数用以在字符串中搜索匹配的所有位置,返回一个列表。
    • pattern:要匹配的正则表达式模式。
    • string:要匹配的字符串。
    • flags:可选参数,用于控制匹配的模式。

下面是一个示例,演示如何使用re模块来匹配字符串:

python 复制代码
import re

# 匹配字符串中的数字
pattern = r'\d+'
string = 'abc123def456ghi'

# 使用re.search()匹配第一个数字
match = re.search(pattern, string)
if match:
    print(f'Matched: {match.group()}')  # 输出:Matched: 123

# 使用re.findall()匹配所有数字
matches = re.findall(pattern, string)
if matches:
    print(f'All Matches: {matches}')  # 输出:All Matches: ['123', '456']

在上面的示例中,使用正则表达式模式r'\d+'匹配字符串中的数字。首先使用re.search()函数匹配第一个数字,然后使用re.findall()函数匹配所有数字。输出结果显示匹配到的数字。


学会了re模块的主要函数,接下来我们来学习正则表达式筛选条件的编写:

  1. 字符匹配

    • 字符:使用普通字符直接匹配,例如匹配字符串 "hello",可以使用正则表达式 "hello"。
    • 句点(.):匹配任意一个字符,除了换行符(\n)。
    • 字符集([]):匹配方括号中的任意一个字符。例如,[aeiou] 匹配任意一个元音字母。
    • 转义字符(\):用来匹配特殊字符。例如,匹配圆括号字符,可以使用 "("。
    • 重复次数:用于指定一个字符的重复次数。例如,a{3} 匹配 "aaa"。
    • 元字符(\d、\w、\s):用于匹配特定类型的字符。例如,\d 匹配任意一个数字字符。
  2. 边界匹配

    • 开始位置(^):匹配字符串的开始位置。
    • 结束位置($):匹配字符串的结束位置。
  3. 重复匹配

    • 重复(*):匹配前面的元素0次或多次。
    • 加号(+):匹配前面的元素1次或多次。
    • 问号(?):匹配前面的元素0次或1次。
    • 花括号({}):匹配前面的元素指定的次数范围。例如,a{2,4} 匹配 "aa"、"aaa"、"aaaa"。
  4. 分组和捕获

    • 圆括号(()):用于分组的目的。例如,(ab)+ 匹配 "ab"、"abab"、"ababab"。
    • 捕获组(\1、\2、\3...):用于引用分组中的内容。例如,(\w+)\s+\1 匹配 "hello hello"。
  5. 特殊序列

    • \d:匹配任意一个数字字符。等价于 [0-9]。
    • \D:匹配任意一个非数字字符。等价于 [^0-9]。
    • \w:匹配任意一个字母、数字或下划线字符。等价于 [a-zA-Z0-9_]。
    • \W:匹配任意一个非字母、数字或下划线字符。等价于 [^a-zA-Z0-9_]。
    • \s:匹配任意一个空白字符,包括空格、制表符、换行符等。
    • \S:匹配任意一个非空白字符。

以上是正则表达式的一些常用语法,我们再来看看爬虫常用的筛选条件:

python 复制代码
soup = BeautifulSoup(html, "html.parser")  # 使用html.parser解析器解析网页内容
# 提取需要的信息
title = soup.title.text  # 提取网页标题
links = soup.find_all("a")  # 提取所有链接
 

10.3 存储器/去重器

完成了调度器与解析器的编写,我们再来看三要素里的最后一个:爬虫的存储器。它用于将爬取完成后的数据储存起来,下面我们利用python的文件写入方法来对数据进行储存,并将提取的信息保存到文件或数据库中。

python 复制代码
# 保存到文件
with open("output.txt", "w") as f:
    f.write(title)
    for link in links:
        f.write(link.get("href"))

好了!我们已经写出了网络爬虫最主要的三个部分,接下来是时候为它添加上更加丰富的功能了,为了使我们的爬虫不会爬取相同的网页,我们来编写一个爬虫的去重器。以下是爬虫去重器的示例代码:

python 复制代码
import hashlib

def get_md5(url):
    """
    计算URL的MD5值
    """
    if isinstance(url, str):
        url = url.encode("utf-8")
    m = hashlib.md5()
    m.update(url)
    return m.hexdigest()

class Deduplicator:
    def __init__(self):
        self.visited_urls = set()
    
    def is_visited(self, url):
        """
        判断URL是否已经被访问过
        """
        url_md5 = get_md5(url)
        if url_md5 in self.visited_urls:
            return True
        else:
            self.visited_urls.add(url_md5)
            return False

使用方法:

python 复制代码
deduplicator = Deduplicator()
url = "http://example.com"

if deduplicator.is_visited(url):
    print("URL已被访问过")
else:
    print("URL未被访问过")

以上代码中,get_md5函数用于计算URL的MD5值,将其作为唯一的标识。Deduplicator类用于存储已经访问过的URL,通过调用is_visited方法判断URL是否已经被访问过。如果URL已被访问过,则返回True;如果URL未被访问过,则将其MD5值添加到已访问集合中,并返回False。

10.4 日志模块

日志模块,可以使我们的爬虫爬取日志信息,提取不同级别的日志,编写Python爬虫的日志模块可以使用Python内置的logging模块来实现。下面是一个简单示例:

python 复制代码
import logging

# 创建日志对象
logger = logging.getLogger('crawler')
logger.setLevel(logging.DEBUG)

# 创建文件handler,用于将日志写入文件
file_handler = logging.FileHandler('crawler.log')
file_handler.setLevel(logging.DEBUG)

# 创建控制台handler,用于在控制台输出日志
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO)

# 定义日志格式
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
file_handler.setFormatter(formatter)
console_handler.setFormatter(formatter)

# 将handler添加到日志对象中
logger.addHandler(file_handler)
logger.addHandler(console_handler)

以上代码创建了一个名为'crawler'的日志对象,并设置了日志级别为DEBUG,即最低级别的日志会输出到文件和控制台。可以根据需求进行调整日志级别。

接下来,可以在爬虫代码中使用日志对象来记录日志信息。例如:

python 复制代码
url = 'http://example.com'

try:
    # 爬取数据的代码
    logger.debug(f'Start crawling url: {url}')
    
    # ...
    
    # 爬取成功的日志信息
    logger.info(f'Successfully crawled url: {url}')
except Exception as e:
    # 爬取失败的日志信息
    logger.error(f'Failed to crawl url: {url}. Error message: {str(e)}')

以上代码会在开始爬取URL和成功爬取URL时分别记录DEBUG级别和INFO级别的日志信息,如果爬取过程中出现异常,则会记录ERROR级别的日志信息,并将异常信息作为日志消息的一部分。所有日志信息会同时输出到文件和控制台。

这样,就完成了一个简单的Python爬虫日志模块的编写。我们可以根据实际需求对日志模块进行扩展和优化,例如添加日志文件的切割、设置日志文件大小等。

10.5 反爬模块

当遇到反爬机制时,我们可以使用Python编写一些反爬模块来应对。这些模块可以帮助我们绕过一些常见的反爬手段,如User-Agent检测、验证码识别、IP封锁等。

以下是一个示例,演示了如何使用Python的requests库和验证码识别库tesseract来实现一个简单的反爬模块:

python 复制代码
import requests
from PIL import Image
import pytesseract

# 请求头,可以根据具体的网站进行调整
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3'}

# 请求网页,可以添加其他参数,如代理IP等
response = requests.get('http://example.com', headers=headers)

# 如果返回的响应中有验证码图片,可以使用Pillow库来处理
if 'captcha' in response.text:
    # 找到验证码图片的URL
    captcha_url = 'http://example.com/captcha.jpg'
    captcha_response = requests.get(captcha_url, headers=headers)

    # 保存验证码图片到本地
    with open('captcha.jpg', 'wb') as f:
        f.write(captcha_response.content)

    # 使用tesseract来识别验证码
    captcha = pytesseract.image_to_string(Image.open('captcha.jpg'))

    # 构建包含验证码的表单数据
    data = {
        'captcha': captcha,
        # 其他表单数据...
    }

    # 提交包含验证码的表单数据
    response = requests.post('http://example.com/submit', data=data, headers=headers)

# 处理响应内容
# ...

注:这只是一个简单的示例,实际应用时可能需要根据具体的反爬机制进行具体调整和优化。此外,还可以考虑使用代理IP池、使用多个账号轮流访问等更复杂的反爬策略。

10.6 代理模块

最后,我们再来使用Python编写爬虫的代理模块:

python 复制代码
import requests

# 使用代理IP访问网页
def request_with_proxy(url, proxies):
    try:
        # 使用get方法发送请求
        response = requests.get(url, proxies=proxies)
        # 返回响应内容
        return response.text
    except requests.exceptions.RequestException as e:
        print('Error:', e)

# 获取代理IP
def get_proxy():
    try:
        # 代理IP的API地址
        api_url = 'http://api.ip.data5u.com/dynamic/get.html?order=YOUR_ORDER_NUMBER&ttl=1&json=1'
        response = requests.get(api_url)
        # 解析返回的JSON数据
        data = response.json()
        # 提取代理IP和端口号
        proxy_ip = data['data'][0]['ip']
        proxy_port = data['data'][0]['port']
        # 构造代理IP字典
        proxy = {
            'http': f'http://{proxy_ip}:{proxy_port}',
            'https': f'https://{proxy_ip}:{proxy_port}',
        }
        return proxy
    except requests.exceptions.RequestException as e:
        print('Error:', e)

# 测试代理IP是否可用
def test_proxy(proxy):
    try:
        # 使用httpbin.org作为测试目标网站
        url = 'http://httpbin.org/ip'
        response = requests.get(url, proxies=proxy)
        # 解析返回的JSON数据
        data = response.json()
        # 提取IP地址
        ip = data['origin']
        print('Proxy IP:', ip)
    except requests.exceptions.RequestException as e:
        print('Error:', e)

# 主函数
def main():
    # 获取代理IP
    proxy = get_proxy()
    if proxy:
        # 测试代理IP是否可用
        test_proxy(proxy)
        # 使用代理IP访问网页
        url = 'https://www.example.com'
        html = request_with_proxy(url, proxy)
        print(html)

if __name__ == '__main__':
    main()

确保将YOUR_ORDER_NUMBER替换为在代理IP网站上获得的订单号。在上述代码中,我们使用httpbin.org作为测试网站,可以将url变量替换为任何想要访问的实际网站。

好了,到这里就是今天的全部内容了,如有帮助不胜荣幸。

相关推荐
网络空间小黑1 小时前
TCP/IP 知识体系
网络·网络协议·tcp/ip·计算机网络·5g·wireshark·信息与通信
LuckyTHP1 小时前
java 使用zxing生成条形码(可自定义文字位置、边框样式)
java·开发语言·python
Dotrust东信创智1 小时前
面向SDV的在环测试深度解析——仿真中间件SIL KIT应用篇
网络·中间件·汽车
leoufung3 小时前
ECPF 简介
linux·网络·kernel
mahuifa3 小时前
(7)python开发经验
python·qt·pyside6·开发经验
小Tomkk3 小时前
2025年PMP 学习十五 第10章 项目资源管理
学习·pmp·项目pmp
oceanweave3 小时前
【K8S学习之生命周期钩子】详细了解 postStart 和 preStop 生命周期钩子
学习·kubernetes
学地理的小胖砸4 小时前
【Python 操作 MySQL 数据库】
数据库·python·mysql
安迪小宝4 小时前
6 任务路由与负载均衡
运维·python·celery
Blossom.1184 小时前
使用Python实现简单的人工智能聊天机器人
开发语言·人工智能·python·低代码·数据挖掘·机器人·云计算