python爬虫之xpath+多进程爬取百度贴吧实战

文章目录

  • 抓取百度贴吧的某一个帖子的评论内容
    • 前言
    • 先查看贴吧的robots.txt
    • 页面结构分析
      • 评论者头像,用户抓取
      • 评论内容的抓取
      • 评论下回复内容的抓取
    • 源码实现
      • 贴吧抓取过程源码实现
      • 多进程的实现

抓取百度贴吧的某一个帖子的评论内容

前言

本项目实战是用来学习用,没有别的商业用途和恶意请求

先查看贴吧的robots.txt

这是君子协议,如果不允许爬取的,就不去碰,先看君子协议的地址:https://tieba.baidu.com/robots.txt
最后看到,评论内容允许被爬取。
在这里插入图片描述

页面结构分析

  • 抓取的数据结构:
    我们要抓取的评论的内容,评论人的头像,用户名,以及评论人的个人主页,评论时间,回复人信息
  • 页面结构
    通过 css 选择器,评论是位于一个class="p_postlist"的 div下,而p_postlist 下又有多个class 包含l_post j_l_post l_post_bright内容,可以确定评论就在这些 div 中
    在这里插入图片描述

评论者头像,用户抓取

通过页面结构分析,头像是位于 class="d_auth"的 div下元素ul 下,url 的 class="p_author
在这里插入图片描述
所以取头像,用户名的 xpath代码这么写

#头像地址
//ul[@class="p_author"]//a[contains(@class,"p_author_face")]/img/@src# 个人主页的链接
//ul[@class="p_author"]//a[contains(@class,"p_author_face")]/@href# 用户名的链接
//ul[@class="p_author"]//a[contains(@class,"p_author_name")]/text()

评论内容的抓取

在这里插入图片描述

#根据结构,可以去确定内容,子节点的id包含 post_content_就能拿到
//div[contains(@class,"d_post_content_main")]//div[contains(@id,"post_content_")]/text()

评论下回复内容的抓取

根据 xpath 工具看到,都是和评论同一个节点,class="d_post_content_main"的元素下。
在这里插入图片描述

# 评论下的内容
.//div[contains(@class,"d_post_content_main")]//ul[@class="j_lzl_m_w"]

但是在请求的代码中,发现这个 xpath 没有执行,数据没获取到,最后发现是js动态生成的,通过 respons.content的源码发现,这一整个回复的上层 div是空的,这里需要 JS 逆向处理,因为这块涉及到有一定的复杂度,就不再展开,等学完 JS 逆行再来处理。
在这里插入图片描述

源码实现

源码链接:https://gitee.com/allen-huang/python/blob/master/crawler/do-request/bbs/baidu_tieba.py

贴吧抓取过程源码实现

根据xpath结构抓取下来的内容,然后入库到 mongodb 中 去

class BaiduTieba(object):def __init__(self, url):self.url = urlself.headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36'}passdef rep_content(self):"""获取请求内容@return:"""import requestsresp = requests.get(self.url, headers=self.headers)if resp.status_code == 200:return resp.contentelse:return Nonepassdef parse_content(self):"""解析请求内容@return:"""resp_data = self.rep_content()# 将请求内容转换成 html 内容,并编码为 utf-8html_data = etree.HTML(resp_data, parser=etree.HTMLParser(encoding='utf-8'))# 获取评论的内容comm_list = html_data.xpath('//div[contains(@class,"l_post j_l_post l_post_bright")]')insert_list = []for comm in comm_list:# 取左侧头像的图片链接author_face = comm.xpath('.//ul[@class="p_author"]//a[contains(@class,"p_author_face")]')[0]comm_user_link = author_face.xpath('./@href')[0]comm_face_img = author_face.xpath('./img/@src')[0]# 取左侧头像的用户名comm_name = comm.xpath('.//ul[@class="p_author"]//a[contains(@class,"p_author_name")]/text()')[0]# 取右侧的评论内容comm_content = comm.xpath('.//div[contains(@class,"d_post_content_main")]//div[contains(@id,"post_content_")]/text()')[0]# todo 取右侧的评论时间,这个需要使用 JS 逆向来取一开始以为是 xpath有问题,但在 chrom 浏览器插件上测试是可以的,# todo 在 response.content 上发现这是通过JS来动态取的,所以需要学完 JS 逆向再来处理# comm_time = comm.xpath(#     './/div[contains(@class,"core_reply_tail")]//ul[@class="p_tail"]/li[2]/span/text()')[0]comm_dict = {"comm_user_link": comm_user_link,"comm_face_img": comm_face_img,"comm_name": comm_name,"comm_content": comm_content,"from_url": self.url,# "comm_time": comm_time}# todo 取右侧的回复内容,这个需要使用 JS 逆向来取,先不做处理,等学完 JS 逆向再来处理# reply_list = []# reply_container = comm.xpath('.//div[contains(@class,"d_post_content_main")]//ul[@class="j_lzl_m_w"]')# for reply in reply_container:#     # 取回复人头像的链接#     reply_face = reply.xpath(#         './li[contains(@class,"lzl_single_post")]/a[@class="j_user_card lzl_p_p"]')#     reply_user_link = reply_face.xpath('./@href')#     reply_user_img = reply_face.xpath('./img/@src')#     # 取回复人的名字,回复内容,回复时间#     reply_con = reply.xpath(#         './li[contains(@class,"lzl_single_post")]/div[contains(@class,"lzl_cnt")]')#     reply_name = reply_con.xpath('./a[contains(@class,"j_user_card")]/text()')#     reply_content = reply_con.xpath('./span[contains(@class,"lzl_content_main")]/text()')#     reply_time = reply_con.xpath(#         './div[contains("class="lzl_content_reply")]//span[class="lzl_time"]/text()')##     reply_dict = {#         "reply_user_link": reply_user_link,#         "reply_user_img": reply_user_img,#         "reply_name": reply_name,#         "reply_content": reply_content,#         "reply_time": reply_time#     }#     reply_list.append(reply_dict)##     comm_dict["reply_list"] = reply_listinsert_list.append(comm_dict)return insert_listpassdef insert_data(self, curr_page):insert_list = self.parse_content()if insert_list:res = MongoPool().test.baidu_tieba.insert_many(insert_list)if res.inserted_ids:print(f"第{curr_page}页的数据插入成功")else:print("插入失败")else:pass

