顶点小说

装xpath helper

GitHub - mic1on/xpath-helper-plus: 这是一个xpath开发者的工具,可以帮助开发者快速的定位网页元素。

Question:加载完插件点击没反应

Answer:将开发人员模式关闭即可

爬虫介绍

分类:

  • 搜索引擎:爬取范围广
  • 聚焦爬虫:爬取范围聚焦

介绍:

程序发起请求(request),获取响应(response),解析response中的数据

URL

即统一资源定位符

组成:

  • 协议

    • http
    • https:新增SSL协议(证书验证),之前花钱,现在开源了,所以大部分网站都是https,据说性能损耗,但忽略不计
  • 主机IP地址(有时也包括端口号)
  • 主机资源具体地址:如目录和文件名等

静态网站和动态网站

  1. 静态网站:数据在页面源代码中
  2. 动态网站:数据在接口中,网站通过ajax请求接口获取数据,再通过js镶在页面中

结构化与非结构化数据

  1. 结构化数据:可以用关系型数据库表示和存储,表现为二维形式的数据
  2. 非结构化数据:数据结构不规则,不方便用二位逻辑来表现,如办公文档、图片、HTML、音频和视频等等

xpath

概念:即为XML路径语言(XML Path Language),用于确定XML文档中某部分位置的语言,python可以使用xpath的语法定位html文档中某部分的位置,并进行抽取

示例:xpath是抽取静态网站数据的常用方法

Question:动态网站可以用xpath进行解析吗?

Answer:

动态网站采用了ajax技术,ajax发起请求对页面进行替换分为 整块替换和 部分替换,部分替换则接口返回数据格式为Json,整块替换则接口返回html文档

如果返回html文档,则可用xpath进行解析,如果返回Json数据,则不可用xpath进行解析

总结:xpath是否可进行解析取决于数据是否为结点数据(是否具有结点),JSON为字符串,肯定不可用xpath进行解析

语法:

  • /:从文档根目录开始选取
  • //:全局进行查找选取,//代表前面有东西,但不重要,相当于正则表达式的 .*?
  • //li/a/text():可以获取小说的所有书名,然后通过python进行切片获取具体的个别数据
  • //li//text():可以获取 li 标签下的所有文字(不区分什么标签),只限深度为1
  • //a[@class="poptext"]:可以选取带有 class属性 的 a标签
  • @href:可以获取此元素的 href属性值
  • *:匹配任何元素结点,如//*、/bookstore/*
  • |:类似and,都获取,如//book/title | //book/price

