爬虫获取一个网站内所有子页面的内容

上一篇介绍了如何爬取一个页面内的所有指定内容,本篇讲的是爬去这个网站下所有子页面的所有指定的内容。

可能有人会说需要的内容复制粘贴,或者直接f12获取需要的文件下载地址一个一个下载就行了,但是如下图十几个一级×几十个二级×一百多个疾病×几百个内容=不太想算下去的数量级…一个mp3一兆多的大小,就只算下载所有的mp3的话就已经是t级别的了,手动一个一个下载恐怕得几个月的不听操作,所以需要本篇介绍的多页面爬虫自动获取,好歹几天时间能自动爬完。

确认需求

在这里插入图片描述
我们要获取这个网站下每个的一级科室的每个二级科室的每个疾病下的每个问题及对应的医生回答的mp3语音文件和语音内容,点击每个问题得到的页面如下:
在这里插入图片描述
从这里就可以获取到我想要的:问题、医生、问题的回答语音mp3文件、语音内容。
首先确认一下思路:遍历每个一级–>遍历每个二级–>遍历每个疾病–>遍历每一页(如下图)–>点击每个内容进去–>获取问题、医生、mp3、内容
在这里插入图片描述
以上是大概的获取思路框架,接下来确认保存形式:每个一级为一个文件夹;在每个一级目录下面存放这个一级的所有二级目录;在每个二级下存放所有对应的疾病目录;在每个疾病目录下存放这个疾病下所有的mp3文件,文件名以“医生-问题”的格式保证不重复,每个疾病目录下只有一个txt文件,里面写入本目录下所有mp3的语音内容,为了后续能快速找到对应内容,给每个内容也加一个“医生-问题”格式的标题。如下图所示:
在这里插入图片描述
在这里插入图片描述

获取对应元素

再次捋一下我们所需要的是:问题、医生、mp3文件、语音内容,接下来开始获取这4个对应的网页元素,需要说明的是我们要获取的不仅只有这四个,这四个只是获取一个页面内容所需的元素,还需要找到每个一级、二级、疾病、下一页(换页)的元素才能自动获取这个网站所有的这4个内容。

这里需要注意,我们找的每个元素需要找的是在页面中唯一的元素,这样才不会出错。比如所有的一级都放在class为“a”的div标签下,但同样的标签有多个,那么可以再往上一层,发现class为“a”的div标签class为“b”的div标签 的标签下,再看一下 class为“b”的div标签 下的 class为“a”的div标签 这样的组合仅有一个,那这个组合才是我们所需要的元素。

一级科室

f12打开开发者模式,点击箭头选择元素:
在这里插入图片描述
这里需要做的是如何获取到这个< dd >标签下的所有< a >标签,经过我的筛选发现class为’yslist_dq’的< div >标签下的第一个< dl >标签的所有< a >标签即是所有的一级科室的元素,我们所需要的是a标签内的text文本内容(作为创建目录的目录名)以及标签的href属性值(用来跳转页面到下一个一级科室)。

二级科室

在这里插入图片描述
依旧是元素选择箭头点击任意一个二级科室,图片上可以发现class为’yslist_dq’的< div >标签下的第2个< dl >标签的所有< a >标签即是所有的二级科室的元素,选择标签内的文本内容和href属性值。

疾病筛选

在这里插入图片描述
同理可得class为’yslist_dq’的< div >标签下的第3个< dl >标签的所有< a >标签即是所有的疾病筛选的元素,选择文本内容和href属性值。

每个页面

这里的每个页面是获取我们所需要的问题、医生、mp3、语音内容这4个内容的页面。
在这里插入图片描述
元素选择箭头(以下开始简称箭头)选择点击任意一个医生头像(一个头像对应一个问题),点击方框内的网址就跳到对应的页面内容中:
在这里插入图片描述
那么页面的元素就是a标签的herf属性值,首先获取到这个a标签。
可以看到每个< li >标签为一个头像,这些< li >都在class为“cur05”的< ul >标签下,经验证class为“cur05”的< ul >标签下的< li >标签下的< a >标签为唯一组合,因为每个< li >标签下只有一个< a >标签,所以直接用class为“cur05”的< ul >标签下的所有< a >标签这个组合。

页面内容——问题

在这里插入图片描述
经验证图片所见的class为“v_title”的< h3 >标签是唯一的元素,则这个h3标签就是问题的元素,我们获取的是标签的文本内容。