多进程的实现

  • 将爬取数据的处理封装成一个执行函数
def main(curr_page):url = "https://tieba.baidu.com/p/7216163538?pn={}".format(curr_page)# 创建一个百度贴吧对象baidu_tieba = BaiduTieba(url)# 调用对象的方法插入到 mongodb中baidu_tieba.insert_data(curr_page)pass
  • 这里是进程池来处理,爬取3页内容
if __name__ == '__main__':TOTAL_PAGE = 3pool = multiprocessing.Pool()pages = range(1, TOTAL_PAGE + 1)# 回调 main函数,pages是迭代器,作为回调函数的参数,这和map函数的用法一样pool.map(main, pages)# 关闭进程池pool.close()# 等待进程池中的进程执行完毕pool.join()

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

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

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

相关文章

操作系统内功篇:硬件结构之CPU是如何执行任务的?

一 CPU是如何读写数据的? 1.1 CPU架构(组成) 当代CPU一般是多核心的,每个核心都有自己的一个L1和L2Cache,L3Cache是一个CPU所有核心共享的,一个CPU只有一个。L1Cache分为数据缓存和指令缓存。 CPU有三层高速缓存的目的就是将Cac…

有什么小程序适合个人开发?

在这个信息爆炸的时代,小程序已经成为了我们生活中的一部分。无论是出行、购物还是娱乐,小程序都能为我们提供便捷的服务。对于个人开发者来说,开发一个小程序不仅可以锻炼自己的技术能力,还可以为他人提供便利,甚至有…

AndroidStudio开发 相关依赖

1、com.google.zxing 用于二维码扫描 2、butterknife 用于简化findView 和 onClick操作 3、pub.devrel:easypermissions 简化权限请求的库 4、 网络请求框架(一):android-async-http 网络请求框架(二):xUtils 网络请求框架(三):Volley Volley…

安装paddle detection心得

一、安装PaddlePaddle conda create -n mypaddle python3.8 conda activate mypaddle python -m pip install paddlepaddle-gpu2.6.0 -i https://mirror.baidu.com/pypi/simple 请确保您的PaddlePaddle安装成功并且版本不低于需求版本。使用以下命令进行验证。 这是CUDA1…

Warning logs 2024-03-23

给旧的笔记本安装ubuntu系统,并实现ssh远程连接 1、下载ubuntu系统 ubuntu下载链接 选择带桌面版本 2、准备U盘 3、使用UltraISO制作启动盘 破解UltraISO软件 输入 注册名:王涛 注册码:7C81-1689-4046-626F 使用UltraISO&#xff0c…

RabbitMQ的使用—实战

RabbitMQ的使用—实战 ​ RabbitMQ是一个开源的消息代理中间件,在分布式系统开发中被广泛应用。它实现了高级消息队列协议(AMQP),提供可靠的消息传递、灵活的路由、消息确认等功能。下面是使用RabbitMQ的基本流程: 安…

ECS Fargate 上部署 SkyWalking OAP Server:利用 AWS CLI 和服务发现提供服务

在本篇文章中,我们将演示如何使用 AWS CLI 在 ECS Fargate 上部署 SkyWalking OAP Server,并利用 AWS 服务发现为 gRPC 流量提供一个静态入口点。这样,客户端就可以通过服务发现名称访问 gRPC 服务。以下是详细步骤: 1. 注册任务定义 创建一个名为 ​​dev-skywalking-oa…

吴长江分红