案例:顶点小说抓取

  1. 导包,定义headers(有的小说网站对headers无要求,有的有要求)
    import requests
    from lxml import etree
    import pymysql # headers
    headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36 Edg/126.0.0.0"
    }
  2. 获取小说分类url
    # 获取小说分类url
    def get_type():
    url = "https://www.cdbxs.com/sort/"
    source = requests.get(url=url, headers=headers).content.decode('utf-8')
    href_lists = etree.HTML(source).xpath('//ul[@class="nav"]/li/a/@href')[2:-4]
    type_lists = []
    for href in href_lists:
    type_lists.append(f"{url}{href.split('/')[2]}/1/")
    # print(type_lists)
    return type_lists
  3. 获取最大页
    # 获取最大页
    def get_max_page(first_page_url):
    source = requests.get(url=first_page_url, headers=headers).content.decode('utf-8')
    # print(source)
    max_page = etree.HTML(source).xpath('//a[13]/text()')
    return max_page
  4. 获取每个分类的每一页url
    # 获取小说分类url
    type_lists = get_type()
    # 分类url默认为第一页
    for first_page_url in type_lists:
    # 获取带分类的url的前半截
    type_url = first_page_url.split('1')[0]
    # 获取此分类下最大页
    max_page = get_max_page(first_page_url)
    # 生成此分类下每一页url
    for every_page in range(1, int(max_page[0])+1):
    every_page_url = f"{type_url}{every_page}/"
    print(every_page_url)
  5. 获取小说列表页信息
    def get_book_info(every_page_url):
    source = requests.get(url=every_page_url, headers=headers).content.decode('utf-8')
    book_lists = [] lis = etree.HTML(source).xpath("//ul[@class='txt-list txt-list-row5']/li")
    for li in lis:
    book_id_url = li.xpath("span[@class='s2']/a/@href")[0]
    book_id = book_id_url.split('/')[3]
    # 书名
    book_name = li.xpath("span[@class='s2']/a/text()")[0]
    # 最新章节
    new_chapter = li.xpath("span[@class='s3']/a/text()")[0]
    # 作者
    author = li.xpath("span[@class='s4']/text()")[0]
    # 更新时间
    update_time = li.xpath("span[@class='s5']/text()")[0] source = requests.get(url=f"https://www.cdbxs.com{book_id_url}", headers=headers).content.decode('utf-8')
    # 字数
    font_num = etree.HTML(source).xpath("//p[6]/span/text()")[0]
    # 摘要
    summary = etree.HTML(source).xpath("//div[@class='desc xs-hidden']/text()")[0] # 以元组添加至 book_lists
    # print((book_id, book_name, new_chapter, author, update_time, font_num, summary))
    book_lists.append((book_id, book_name, new_chapter, author, update_time, font_num, summary))
    return book_lists
  6. 获取章节列表url
    # 获取章节列表url
    def get_chapter_urls(chapter_list_url):
    source = requests.get(url=chapter_list_url, headers=headers).content.decode('utf-8')
    # 章节url
    chapter_urls = map(lambda x: "https://www.cdbxs.com" + x, etree.HTML(source).xpath("//div[@class='section-box'][2]/ul[@class='section-list fix']/li/a/@href | //div[@class='section-box'][1]/ul[@class='section-list fix']/li/a/@href")) return chapter_urls
  7. 获取章节详情信息
    # 获取章节详情信息
    def get_chapter_info(chapter_url):
    source = requests.get(url=chapter_url, headers=headers).content.decode('utf-8')
    # 标题
    title = etree.HTML(source).xpath("//h1[@class='title']/text()")
    # 正文
    content = ''.join(etree.HTML(source).xpath("//div[@id='nb_content']/dd//text()"))
    if title:
    return title[0], content
    else:
    return '', content
  8. 整合
    # 获取小说分类url
    type_lists = get_type()
    # 分类url默认为第一页
    for first_page_url in type_lists:
    # 获取带分类的url的前半截
    type_url = first_page_url.split('1')[0]
    # 获取此分类下最大页
    max_page = get_max_page(first_page_url)
    # 生成此分类下每一页url
    for every_page in range(1, int(max_page[0]) + 1):
    every_page_url = f"{type_url}{every_page}/"
    # 获取小说列表页信息
    book_info_lists = get_book_info(every_page_url)
    # 获取章节列表url
    for book_info in book_info_lists:
    print(f"爬取小说:{book_info[1]}...")
    book_id = book_info[0]
    chapter_urls = get_chapter_urls(f"https://www.cdbxs.com/booklist/b/{book_id}/1")
    for chapter_url in chapter_urls:
    # print(chapter_url)
    chapter_info = get_chapter_info(chapter_url)
    print(chapter_info)
    print(chapter_info[0])
    print(chapter_info[1])
    # print(f"title:{chapter_info[0]}")
    # print(f"content:{chapter_info[1]}")

:关注我,后续会陆续出爬虫内容(包括但不仅限于顶点小说进阶:数据入库、多线程多进程爬取数据)

更多精致内容,关注公众号:[CodeRealm]