页面内容——医生

在这里插入图片描述
class为“mgBottom10”的< ul >标签下的< strong >标签的文本内容。

页面内容——mp3文件

在这里插入图片描述
< audio >为唯一的标签,获取其src属性值。

页面内容——语音内容

在这里插入图片描述
class为“v_con”的< div >标签下的class为“text”的< div >标签的文本内容。

下一页

在这里插入图片描述
class为“pageyl”的< div >标签下的最后一个< li >标签的< a >标签的href属性值。

代码

代码介绍

1.代码的大概思路:就是在上文确认需求中所提到的,获取每个一级的text和href值,用文本创建目录,用href值跳转到遍历到的一级科室页面;同理二级和疾病;然后遍历到第3层的疾病之下,开始获取页面的每个头像对应的href值进行跳转,在跳转的页面中根据上文找到的元素获取我们需要的4个内容;然后点击下一页重复上一步操作,直到没有下一页了。
2.headers本来用的是我自己浏览器中获取到的,但是用一个headers一次性访问上万个页面有时候也会触发反爬机制导致中断,所以我多找几个人要了他们的headers,放入list中,每次跳转页面的时候都从中random选择一个,为了确保有够random随机种子值用当前时间戳。list中的每个headers除了user-agent也可以加入cookies减少中断概率(如第一个headers中的注释所示)。
3.因为一次性访问太多次有可能有时候访问一个页面不给响应,此时使用resolve()函数循环请求该网站,每次循环随机选择headers及延长响应时间。进行跳转页面时都进行捕获异常,只要有异常就调用resolve()。
4.即使做的绕过反爬机制的准备再充足,面对这么庞大的数据爬去也肯定会有各种因素导致的中断,如果爬了几天的数据忽然中断了,再继续只能重头开始的话人真的会崩溃。虽然只是交给机器来操作是机器花了这么久的功夫,但是我们花时间等也是挺废精力的哈哈哈。所以这里也要写一个断点续传的功能,从中断处开始继续爬取(代码中注释明显可一眼找到)。

代码实现