吴长江是雷士照明的创始人,他在公司初创时与两位合伙人共同持有股份,但随着公司的发展,分红问题逐渐凸显。吴长江在面临分红分歧时,选择稀释自己的股份,将部分股份转让给其他股东,以实现股权的均衡。然而&a…

雷卯推荐超级省电防反接方案

方案特别适合一端电池,一端充电的防反接,特别节能 低VF肖特基电源防反接 此方案采用3颗低压降SKY,相比只用1颗功耗更低,可以防止元器件过热 (两者正常工作损耗对比公式: 1.采用1颗SS34LVFA:…

【MySQL数据库】二级内容整理

文章目录 前言基础知识题库软件考试建议总结前言 本文分享一些备考二级MySQL数据库程序设计的资料和心得,希望对同样复习MySQL数据库知识的小伙伴们能够有所帮助。⛽ 基础知识 如果有对MySQL完全不了解的同学可以从这里入门: 👉 MySQL系列视频如果觉得视频时间比较长,可以…

如何安装配置Goland并使用固定公网地址SSH远程连接本地服务器

文章目录 1. 安装配置GoLand2. 服务器开启SSH服务3. GoLand本地服务器远程连接测试4. 安装cpolar内网穿透远程访问服务器端4.1 服务器端安装cpolar4.2 创建远程连接公网地址 5. 使用固定TCP地址远程开发 本文主要介绍使用GoLand通过SSH远程连接服务器,并结合cpolar内…

八、C#计数排序算法

简介 计数排序是一种非比较性的排序算法,适用于排序一定范围内的整数。它的基本思想是通过统计每个元素的出现次数,然后根据元素的大小依次输出排序结果。 实现原理 首先找出待排序数组中的最大值max和最小值min。 创建一个长度为max-min1的数组count…

嵌入式学习第三十天!(单向链表练习)

1. 单向链表的逆序: int Is_Empty_Link(LINK_LIST *plist) {return plist->phead NULL; }void Reverse_Link(LINK_LIST *plist) {LINK_NODE *ptmp plist->phead;LINK_NODE *pinsert NULL;plist->phead NULL;if(Is_Empty_Link(plist)){return;}else{wh…

策略模式在项目中实际应用

Java策略模式是一种行为设计模式,它使你能在运行时改变对象的行为。策略模式定义了一系列的算法,并将每一个算法封装起来,使它们可以互相替换。策略模式使得算法可以独立于使用它的客户端变化。在Java中实现策略模式,通常包含三个…

Vue3:编程式路由导航

一、情景说明 Vue3的用法略有区别 Vue2的用法&#xff1a;https://blog.csdn.net/Brave_heart4pzj/article/details/136326608 二、案例 简单理解&#xff1a;RouterLink中to怎么写&#xff0c;router.replace或router.push中就怎么配置。 <!-- 跳转的按钮 --> <…

IM系统设计之websocket消息转发

Websocket消息转发 项目地址&#xff1a;gitgithub.com:muyixiaoxi/Link.git 上周面试被面试官问到&#xff1a;“在分布式IM系统中&#xff0c;如何实现多个websocket集群之间的通信”。 我在思考了良久后回答&#xff1a;“不会”。 随着我的回答&#xff0c;我和面试官的…

企业产品网络安全建设实录日报规划

为什么要做这个系列&#xff1f; 因为太忙了&#xff0c;忙工作&#xff0c;忙家庭。很难再像之前一样能做到电脑前码一个小时的字&#xff0c;写半个小时的博客。 但是现在的经验增长快速&#xff0c;有很多值得分享的点 想想这平行世界里的我&#xff0c;实际上并不是每一个人…

Spring Data访问Elasticsearch----创建存储库实例

Spring Data访问Elasticsearch----创建存储库实例 一、Java配置二、XML配置三、使用过滤器四、独立使用 本文介绍如何为已定义的存储库接口创建实例和bean定义。 一、Java配置 在Java配置类上使用特定于存储的EnableElasticsearchRepositories注解来定义用于存储库激活的配置。…

MySQL 中的事务和存储引擎

目录 事务的 ACID 特性 MySQL 的四种隔离机制和问题 MySQL 的四种隔离机制&#xff1a; MySQL 的存储引擎 InnoDB 存储引擎 MyISAM 存储引擎 Memory 存储引擎 通过 ALTER TABLE 语句更改存储引擎 在创建表时指定存储引擎 通过修改配置文件设置默认存储引擎 在数据库系…

element el-dialog里再调用其他组件,查找不到组件的方法

需求描述&#xff1a;点击编辑按钮&#xff0c;跳出编辑弹窗&#xff0c;回显图片组件里面的图片问题&#xff1a;element el-dialog里再调用组件&#xff0c;打开该弹窗的瞬间找不到弹窗里调用子组件的方法原因&#xff1a;弹窗显示时&#xff0c;调用的子组件还没渲染出来所以…