《从零开始学习Python爬虫:顶点小说全网爬取实战》的更多相关文章

  1. 简单物联网:外网访问内网路由器下树莓派Flask服务器

    最近做一个小东西,大概过程就是想在教室,宿舍控制实验室的一些设备. 已经在树莓上搭了一个轻量的flask服务器,在实验室的路由器下,任何设备都是可以访问的:但是有一些限制条件,比如我想在宿舍控制我种花 ...

  2. 利用ssh反向代理以及autossh实现从外网连接内网服务器

    前言 最近遇到这样一个问题,我在实验室架设了一台服务器,给师弟或者小伙伴练习Linux用,然后平时在实验室这边直接连接是没有问题的,都是内网嘛.但是回到宿舍问题出来了,使用校园网的童鞋还是能连接上,使 ...

  3. 外网访问内网Docker容器

    外网访问内网Docker容器 本地安装了Docker容器,只能在局域网内访问,怎样从外网也能访问本地Docker容器? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Docker容器 ...

  4. 外网访问内网SpringBoot

    外网访问内网SpringBoot 本地安装了SpringBoot,只能在局域网内访问,怎样从外网也能访问本地SpringBoot? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装Java 1 ...

  5. 外网访问内网Elasticsearch WEB

    外网访问内网Elasticsearch WEB 本地安装了Elasticsearch,只能在局域网内访问其WEB,怎样从外网也能访问本地Elasticsearch? 本文将介绍具体的实现步骤. 1. ...

  6. 怎样从外网访问内网Rails

    外网访问内网Rails 本地安装了Rails,只能在局域网内访问,怎样从外网也能访问本地Rails? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Rails 默认安装的Rails端口 ...

  7. 怎样从外网访问内网Memcached数据库

    外网访问内网Memcached数据库 本地安装了Memcached数据库,只能在局域网内访问,怎样从外网也能访问本地Memcached数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装 ...

  8. 怎样从外网访问内网CouchDB数据库

    外网访问内网CouchDB数据库 本地安装了CouchDB数据库,只能在局域网内访问,怎样从外网也能访问本地CouchDB数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Cou ...

  9. 怎样从外网访问内网DB2数据库

    外网访问内网DB2数据库 本地安装了DB2数据库,只能在局域网内访问,怎样从外网也能访问本地DB2数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动DB2数据库 默认安装的DB2 ...

  10. 怎样从外网访问内网OpenLDAP数据库

    外网访问内网OpenLDAP数据库 本地安装了OpenLDAP数据库,只能在局域网内访问,怎样从外网也能访问本地OpenLDAP数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动 ...

随机推荐

  1. 解锁高效创新:IPD策略如何重塑产品开发流程

    IPD(集成产品开发)涵盖了产品从创意提出到研发.生产.运营等,包含了产品开发到营销运营的整个过程.围绕产品(或项目)生命周期的过程的管理模式,是一套生产流程,更是时下国际先进的管理体系.IPD(集成 ...

  2. 2024-05-15:用go语言,考虑一个整数 k 和一个整数 x。 对于一个数字 num, 在其二进制表示中, 从最低有效位开始, 我们计算在 x,2x,3x 等位置处设定位的数量来确定其价值。

    2024-05-15:用go语言,考虑一个整数 k 和一个整数 x. 对于一个数字 num, 在其二进制表示中, 从最低有效位开始, 我们计算在 x,2x,3x 等位置处设定位的数量来确定其价值. 举 ...

  3. java学习之旅(day.14)

    可变字符串 StringBuffer:可变长字符串,运行效率慢,线程安全 StringBuilder:可变长字符串,运行效率快,线程不安全 package com.zhang.lei; //Strin ...

  4. 【U8】bom全阶 点击展开按钮,无法获得叶子子阶

    经查看 是因为 子件的失效日期与生效日期是相同一天,延后子件的失效日期就可以在点击展开按钮后,看到子阶bom了.

  5. mit 6.824 lab1 思路贴

    前言 为遵守 mit 的约定,这个帖子不贴太多具体的代码,主要聊聊自己在码代码时的一些想法和遇到的问题. 这个实验需要我们去实现一个 map-reduce 的功能.实质上,这个实验分为两个大的板块,m ...

  6. 如何用 Unity 做出一只赛博宠物

    推荐的一些学习资料 unity 官方文档:Unity 用户手册 (2019.4LTS) - Unity 手册 视频教程:https://www.bilibili.com/video/BV1zB4y1C ...

  7. 7.22考试总结(NOIP模拟23)[联·赛·题]

    不拼尽全力去试一下,又怎么会知道啊 前言 又是被细节问题搞掉的一天. T1 的话,与正解相差无几,少打了两个 else 一个 ls 打成了 rs,然后就爆零了(本来还有 45pts 的),然后加了一个 ...

  8. 鸿蒙HarmonyOS实战-ArkTS语言基础类库(概述)

    一.概述 1.什么是语言基础类库 语言基础类库,也称为标准库或核心库,是编程语言提供的一组内置的基础功能和常用工具的集合.它通常包含了各种数据结构.算法.输入输出处理.字符串处理.日期时间处理.文件操 ...

  9. 使用python获取房价信息

    从贝壳网获取房价信息. 基本的步骤和我的这篇博文一样:https://www.cnblogs.com/mrlayfolk/p/12319414.html.不熟悉的可参考一下. 下面的代码是获取3000 ...

  10. java中以字符分隔的字符串与字符串数组的相互转换

    1.字符串数组拼接成一个以指定字符(包括空字符)分隔的字符串--String.join(),JDK8的新特性 String[] strArray = {"aaa","bb ...