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

news2024/9/28 9:23:13

文章目录

  • 抓取百度贴吧的某一个帖子的评论内容
    • 前言
    • 先查看贴吧的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 = url
        self.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'
        }
        pass

    def rep_content(self):
        """
        获取请求内容
        @return:
        """
        import requests
        resp = requests.get(self.url, headers=self.headers)
        if resp.status_code == 200:
            return resp.content
        else:
            return None
        pass

    def parse_content(self):
        """
        解析请求内容
        @return:
        """
        resp_data = self.rep_content()
        # 将请求内容转换成 html 内容,并编码为 utf-8
        html_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_list
            insert_list.append(comm_dict)
        return insert_list
        pass

    def 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 = 3
    pool = multiprocessing.Pool()
    pages = range(1, TOTAL_PAGE + 1)
    # 回调 main函数,pages是迭代器,作为回调函数的参数,这和map函数的用法一样
    pool.map(main, pages)
    # 关闭进程池
    pool.close()
    # 等待进程池中的进程执行完毕
    pool.join()

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

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

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

相关文章

uniapp自定义导航栏左中右内容和图标,以及点击事件

uniapp自定义导航栏左中右内容和图标&#xff0c;以及点击事件 效果&#xff1a; 页面&#xff1a; <view class"navigation-bar"><view class"navigation-bar-left" click"navigateBack"><u-icon name"arrow-left"…

曲面斑马纹分析

曲面斑马纹分析是一种在曲面设计和质量检测中广泛使用的技术&#xff0c;其基本原理是利用明暗相间的光线照射到物体表面经反射产生的纹路来评估曲面的连续性和光顺性。这些斑马纹不仅美观&#xff0c;更重要的是它们能直观地展示曲面上的几何特性&#xff0c;帮助设计师和工程…

C++入门笔记开源【研究生3年+7W字】

博主研究生3年时间积累了一个C的基础知识文档&#xff0c;共计7W字。几乎把常用的各种语法和接口都包含进去了。一个文档&#xff0c;markdown格式的&#xff0c;可以当做工具书来使用。由于本文档内容较多&#xff0c;直接复制到csdn会各种卡&#xff0c;而且图片链接不对&…

【循环神经网络rnn】一篇文章讲透

目录 引言 二、RNN的基本原理 代码事例 三、RNN的优化方法 1 长短期记忆网络&#xff08;LSTM&#xff09; 2 门控循环单元&#xff08;GRU&#xff09; 四、更多优化方法 1 选择合适的RNN结构 2 使用并行化技术 3 优化超参数 4 使用梯度裁剪 5 使用混合精度训练 …

C++剑指offer与高频面试题源码解答与分析

这是博主在当初秋招刷题时候记录的剑指offer第二版以及一些高频题的C源码和解法分析&#xff0c;可以说把这上面的题练好了面试不虚&#xff0c;最后也顺利帮助我拿下baidu ali meituan等多家大厂offer。整篇文章写了大概5W个字&#xff0c;也是积累了很长一段时间的作品&#…

数据分析案例-国际象棋顶级棋手数据可视化分析(文末送书)

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

C++的内存模型

大家好&#xff1a; 衷心希望各位点赞。 您的问题请留在评论区&#xff0c;我会及时回答。 内存分区模型 C程序在执行时&#xff0c;将内存大方向划分为4个区域。 代码区&#xff1a;存放函数体的二进制代码&#xff0c;由操作系统进行管理。 全局区&#xff1a;存放全局变…

是时候来唠一唠synchronized关键字了,Java多线程的必问考点!

写在开头 在之前的博文中&#xff0c;我们介绍了volatile关键字&#xff0c;Java中的锁以及锁的分类&#xff0c;今天我们花5分钟时间&#xff0c;一起学习一下另一个关键字&#xff1a;synchronized。 synchronized是什么&#xff1f; 首先synchronized是Java中的一个关键字…

机器学习-06-无监督算法-01-划分聚类Kmeans算法

总结 本系列是机器学习课程的系列课程&#xff0c;主要介绍机器学习中无监督算法&#xff0c;包括划分聚类等。 参考 数据分析实战 | K-means算法——蛋白质消费特征分析 欧洲48国英文名称的来龙去脉及其国旗动画 Kmeans在线动态演示 本门课程的目标 完成一个特定行业的…

基于modbus TCP实现EPICS与西门子S7 1200系列1215C PLC的通信