import random
import time
import requests
import os
from bs4 import BeautifulSouprandom.seed(int(time.time()))def resolve(url, headers_list):for i in range(5):  # 循环去请求网站headers = random.choice(headers_list)response = requests.get(url, headers=headers, timeout=20)if response.status_code == 200:breakreturn responsesave_root = "/home/alpha/桌面/results"
url = "https://www....."
# headers = {
#     "user-agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36"
# }
headers_list = [{# "Cookie":r"open_link_uuid=283daf44-d04e-49ae-bb47-3b8117d9e71f;utrace=23F72A5EEEB2DAFA0537A35D6848F563;Hm_lvt_8b53bc0f3e59f56a58a92a894280e28d=1693984791;open_link_uuid=47e1a39d-224f-4c45-b1a5-a6bdb84dce5b;Hm_lvt_8bb61372f543ea81f53e93693c2a7531=1694144572;Hm_lpvt_8b53bc0f3e59f56a58a92a894280e28d=1694425881","user-agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36"}, {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36 Edg/116.0.1938.76'}, {'user-agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0'}, {'user-agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:58.0) Gecko/20100101 Firefox/58.0'}, {'user-agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:88.0) Gecko/20100101 Firefox/88.0'}, {'user-agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.87 Safari/537.36 SE 2.X MetaSr 1.0'}, {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36'}, {'user-agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.54 Safari/537.36'}, {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Safari/537.36 Core/1.94.202.400 QQBrowser/11.9.5355.400'}, {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/115.0.0.0 Safari/537.36'}, {'user-agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Mobile Safari/537.36'}
]
headers = random.choice(headers_list)
try:response = requests.get(url=url, headers=headers)
except:response = resolve(url, headers_list)
soup = BeautifulSoup(response.text, 'html.parser')
div_yslist_dq = soup.find('div', class_='yslist_dq')
first_dl = div_yslist_dq.find('dl')
a_tags_1 = first_dl.find_all('a')
for a_tag_1 in a_tags_1:     # 一级科室href_1 = a_tag_1.get('href')title_1 = a_tag_1.text############################### 中断 从断点继续# if title_1 in ["内科", "外科"]:# 	continue############################### print(f'链接地址: {href_1}, 标题: {title_1}')first_level = os.path.join(save_root, title_1)if not os.path.exists(first_level):os.mkdir(first_level)url = "https://www.youlai.cn" + href_1headers = random.choice(headers_list)try:response = requests.get(url=url, headers=headers)except:response = resolve(url, headers_list)soup = BeautifulSoup(response.text, 'html.parser')div_yslist_dq = soup.find('div', class_='yslist_dq')first_dl = div_yslist_dq.findAll('dl')[1]a_tags_2 = first_dl.find_all('a')for a_tag_2 in a_tags_2:      # 二级科室href_2 = a_tag_2.get('href')title_2 = a_tag_2.textif title_2 == "全部":continue############################### 中断 从断点继续# if title_2 in ["消化内科", "心血管内科"]:# 	continue################################ print(f'链接地址: {href_2}, 标题: {title_2}')sec_level = os.path.join(first_level, title_2)if not os.path.exists(sec_level):os.mkdir(sec_level)# input()url = "https://www.youlai.cn" + href_2headers = random.choice(headers_list)try:response = requests.get(url=url, headers=headers)except:response = resolve(url, headers_list)soup = BeautifulSoup(response.text, 'html.parser')div_yslist_dq = soup.find('div', class_='yslist_dq')first_dl = div_yslist_dq.findAll('dl')[2]a_tags_3 = first_dl.find_all('a')for a_tag_3 in a_tags_3:      # 疾病筛选href_3 = a_tag_3.get('href')title_3 = a_tag_3.text############################### 中断 从断点继续# if title_3 in ["胃炎", "胃溃疡", "肝硬化", "便秘", "肠胃炎", "腹痛", "慢性腹泻", "胰腺炎", "消化不良", "慢性胃炎", "反流性食管炎"]:#     continue##############################if title_3 == "全部":continue# print(f'链接地址: {href_3}, 标题: {title_3}')third_level = os.path.join(sec_level, title_3)if not os.path.exists(third_level):os.mkdir(third_level)# print(href_3)url = "https://www.youlai.cn" + href_3headers = random.choice(headers_list)try:response = requests.get(url=url, headers=headers)except:response = resolve(url, headers_list)soup = BeautifulSoup(response.text, 'html.parser')page_num = soup.find('div', class_='pageyl').findAll("li")[-2].text# print(page_num)# input()for page in range(eval(page_num)):     # 遍历所有页数############################### 中断 从断点继续# print(page + 1)# if title_3 == "结肠炎" and page in [0, 1, 2]:#     page_url = "https://www.youlai.cn" + "/ask/voicelist/1_12_12_0_4.html"#     headers = random.choice(headers_list)#     try:#         response = requests.get(url=page_url, headers=headers)#     except:#         response = resolve(page_url, headers_list)#     soup = BeautifulSoup(response.text, 'html.parser')#     continue############################### 默认在第一页div_yslist_dq = soup.find('ul', class_='cur05')a_tags_4 = div_yslist_dq.findAll('a')for a_tag_4 in a_tags_4:       # 遍历每页的所有mp3href_4 = a_tag_4.get('href')title_4 = a_tag_4.text# print(f'链接地址: {href_4}, 标题: {title_4}')url = "https://www.youlai.cn" + href_4headers = random.choice(headers_list)try:response_4 = requests.get(url=url, headers=headers)except:response_4 = resolve(url, headers_list)soup_4 = BeautifulSoup(response_4.text, 'html.parser')mp3_tag = soup_4.find('audio')mp3_path = mp3_tag.get("src").strip()# while True:#     try:#         print(response_4.status_code)#         print(mp3_tag)#         mp3_path = mp3_tag.get("src").strip()#         break#     except AttributeError:#         print(headers)#         headers = random.choice(headers_list)#         time.sleep(5)#         print(headers)headers = random.choice(headers_list)try:mp3_content = requests.get(url=mp3_path, headers=headers).contentexcept:mp3_content = resolve(mp3_path, headers_list)mp3_title = soup_4.find('h3', class_='v_title').text.strip()print(mp3_title)if mp3_title[-1] == "?":mp3_title = mp3_title[:-1]doc_name = soup_4.find("ul", class_='mgBottom10').find("strong").text.strip()with open(third_level + "/" + doc_name + "-" + mp3_title + ".mp3", mode="wb") as f1:  # 下载每个mp3文件f1.write(mp3_content)print(mp3_path)mp3_text = soup_4.find('div', class_='v_con').find('div', class_='text').text.strip() + "\n"with open(third_level + "/" + "content.txt", mode="a") as f2:mp3_title = doc_name + "-" + mp3_title + "\n"f2.write(mp3_title)f2.writelines(mp3_text)print(mp3_text)# 点击下一页next_page = soup.find('div', class_='pageyl').findAll("li")[-1]next_page_title = next_page.textprint(next_page_title)if not next_page_title == "下一页":continuenext_page_href = next_page.find("a").get("href")print(next_page_href)page_url = "https://www.youlai.cn" + next_page_hrefheaders = random.choice(headers_list)try:response = requests.get(url=page_url, headers=headers)except:response = resolve(page_url, headers_list)soup = BeautifulSoup(response.text, 'html.parser')

实现效果

在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/143039.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Spring Cloud】认识微服务架构,拆分简单的 Demo 实现服务的远程调用

文章目录 前言一、认识微服务1.1 服务架构的演变&#xff1a;从单体到微服务单体架构分布式架构微服务架构 1.2 微服务技术的对比&#xff1a;Dubbo、Spring Cloud、Spring Cloud Alibaba技术对比公司需求的选择 1.3 Spring Cloud&#xff1a;微服务框架的精华什么是 Spring Cl…

工具篇 | WSL使用入门教程以及基于WSL和natApp内网穿透实践 - 对比VMWare

介绍 在开发工具中&#xff0c;Windows Subsystem for Linux (WSL) 和 VMWare 它们都可以实现了在 Windows 上运行 Linux系统。 文章概览 WSL Vs VMWare 我们将简单比对 WSL 和 VMWare&#xff0c;在性能、资源消耗等方面的差异&#xff0c;以协助您做出更加明确的选择。 …

数据结构与算法

目录 数据结构与算法 为什么要学习数据结构和算法&#xff1f; 常见的数据结构 常用算法 插入排序 一、概念及其介绍 二、适用说明 三、过程图示 希尔排序 一、概念及其介绍 二、适用说明 三、过程图示 归并排序 一、概念及其介绍 二、适用说明 三、过程图示 …

python抓取网页视频

1. 喜马拉雅音频 1-1 喜马拉雅 import requests import json import time import random import hashliburl https://www.ximalaya.com/revision/play/v1/audio?id46103875&ptype1headers { user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.3…

【量化】量化原理浅析

前言 模型在端侧运行时&#xff0c;会追求模型保持原有精度的同时&#xff0c;让模型的运行速度更快。基本方向为模型压缩和加速&#xff0c;着力于减少网络参数量、降低计算复杂度。可通过以下方式实现&#xff1a; 针对网络结构本身进行改进&#xff0c;常用的3x3的卷积的叠加…

从零搭建开发脚手架 顺应潮流开启升级 - SpringBoot 从2.x 升级到3.x

文章目录 涉及升级项导入包修改SpringBoot3.x中spring.factories功能被移除 涉及升级项 升级JDK 8 -> JDK17 Spring Boot 2.3.7 -> Spring Boot 3.1.3 Mysql5.7.x -> Mysql8.x Mybatis-Puls 3.4.2 -> 3.5.3 knife4j 2.x -> 4.3.x sa-token 1.24.x -> 1.…

基于Xilinx UltraScale+ MPSOC(ZU9EG/ZU15EG)的高性能PCIe数据预处理平台

PCIE707是一款基于PCIE总线架构的高性能数据预处理FMC载板&#xff0c;板卡具有1个FMC&#xff08;HPC&#xff09;接口&#xff0c;1路PCIe x4主机接口、1个RJ45千兆以太网口、2个QSFP 40G光纤接口。板卡采用Xilinx的高性能UltraScale MPSOC系列FPGA作为实时处理器&#xff0c…

vue3 - 使用 xlsx 库将数据导出到 Excel 文件

GitHub Demo 地址 在线预览 xlsx是由SheetJS开发的一个处理excel文件的JavaScript库。它可以读取、编写和操作 Excel 文件 安装xlsx npm install xlsx --save实现一个通过的数据导出工具类 import * as XLSX from xlsx/*** description: 导出excel* param {any} dataList* p…

公司新招了个字节拿36K的人,让我见识到了什么才是测试扛把子......

5年测试&#xff0c;应该是能达到资深测试的水准&#xff0c;即不仅能熟练地开发业务&#xff0c;而且还能熟悉项目开发&#xff0c;测试&#xff0c;调试和发布的流程&#xff0c;而且还应该能全面掌握数据库等方面的技能&#xff0c;如果技能再高些的话&#xff0c;甚至熟悉分…

枚举enum

使用enum关键字定义提供枚举类的对象&#xff0c;多个对象用逗号分开&#xff0c;结尾用分号结束提供构造方法&#xff0c;给属性赋值使用public statiac final来修饰是属性提供get方法提供toString方法 public enum Season {SPRING("春天", "春暖花开"),…

linux下解决tomcat错误问题

错误一&#xff1a; Linux下Tomcat启动报错&#xff1a;Neither the JAVA_HOME nor the JRE_HOME environment variable is defined 原因&#xff1a;可能是Linux环境变了&#xff0c;需要在catalina.sh文件里指定JDK路径 解决方式&#xff1a; 在/bin/catalina.sh配置文件中加…

CSS详细基础(二)文本样式

插播一条CSS的工作原理&#xff1a; CSS是一种定义样式结构如字体、颜色、位置等的语言&#xff0c;被用于描述网页上的信息格式化和显示的方式。CSS样式可以直接存储于HTML网页或者单独的样式单文件。无论哪一种方式&#xff0c;样式单包含将样式应用到指定类型的元素的规则。…

mySQL 安装

一、windows安装包下载 mysql官网提供了两种安装方式&#xff0c;一个是zip安装&#xff0c;另一个是msi安装&#xff0c;这里简绍第一种安装方式&#xff0c;第二种简单&#xff0c;不再简绍 官网下载&#xff0c;根据自己需要选择版本&#xff1a;MySQL :: MySQL Community…

C#设置自动关机

功能&#xff1a;自动设置电脑关机时间&#xff0c;可取消 创建一个shutdown函数&#xff0c;bool isCancle&#xff0c;传入值为ture就取消关机&#xff0c;interval间隔时间&#xff0c;unit不带符号的整型 private static void ShutdownPC(bool isCancel, uint interval){P…

【Java 进阶篇】数据定义语言(DDL)详解

数据定义语言&#xff08;DDL&#xff09;是SQL&#xff08;结构化查询语言&#xff09;的一部分&#xff0c;它用于定义、管理和控制数据库的结构和元素。DDL允许数据库管理员、开发人员和其他用户创建、修改和删除数据库对象&#xff0c;如表、索引、视图等。在本文中&#x…

数据备份文件生成--根据表名生成对应的sql语句文件

最近客户有个需求&#xff0c;希望在后台增加手动备份功能&#xff0c;将数据导出下载保存。 当然&#xff0c;此方法不适用于海量数据的备份&#xff0c;这只适用于少量数据的sql备份。 这是我生成的sql文件&#xff0c;以及sql文件里的insert语句&#xff0c;已亲测&#x…

Oracle物化视图(Materialized View)

与Oracle普通视图仅存储查询定义不同&#xff0c;物化视图&#xff08;Materialized View&#xff09;会将查询结果"物化"并保存下来&#xff0c;这意味着物化视图会消耗存储空间&#xff0c;物化的数据需要一定的刷新策略才能和基表同步&#xff0c;在使用和管理上比…

Fortinet 2023上半年全球威胁态势研究报告:勒索软件检测成下降趋势,针对性攻击持续升温

近日&#xff0c;专注于推动网络与安全融合的全球网络安全领导者Fortinet&#xff08;NASDAQ&#xff1a;FTNT&#xff09;&#xff0c;发布《2023上半年全球威胁态势研究报告》。报告显示&#xff0c;2023 年上半年勒索软件检出数量继续下降、高级持续性威胁&#xff08;APT&a…

秋招面经记录

秋招面经记录 MySQLRedis项目分布式框架java网络数据结构设计模式HR手撕 MySQL Mysql中有1000万条数据&#xff0c;每次查询10条&#xff0c;该如何优化&#xff08;答&#xff1a;Limit子查询优化&#xff09; select t.* from t_topic t LIMIT 90000,10; 对上面的mysql语句说…

距离矢量路由协议RIP(含Cisco模拟器实验命令配置)

距离矢量路由协议RIP(含Cisco模拟器实验命令配置) 简介 距离矢量路由协议&#xff08;Routing Information Protocol, RIP&#xff09;是一种内部网关协议&#xff0c;它位于应用层&#xff0c;使用520 UDP端口。RIP基于距离矢量算法&#xff08;Bellham-Ford&#xff09;根据…