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

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

可能有人会说需要的内容复制粘贴,或者直接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.xdnf.cn/news/143489.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

华为云Stack的学习(七)

八、华为云Stack存储服务介绍 1.云硬盘EVS 云硬盘&#xff08;Elastic Volume Service&#xff0c;EVS&#xff09;&#xff0c;又名磁盘&#xff0c;是一种虚拟块存储服务&#xff0c;主要为ECS&#xff08;Elastic Cloud Server&#xff09;和BMS&#xff08;Bare Metal Se…

MySQL - order by排序查询 (查询操作 四)

功能介绍&#xff1a;order by&#xff1a;对查询结果进行排序&#xff0c;执行顺序在查询完结果执行&#xff08;比如where后&#xff09; 排序方式&#xff1a;ASC&#xff1a;升序&#xff08;默认&#xff0c;不用指定&#xff09; DESC&#xff1a;降序 语法&#x…

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

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

GIT提示Another git process seems to be running in this repository

解决方法 1、进入项目里面的.git文件里面找到index.lock删除即可。

05-Zookeeper典型使用场景实战

上一篇&#xff1a;04-Zookeeper集群详解 1. Zookeeper 分布式锁加锁原理 如上实现方式在并发问题比较严重的情况下&#xff0c;性能会下降的比较厉害&#xff0c;主要原因是&#xff0c;所有的连接都在对同一个节点进行监听&#xff0c;当服务器检测到删除事件时&#xff0c…

gym_unity学习笔记

最近学了一段时间gym_unity&#xff0c;把一些资料留在这里 实例 实例gym_unity训练RollerBall&#xff1a;https://blog.csdn.net/alibutter/article/details/120908687实例gyn_unity训练3DBall&#xff1a;https://zhuanlan.zhihu.com/p/554927641?utm_id0 源码&#xff1…

Linux部署elk日志监控系统

目录 一、简介 二、部署elasticsearch 2.1 安装jdk11&#xff08;jdk版本>11&#xff09; 2.2 下载安装包 2.3 授权elk用户 2.4 配置elasticsearch.yml 2.5 启动elasticsearch 三、部署logstash 3.1 启动测试 3.2 可能出现的报错 3.3 指定配置文件启动logstash 3.4 安装El…

DevExpress WinForms图表组件 - 直观的数据信息呈现新方式!(一)

凭借界面控件DevExpress WinForms全面的2D和3D图表类型的集合&#xff0c;DevExpress WinForms的图表控件设计大大简化了开发者直观地向最终用户呈现信息的方式。 DevExpress WinForms有180组件和UI库&#xff0c;能为Windows Forms平台创建具有影响力的业务解决方案。同时能完…

【笔记】Splay

【笔记】Splay 目录 简介右旋左旋 核心思想操作a. Splayb. 插入c. 删除 信息的维护例题AcWing 2437. SplayP3369 【模板】普通平衡树 简介 Splay 是一种平衡树&#xff0c;并且是一棵二叉搜索树&#xff08;BST&#xff09;。 它满足对于任意节点&#xff0c;都有左子树上任意…

常见应用层协议

一.HTTP&#xff08;超文本传输协议&#xff09; HTTP 和 HTTPS 二.FTP&#xff08;文件传输协议&#xff09; 三.SMTP&#xff08;简单邮件传输协议&#xff09; 四.POP3&#xff08;邮局协议版本3&#xff09; 五.IMAP&#xff08;互联网消息访问协议&#xff09; 六.DNS&am…

利用证书给pdf文件添加数字签名

文章目录 给pdf文件签名一、文件准备1. 构建印章2. 获取证书方法一 阿里云申请证书方法二 自建证书 二、利用证书给pdf签名三、设定签名位置在指定坐标签名在指定签名域签名 传送门 给pdf文件签名 如何给pdf文件签名&#xff0c;这样pdf文件就具有不可修改性&#xff0c;具有鉴…

钡铼BL302与PLC:提升酿酒业效率与品质的利器

啤酒是人类非常古老的酒精饮料&#xff0c;是水和茶之后世界上消耗量排名第三的饮料。 啤酒在生产过程中主要有制造麦芽、粉碎原料、糖化、发酵、贮酒後熟、过滤、灌装包装等工序流程。需要用到风选机、筛分机、糖化锅、发酵设备、过滤机、灌装机、包装机等食品机械设备。这些食…

指针笔试题详解

个人主页&#xff1a;点我进入主页 专栏分类&#xff1a;C语言初阶 C语言程序设计————KTV C语言小游戏 C语言进阶 C语言刷题 欢迎大家点赞&#xff0c;评论&#xff0c;收藏。 一起努力&#xff0c;一起奔赴大厂。 目录 1.前言 2.指针题写出下列程序的结…

【算法练习Day1】二分查找移除元素

​ ​&#x1f4dd;个人主页&#xff1a;Sherry的成长之路 &#x1f3e0;学习社区&#xff1a;Sherry的成长之路&#xff08;个人社区&#xff09; &#x1f4d6;专栏链接&#xff1a;练题 &#x1f3af;长路漫漫浩浩&#xff0c;万事皆有期待 文章目录 二分查找解决方法一&…

在比特币上使用可检索性证明支付存储费用

我们为用户开发了一种为云存储付费的新方法。 与亚马逊的 S3 等传统云存储相比&#xff0c;用户不必信任服务器。 我们使用比特币智能合约来确保支付取决于服务器的可检索性证明 (PoR)&#xff0c;该证明只能在数据仍然可用且需要时可以检索的情况下生成。 可检索性证明 (PoR)…

C/C++学习路线总结与分享

目录 1、学习C语言 2、学习C 3、了解基础的网络知识 4、Linux相关知识 5、数据库知识 6、数据结构与算法 7、需要重点关注的编程技术 7.1、socket网络编程 7.2、多线程与多线程编程 7.3、多进程及多进程通信 7.4、动态链接库编程 7.5、数据库编程 7.6、设计模式 …

Super Marker插件——标记资源,提高效率

插件介绍&#xff1a; 这是一款可以给资源添加颜色或图标标记&#x1f4cc;的插件&#xff0c;当资源文件比较多的时候&#xff0c;颜色标记可以让你一眼定位到要使用的资源&#xff0c;提高开发效率。 插件地址&#xff1a; Cocos商店&#xff1a;https://store.cocos.com/a…

机器学习,深度学习

一 、Numpy 1.1 安装numpy 2.2 Numpy操作数组 jupyter扩展插件&#xff08;用于显示目录&#xff09; 1、pip install jupyter_contrib_nbextensions -i https://pypi.tuna.tsinghua.edu.cn/simple 2、pip install jupyter_nbextensions_configurator -i https://pypi.tuna.t…

c#:System.Text.Json 的使用三(从Newtonsoft迁移)

环境&#xff1a; .net 6.0vs2022 系列篇&#xff1a; 《c#&#xff1a;System.Text.Json 的使用一》 《c#&#xff1a;System.Text.Json 的使用二》 《c#&#xff1a;System.Text.Json 的使用三&#xff08;从Newtonsoft迁移&#xff09;》 参考&#xff1a; 《MSDN: 从 Newt…

Kafka 常见问题

文章目录 kafka 如何确保消息的可靠性传输Kafka 高性能的体现利用Partition实现并行处理利用PageCache 如何提高 Kafka 性能调整内核参数来优化IO性能减少网络开销批处理数据压缩降低网络负载高效的序列化方式 kafka 如何确保消息的可靠性传输 消费端弄丢了数据 唯一可能导致…