PLC介绍 西门子系列PLC在国内的市场占比第一&#xff0c;1200系列中小型PLC&#xff0c;因其众多的产品序列、强大的通讯功能和丰富扩展模块&#xff0c;被使用在工业生产、自动化生产线、智能制造、机器人等各行各业。根据CPU的供电电源的型号和数字量输出的类型&#xff0c;…

科技革新背后:码垛机器人在不同领域的实践应用

随着科技的进步&#xff0c;机器人技术已经渗透到各个行业之中&#xff0c;成为提高生产效率、减少人工成本的重要工具。码垛机器人作为自动化技术的杰出代表&#xff0c;其在各个行业中的应用场景日益广泛&#xff0c;从食品饮料到化工产品&#xff0c;再到物流仓储&#xff0…

矩阵计算-线性系统和 LU 分解

一、三角系统 …… 二、高斯消元法 …… 三、LU分解--直接三角分解法 求解线性方程Axb&#xff1a; 参考视频&#xff1a;【数值分析】矩阵LU三角分解| 速成讲解 考试宝典_哔哩哔哩_bilibili 令ALU&#xff0c;其中L是单位下三角矩阵&#xff08;对角线上元素都是1&#xff…

探秘国内IP代理购买:全面解析与实用建议

随着网络空间的不断发展和扩大&#xff0c;越来越多的用户需要在互联网上获取访问其他国家或地区网站的需求。而为了实现这一目的&#xff0c;使用IP代理服务成为了一种常见的方式。在国内&#xff0c;选择合适的IP代理服务商并购买适合自己需求的IP代理已成为许多人关心的问题…

JavaScript 权威指南第七版(GPT 重译)(二)

第四章&#xff1a;表达式和运算符 本章记录了 JavaScript 表达式以及构建许多这些表达式的运算符。表达式 是 JavaScript 的短语&#xff0c;可以 评估 以产生一个值。在程序中直接嵌入的常量是一种非常简单的表达式。变量名也是一个简单表达式&#xff0c;它评估为分配给该变…

mongodb文档数据建模

基础建模 内嵌方法和数组方完成关系表述 内嵌一对一关系建模 数组内嵌一对N 关系建模 数组内嵌对象多对多关系建模 文档模型设计之二&#xff1a;工况细化 join 查询 不支持外键 设计模式集锦 版本迭代加schema_version 字段 频繁写入改为时间区间写入 聚合变预聚合方式 采用…

银行数字人民币系统应用架构设计

2019年10月&#xff0c;01区块链联合数字资产研究院发布了《人民币3.0&#xff1a;中国央行数字货币运行框架与技术解析》&#xff0c;从数字货币界定和人民币发展历程出发&#xff0c;区分了央行数字货币与比特币、移动支付等的区别&#xff0c;全面介绍了央行数字货币的发展历…

【Linux实践室】Linux用户管理实战指南:新建与删除用户操作详解

&#x1f308;个人主页&#xff1a;聆风吟_ &#x1f525;系列专栏&#xff1a;Linux实践室、网络奇遇记 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 一. ⛳️任务描述二. ⛳️相关知识2.1 &#x1f514;Linux创建用户命令2.1.1 知识点讲解2.1.2 案…

IDEA调优-四大基础配置-编码纵享丝滑

文章目录 1.JVM虚拟机选项配置2.多线程编译速度3.构建共享堆内存大小4.关闭不必要的插件 1.JVM虚拟机选项配置 -Xms128m -Xmx8192m -XX:ReservedCodeCacheSize1024m -XX:UseG1GC -XX:SoftRefLRUPolicyMSPerMB50 -XX:CICompilerCount2 -XX:HeapDumpOnOutOfMemoryError -XX:-Omi…

matlab和stm32的安装环境。能要求与时俱进吗,en.stm32cubeprg-win64_v2-6-0.zip下载太慢了

STM32CubeMX 6.4.0 Download STM32CubeProgrammer 2.6.0 Download 版本都更新到6.10了&#xff0c;matlab还需要6.4&#xff0c;除了st.com其他地方都没有下载的,com.cn也没有。曹 还需要那么多固件安装。matlab要求制定固件位置&#xff0c;然后从cubemx中也指定…

必示科技携手云杉网络发布“智能可观测性联合解决方案”

近日&#xff0c;必示科技与云杉网络携手发布“智能可观测性联合解决方案”&#xff0c;整体方案融合云杉网络DeepFlow产品在可观测性领域、必示科技AIOps产品在运维数据分析领域的深厚技术积淀&#xff0c;完整实现IT系统高质量、高性能、全栈的可观测数据采集、智能监控和智能…