【爬虫】文本爬取思路

该博客主要介绍使用Python实现完本小说爬取并写入txt文本的方法。先分析章节页面获取所有章节网址,再探讨爬取某一章节正文和标题的方式,还提及写入txt文本的操作及基本反反爬措施,最后给出总的代码和运行效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1、实现目的:

2、分析

1、分析章节页面:怎么才能获取纯洁的所有的章节网址

输出:成功获取所有链接所构成的列表

2、怎么爬取某一章节的正文和标题?

3、怎么写入txt文本

4、基本反反爬措施

4、总的代码:

5、运行效果


1、实现目的:

爬取完本小说并将其写入txt文本中

2、分析

1、分析章节页面:怎么才能获取纯洁的所有的章节网址

 假设正文标签如下

通过分析可知,连接全部存放在此标签下

<ul class="links" >.........

<li class=" link">

<a href="https://xxxxxx.html" target="_blank" title="第一章 xxxx ">第一章 xxxx</a>
                        </li>

且都放在  li 中

那么怎么获取?

def getTarget(t):
    targets = []
    req = requests.get(t,headers=headers).content.decode('utf-8')
    soup = BeautifulSoup(req, "html.parser")
    links = soup.find('ul', class_='links').find_all('a')
    for link in links:
        # print(link.get('href'))
        targets.append(link.get('href'))
    return targets

输出:成功获取所有链接所构成的列表

2、怎么爬取某一章节的正文和标题?

通过审查元素分析正文和标题所在标签:

发现都在div标签下的class=“reader-box下的p标签中

章节名在此之下的class="title”下

正文内容在此之下的class=“content"下

# 获取文本
def getContent(urls):
    contents = []
    index = 1
    for url in urls:
        print("第{}章正在下载。。。".format(index))
        req = requests.get(url, headers=headers, timeout=100).content.decode('utf-8')
        soup = BeautifulSoup(req, "html.parser")

        t = soup.find('div', class_='reader_box')
        name = t.find('div', class_='title').text
        content = t.find('div', class_='content').text.replace("     ", '\n')
        contents.append(name + '\n' + content)  # 返回章节名和正文
        index += 1
    print("下载完成,正在写入txt文本...")
    return contents

3、怎么写入txt文本

def Download():
    contents = getContent(getTarget(target))
    with open("文本.txt", 'a') as f:
        for content in contents:
            f.writelines(content)
            f.write('\n')
            f.write('********************************')
            f.write('\n')
    f.close()
    print("写入成功!请在本目录查找小说文件")

4、基本反反爬措施

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) 。。。。。。。",
    "authority": "xxx.com",
}

头文件和休眠时间的设置

4、总的代码:

# -*- coding: utf-8 -*-
"""
@File  : 多章节小说爬取.py
@author: FxDr
@Time  : 2022/10/30 0:52
"""
import random

import requests
from bs4 import BeautifulSoup

url = 'https://xxxxx.html' # 第一章地址
target = 'http://xxxxxxx.html'  # 目录页

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) 。。。。。。",
    "authority": "xxxx.com",
}


# 获取文本
def getContent(urls):
    contents = []
    index = 1
    for url in urls:
        print("第{}章正在下载。。。".format(index))
        req = requests.get(url, headers=headers, timeout=100).content.decode('utf-8')
        soup = BeautifulSoup(req, "html.parser")

        t = soup.find('div', class_='reader_box')
        name = t.find('div', class_='title').text
        content = t.find('div', class_='content').text.replace("     ", '\n')
        contents.append(name + '\n' + content)  # 返回章节名和正文
        index += 1
    print("下载完成,正在写入txt文本...")
    return contents


def getTarget(t):
    targets = []
    req = requests.get(t, headers=headers).content.decode('utf-8')
    soup = BeautifulSoup(req, "html.parser")
    links = soup.find('ul', class_='links').find_all('a')
    for link in links:
        # print(link.get('href'))
        targets.append(link.get('href'))
    return targets


def Download():
    contents = getContent(getTarget(target))
    with open("文本.txt", 'a') as f:
        for content in contents:
            f.writelines(content)
            f.write('\n')
            f.write('********************************')
            f.write('\n')
    f.close()
    print("写入成功!请在本目录查找小说文件")


# print(getContent(url))
# print(getTarget(target))
Download()

5、运行效果

 文件下载如下:当前py文件所在文件夹下

文本.txt

<think>我们有一个需求:在前端Vue页面中实时展示Python爬虫爬取过程。 技术栈:前端Vue.js,后端SpringBoot,爬虫使用Python思路: 1. 爬虫执行过程中需要将实时日志(例如:当前爬取的URL、状态、进度等)发送出来。 2. 后端(SpringBoot)需要提供一个接口,让爬虫将日志推送到后端,同时后端还需要提供一个将日志推送给前端的机制(例如WebSocket)。 3. 前端Vue通过WebSocket连接到后端,实时接收并显示日志。 步骤分解: 一、爬虫端(Python): 在爬虫执行过程中,将关键步骤的日志信息通过HTTP请求或WebSocket发送给后端(SpringBoot)。 这里我们可以选择使用HTTP POST请求,因为实现简单,但实时性要求高的话,可以考虑WebSocket。不过考虑到爬虫可能同时有多个,且需要轻量级,我们可以使用消息队列(如RabbitMQ、Kafka)或者直接由后端提供一个REST接口接收日志,然后后端再通过WebSocket推送给前端。 但是为了简化,我们可以这样设计: - 爬虫每产生一条日志,就通过一个HTTP接口发送给后端。 - 后端将这个日志通过WebSocket广播给所有关注该爬虫任务的前端客户端。 二、后端(SpringBoot): 1. 提供一个REST接口,供爬虫发送日志。接口路径例如:`/api/log`,请求体包含日志内容、爬虫任务ID等。 2. 使用WebSocket将接收到的日志实时推送给前端。我们可以为每个爬虫任务创建一个主题(topic),或者使用一个全局的日志主题,前端通过订阅特定任务ID来接收日志。 具体实现: - 创建一个WebSocket配置类,启用WebSocket。 - 创建一个WebSocket处理器和拦截器(如果需要)。 - 创建一个REST控制器接收爬虫日志,然后通过WebSocket发送给前端。 三、前端(Vue): 1. 在需要显示日志的页面,建立WebSocket连接。 2. 发送一个订阅请求,指定要订阅的爬虫任务ID(如果有多个任务同时进行,需要区分)。 3. 接收WebSocket消息,将日志实时显示在页面上(例如,使用一个文本区域或列表)。 详细步骤: 后端实现(SpringBoot)的关键代码: 1. 添加WebSocket依赖(在pom.xml中): ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-websocket</artifactId> </dependency> ``` 2. 配置WebSocket: ```java import org.springframework.context.annotation.Configuration; import org.springframework.messaging.simp.config.MessageBrokerRegistry; import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; import org.springframework.web.socket.config.annotation.StompEndpointRegistry; import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer; @Configuration @EnableWebSocketMessageBroker public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { @Override public void configureMessageBroker(MessageBrokerRegistry config) { config.enableSimpleBroker("/topic"); // 客户端订阅路径的前缀 config.setApplicationDestinationPrefixes("/app"); // 客户端发送消息的前缀 } @Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/ws").setAllowedOriginPatterns("*").withSockJS(); } } ``` 3. 创建一个控制器接收爬虫日志,并转发到WebSocket: ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.messaging.simp.SimpMessagingTemplate; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; @RestController public class LogController { @Autowired private SimpMessagingTemplate messagingTemplate; @PostMapping("/api/log") public void sendLog(@RequestBody LogMessage logMessage) { // 将日志消息发送到WebSocket的主题,假设每个爬虫任务有一个唯一的taskId // 前端订阅了"/topic/logs/{taskId}",这里就发送到该主题 messagingTemplate.convertAndSend("/topic/logs/" + logMessage.getTaskId(), logMessage); } } // LogMessage类 public class LogMessage { private String taskId; private String content; // getters and setters } ``` 4. 爬虫端(Python)发送日志的示例代码(使用requests): ```python import requests import time task_id = "12345" # 假设任务ID # 模拟爬虫执行,发送日志 urls = ["http://example.com/page1", "http://example.com/page2", "http://example.com/page3"] for i, url in enumerate(urls): log = f"正在爬取:{url}" # 发送日志到后端 requests.post("http://后端地址/api/log", json={ "taskId": task_id, "content": log }) time.sleep(1) ``` 5. 前端Vue代码(使用SockJS和Stomp.js): 首先安装依赖:`npm install sockjs-client stompjs` 在Vue组件中: ```vue <template> <div> <div v-for="(log, index) in logs" :key="index">{{ log }}</div> </div> </template> <script> import SockJS from 'sockjs-client'; import Stomp from 'stompjs'; export default { data() { return { logs: [], taskId: '12345', // 当前爬虫任务ID stompClient: null }; }, mounted() { this.connect(); }, beforeDestroy() { this.disconnect(); }, methods: { connect() { const socket = new SockJS('http://后端地址/ws'); this.stompClient = Stomp.over(socket); this.stompClient.connect({}, () => { // 订阅主题 this.stompClient.subscribe(`/topic/logs/${this.taskId}`, (message) => { const logMessage = JSON.parse(message.body); this.logs.push(logMessage.content); }); }, (error) => { console.error('连接失败', error); }); }, disconnect() { if (this.stompClient) { this.stompClient.disconnect(); } } } }; </script> ``` 注意事项: - 跨域问题:后端需要配置允许跨域(WebSocket配置中已经设置了`setAllowedOriginPatterns("*")`)。 - 安全性:实际应用中,需要对任务ID进行验证,确保只有拥有权限的用户才能订阅对应的日志。 - 性能:如果日志量非常大,需要考虑前端显示的性能(比如只显示最近N条,或者使用虚拟滚动)。 这样,当爬虫执行时,发送日志到后端,后端通过WebSocket推送给前端,前端就可以实时显示爬虫的日志了。 相关问题: 1. 如何确保WebSocket连接的安全性? 2. 如果爬虫任务非常多,如何避免WebSocket消息过多导致服务器压力过大? 3. 前端如何同时显示多个爬虫任务的日志? 4. 如果用户刷新页面,如何恢复之前的日志(历史日志)?</think>### 前端 Vue 实时显示 Python 爬虫执行过程实现方案 #### 核心思路 通过 WebSocket 建立前后端双向通信通道,结合以下技术实现实时展示: 1. **Python 爬虫**:在关键节点推送状态数据 2. **SpringBoot 后端**:作为 WebSocket 服务端中转消息 3. **Vue 前端**:通过 WebSocket 客户端实时渲染数据流 ```mermaid sequenceDiagram participant Python爬虫 participant SpringBoot participant Vue前端 Python爬虫->>SpringBoot: 推送爬取状态(WebSocket) SpringBoot->>Vue前端: 转发实时数据(WebSocket) Vue前端->>用户界面: 动态渲染进度 ``` #### 一、Python 爬虫端实现(关键代码) ```python import websockets import asyncio async def send_progress(task_id, status): # 连接SpringBoot的WebSocket端点 async with websockets.connect("ws://后端地址/ws/progress") as ws: await ws.send(json.dumps({ "taskId": task_id, "status": status, # 如: "开始爬取", "解析完成" "progress": 75, # 百分比进度 "currentUrl": "https://example.com/page1" })) # 在爬虫关键节点调用 async def main_crawler(): await send_progress("task-123", "启动爬虫") # 爬取逻辑... await send_progress("task-123", "获取到50条数据") ``` #### 二、SpringBoot WebSocket 配置 ```java @Configuration @EnableWebSocketMessageBroker public class WebSocketConfig implements WebSocketMessageBrokerConfigurer { @Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/ws/progress") // Python连接端点 .setAllowedOriginPatterns("*"); registry.addEndpoint("/ws/client") // Vue连接端点 .setAllowedOriginPatterns("*") .withSockJS(); } @Override public void configureMessageBroker(MessageBrokerRegistry registry) { registry.enableSimpleBroker("/topic"); registry.setApplicationDestinationPrefixes("/app"); } } @Controller public class ProgressController { @MessageMapping("/crawler-progress") public void forwardProgress(ProgressMessage message) { // 将Python发来的消息广播给订阅的Vue客户端 messagingTemplate.convertAndSend( "/topic/progress/" + message.getTaskId(), message ); } } ``` #### 三、Vue 前端实现(核心代码) ```vue <template> <div> <div v-for="log in logs" :key="log.timestamp"> [{{ log.time }}] {{ log.taskId }}: {{ log.message }} <progress :value="log.progress" max="100"></progress> </div> </div> </template> <script> import SockJS from 'sockjs-client'; import Stomp from 'webstomp-client'; export default { data() { return { logs: [], stompClient: null } }, mounted() { this.connectWebSocket(); }, methods: { connectWebSocket() { const socket = new SockJS('/ws/client'); this.stompClient = Stomp.over(socket); this.stompClient.connect({}, () => { // 订阅特定爬虫任务进度通道 this.stompClient.subscribe( `/topic/progress/${this.taskId}`, message => { const log = JSON.parse(message.body); this.logs.push({ ...log, time: new Date().toLocaleTimeString() }); } ); }); } }, beforeDestroy() { if (this.stompClient) this.stompClient.disconnect(); } } </script> ``` #### 四、优化建议 1. **数据格式规范**: ```json { "taskId": "crawl-2023", "stage": "PARSING", // STARTED/DOWNLOADING/PARSING/SAVING "progress": 60, "currentUrl": "https://example.com/page5", "itemsCount": 120 } ``` 2. **可视化增强**: - 使用进度条组件(如 `vue-progress-bar`) - 不同状态显示不同颜色图标 - 实时统计面板(已爬页面/总页面) 3. **错误处理**: ```javascript // Vue中添加错误监听 this.stompClient.subscribe('/topic/errors', error => { this.$notify.error({ title: '爬虫异常', message: error.body }); }); ``` #### 注意事项 1. **跨域问题**:确保 SpringBoot 配置允许爬虫域名的 WebSocket 连接 2. **认证机制**:添加 JWT 认证保护 WebSocket 端点 3. **性能优化**:使用消息压缩(如 `permessage-deflate`) 4. **断线重连**:在 Vue 中实现 WebSocket 自动重连机制 > 系统采用 SpringBoot 作为后端框架,负责处理用户请求、数据分析和推荐算法的实现。前端使用 Vue.js 构建用户界面,提供友好的用户交互体验[^1]。这种架构特别适合实现实时数据监控场景。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值