基于爬虫和Kettle的书籍信息采集与预处理

一:爬虫

1、爬取的目标

将读书网上的书籍的基本信息,比如:封面、书名、作者、出版社、价格、出版时间、内容简介、作者简介、书籍目录、ISBN和标签爬取出来,并将爬取的结果放入数据库中,方便存储。

2、网站结构

   

图1读书网书籍类别详情

此次实验爬取读书网页面中文学、小说、传记、青春文学、艺术、散文随笔、励志、人文社科、经济管理、励志十大类书籍。

每一类书籍包括书名、价格、作者、出版社、ISDN、出版时间、封面以及书籍简介、作者简介、书目录和书籍所属类别。页面具体情况如图2所示。

图2读书网书籍属性设计详情

3、爬虫技术方案

1)、所用技术:

         网站解析的使用的是Xpath、数据库存储使用的是pymysql。

2)、爬取步骤:

    (1)、分析目标网站:了解页面结构;

(2)、获取页面内容:使用python中的requests库来获取页面内容;

(3)、定位页面:使用Xpath定位我们所需要的数据的位置;

(4)、连接数据库:创建数据连接,放入自己数据库的端口、用户和密码等数据,使得连接上自己的数据库,将爬取好的数据返给数据库中,方便存储;

(5)、关闭连接:关闭数据库连接。

4、爬取过程:

   

1)、常量定义

    

此处定义了网页后缀END=‘.html’用于进行网页拼接。

Start_Page = 1 定义爬取起始页码,end_Page = 10 定义爬取结束页码。

Base_url 用于设置爬取网页的基础网站,进行后续网页拼接。

Book_type={},该字典设置爬取书籍类别。

Header={},该字典进行请求头设置。

2)、设置游标,连接数据库,再使用for循环,确保书籍能够循环爬取,最后将爬取完毕的数据放入数据库中,最后关闭数据库的连接。

  

   3)、一级链接爬取,接收参数基本网页地址、书籍类型、网页页数后,再使用requests库中r.get(url=url,headers=header)发送请求,使用response接收请求数据。

   

4)、二级链接爬取,在数据获取步骤,进行更细致的xpath语句书写。

使用try-except语句提高程序健壮性,返回一个书籍信息字典。

      

      5)、保存数据,创建游标,编写sql语言,之后执行sql语言,执行成功就插入所给的表,如果执行失败则输出插入失败。

      

5、爬虫结果

预处理

  1. 删除列

1)、新建转换,之后使用表输入,将MySQL文件中的表输入kettle。需要连接数据库的类型是MySQL,主机名称是localhost、用户是root、密码是root、端口号是3306。

    

之后进行字段获取。

2)、选择转换中的字段选择进行列删除,将dictroy这个列进行删除。

2、选择转换中的增加常量,增加remainder这一列,查询书籍卖出剩余的情况。

    

  1. 、最后选择文本文件输出,将处理好的数据输出,输出的格式是csv文件,分割符用逗号隔开,编码用UTF-8J进行转码,防止输出文件中有乱码。文本文件命名为姓名_处理完成_csv。

4、预处理完全处理全流程

三、爬虫源代码

import re
import requests
from lxml import etree
import pymysql
import datetime
"""
爬取一个网站
1.获得数据不小于一千条
2.每条数据属性不小于10
"""

END = '.html'
start_Page = 1
end_Page = 10
base_url = 'https://www.dushu.com'
# 以字典形式保存每一类对应的网页数字
book_type = {"文学": 1077, "小说": 1078, "传记": 1081, "青春文学": 1079,
     "艺术": 1082, "散文随笔": 1163, "鉴赏": 1222, "人文社科": 1003,
     "经济管理": 1004, "励志": 1094
}

header = {
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36'
}

def get_one_bookInfo_link(base_url, _type, page):
    # url 控制爬取的书籍类型、网页页数
    url = base_url+'/book/'+str(_type)+'_'+str(page)+END
    # print(url)
    response = requests.get(url=url, headers=header)
    if response.status_code == 200:
        htmlTEXT = response.content.decode(response.apparent_encoding)
        html = etree.HTML(htmlTEXT)
        bookLinke_List = html.xpath('//div[@class="container margin-top"]//div[@class="bookslist"]/ul/li/div[@class="book-info"]/h3/a/@href')
        return bookLinke_List
    else:
        print("请求失败")


def get_oneBook_info(bookLinke):
    url = base_url + bookLinke
    content = requests.get(url=url, headers=header)
    if content.status_code == 200:
        info = etree.HTML(content.content.decode(content.apparent_encoding))
        # 获取书籍详细信息,十个
        try:
            img = info.xpath('//div[@class="bookdetails-left"]/div[@class="book-pic"]//img/@src')[0]  # 封面
            title = info.xpath('//div[@class="bookdetails-left"]/div[@class="book-pic"]//img/@alt')[0]  # 书名
            author = info.xpath('//div[@id="ctl00_c1_bookleft"]/table//tr[1]//td[2]/text()')[0]  # 作者
            publish = info.xpath('//div[@id="ctl00_c1_bookleft"]/table//tr[2]//td[2]/text()')[0]  # 出版社
            temp_price = info.xpath('//div[@id="ctl00_c1_bookleft"]/p/span/text()')[0]  # 价格
            price = temp_price.split('¥')[1]
            time = info.xpath('//div[@class="bookdetails-left"]/div[@class="book-details"]/table//tr[1]/td[@class="rt"][2]/text()')[0]  # 出版时间
            cont = info.xpath('//div[@class="container margin-top"]//div[contains(@class, "book-summary")][1]/div/div/text()')[0]   # 内容简介
            blurb = info.xpath('//div[@class="container margin-top"]//div[contains(@class, "book-summary")][2]/div/div/text()')[0]  # 作者简介
            directory = info.xpath('//div[@class="container margin-top"]//div[contains(@class, "book-summary")][3]/div/div/text()')[0]  # 书籍目录
            isbn = info.xpath('//div[@class="bookdetails-left"]/div[@class="book-details"]/table//tr[1]/td[@class="rt"][1]/text()')[0]   # ISBN
            label = info.xpath('//div[@id="ctl00_c1_bookleft"]/table//tr[4]//td[2]/text()')[0]  # 标签
            # 使用字典保存一本书籍的信息
            book_info = {
                "img": img,
                "title": title,
                "author": author,
                "publish": publish,
                "price": price,
                "time": time,
                "cont": cont,
                "blurb": blurb,
                "directory": directory,
                "isbn": isbn,
                "label": label
            }
            return book_info
        except Exception as e:
            print("爬取时单本书籍获取出现错误:", e, "\n发生错误地址为:"+url)
            err_info = {
                "img": 'https://a.dushu.com/img/n200.png',
                "title": 'titleEro',
                "author": 'authorEro',
                "publish": 'publishEro',
                "price": '00.00',
                "time": '2001-01-01',
                "cont": 'contEro',
                "blurb": 'blurbEro',
                "directory": 'directoryEro',
                "isbn": 'isbnEro',
                "label": 'labelEro'
            }
            return err_info
    else:
        print("请求失败")


def set_BookInfo_ToMySql(book_info, db):
    # print(book_info.values())
    cursor = db.cursor()
    # sql语句
    sql = "INSERT INTO book(img,title,author,publish,price,time,cont,blurb,directory,isbn,label) VALUES " \
          "('%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s')"\
          %(book_info["img"], book_info["title"], book_info["author"], book_info["publish"],
            book_info["price"], book_info["time"], book_info["cont"], book_info["blurb"],
            book_info["directory"], book_info["isbn"], book_info["label"])
    print(book_info.values())
    try:
        # 执行sql语句
        if cursor.execute(sql):
            print('插入数据成功')
            # 提交到数据库执行
            db.commit()  # 持久化
    except Exception as e:
        # 如果发生错误则回滚
        print("插入失败", e)
        db.rollback()


def main():
    #  用于存储计算数据爬取数量
    count = 0
    # 连接数据库
    db = pymysql.connect(host='localhost', user='root', password='root', port=3306, db='pachong')
    # 开启爬取程序
    for type in book_type:  # 控制爬取书籍的类别
        for i in range(start_Page, end_Page+1):    # 控制每一类爬取的页数
            # 每一个网页的书籍的二级连接
            bookLinke_List = get_one_bookInfo_link(base_url=base_url, _type=book_type[type], page=i)
            if bookLinke_List:
                for link in bookLinke_List:
                    print(link)
                    info = get_oneBook_info(link)
                    info['label'] = type
                    # print(info)
                    set_BookInfo_ToMySql(book_info=info, db=db)
                    count += 1
            else:
                print("爬取内容为空")
    # 数据插入完成后关闭数据库
    if db:
        db.close()
        print("关闭数据库成功,程序结束")
    else:
        print("数据加载成功,数据库未关闭")
    return count


if __name__ == '__main__':
    print("Run...")
    # 获取开始时间
    start_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    # db = pymysql.connect(host='localhost', user='root', password='root', port=3306, db='movie')
    # info = get_oneBook_info('/book/13981332/')
    # set_BookInfo_ToMySql(info, db=db)
    # db.close()
    print("已爬取书籍数量:", main())
    # 获取结束时间
    end_time = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    print("程序结束{}\n运行开始时间:{}".format(end_time, start_time))

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

利用网络威胁情报增强网络安全态势

在当今的网络威胁形势下,明智且主动的防御策略至关重要。网络威胁情报是组织的重要工具,可帮助他们预测和应对网络风险。网络威胁情报不仅提供原始数据,还提供: 深入了解网络攻击者的动机了解他们的潜在目标了解他们的战术 通过…

如何运用TRIZ理论解决电动汽车的续航里程问题?

电动汽车的普及在很大程度上受到续航里程的制约。面对这一问题,传统的解决方案往往只能治标不治本。然而,TRIZ理论为我们提供了一个全新的视角,帮助我们从根本上解决这一难题。 TRIZ,全称为“发明问题解决理论”,是由苏…

java SSM物资采购管理系统myeclipse开发mysql数据库springMVC模式java编程计算机网页设计

一、源码特点 java SSM物资采购管理系统是一套完善的web设计系统(系统采用SSM框架进行设计开发,springspringMVCmybatis),对理解JSP java编程开发语言有帮助,系统具有完整的源代 码和数据库,系统主要采…

JDBC-数据库连接池(druid)

一、背景 在介绍JDBC基本概念中,似乎Java程序每次与数据库交互都要通过驱动创建一个新的连接对象(Connection),再由连接对象创建一个可执行SQL的Statement对象(或PreparedStatement对象),操作完…

一键搭建elk

一键启动elk 1. 生成环境的脚本 setup.sh #!/usr/bin/bash# logstash enviroment mkdir -p logstash touch logstash/logstash.conf # shellcheck disableSC1078 echo input {tcp {mode > "server"host > "0.0.0.0"port > 4560codec > jso…

HCIP OSPF实验

任务: 1.使用三种解决ospf不规则区域的方法 2.路由器5、6、7、8、15使用mgre 3.使用各种优化 4.全网可达 5.保证更新安全 6.使用地址为172.16.0.0/16合理划分 7.每个路由器都有环回 拓扑图&IP划分如下: 第一步,配置IP&环回地址…

【面试突击】网关系统面试实战

🌈🌈🌈🌈🌈🌈🌈🌈 欢迎关注公众号(通过文章导读关注:【11来了】),及时收到 AI 前沿项目工具及新技术 的推送 发送 资料 可领取 深入理…

Netty 介绍、使用场景及案例

Netty 介绍、使用场景及案例 1、Netty 介绍 https://github.com/netty/netty Netty是一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可扩展的网络服务器和客户端。它是一个开源项目,最初由JBoss公司开发,现在由社区维护。Netty的…

qt初入门2:qt选择一个文件或者目录,获取当前目录,操作文件目录等整理

最近用qt操作文件或者目录的动作比较多,简单整理一下常用的接口,方便回顾。 总的来说,其实就是用文件选择对话框QFileDialog类,以及操作文件信息的QFileInfo类,以及相关QCoreApplication中静态成员函数获取一些信息&a…

对话姿美堂创始人董事长徐熙明:不受短期诱惑和外界噪音的影响,坚持做难而正确的事

“ 客户至上 ” 整理 | 云舒&凯丰 编辑 | 梦遥 出品|极新&北京电子商务协会 在过去几年中,直播电商经历了显著的发展,成为数字化零售领域的一个重要分支。随着智能手机和高速互联网的普及,消费者的购物习惯发生…

聚焦老年生活与健康,“老有所依·情暖夕阳”元岗街社区微型养老博览会顺利开展

尊老敬老是中华民族的传统美德, 爱老助老是全社会的共同责任。 家有一老,如有一宝, 长者的生活情况是一个家庭的头等大事, 做好长者服务是街道和社区的重要工作。 2024年1月6日,由元岗街道党工委、元岗街道办事处、…

OpenGl 19高级GLSL

一.GLSL的内建变量 在着色器中,需要当前着色器以外地方的数据的话,必须把数据传进来。之前我们是通过uniform类型和采样器来完成的。之外,GLSL还支持另外几个以gl为前缀的变量,提供更多读写数据的方式,比如说顶点着色…

ES高级查询

ES中提供了一种强大的检索数据方式,这种检索方式称为Query DSL,这种方式的丰富查询语法让ES检索变得更强大,更简洁。 1.常见查询 1.1查询所有[match_all] match_all关键字:返回索引中的全部文档。 GET /products/_search { &…

acwing4986.互质数的个数

题目不难 有个好的细节想着分享一下 一开始写的有点问题&#xff5e;需要特判掉一个... #include<bits/stdc.h> using namespace std; using ll long long; const int N 1e510;const ll mod 998244353;ll qmi(ll a,ll b){ll ans 1;while(b){if(b&1)ans ans*a%…

(20)Linux初始文件描述符

前言&#xff1a;本章我们介绍 O_WRONLY, O_TRUNC, O_APPEND 和 O_RDONLY。之后我们开始讲解文件描述符。 一、系统传递标记位 1、O_WRONLY C 语言在 w 模式打开文件时&#xff0c;文件内容是会被清空的&#xff0c;但是 O_WRONLY 好像并非如此&#xff1f; 代码演示&…

H264码流进行RTP包封装

一.H264基本概念 H.264从框架结构上分为视频编码层&#xff08;VCL&#xff09;和网络抽象层&#xff08;NAL&#xff09;&#xff0c;VCL功能是进行视频编解码&#xff0c;包括运动补偿预测&#xff0c;变换编码和熵编码等功能&#xff1b;NAL用于采用适当的格式对VCL视频数据…

【竞技宝】DOTA2:梦幻联赛开战在即 中国区前两名将晋级正赛

北京时间2024年1月12日&#xff0c;近期DOTA2刚刚结束了别墅杯东南亚/中国区的封闭预选赛&#xff0c;而别墅杯的正赛还要等到下个月才会正式开打&#xff0c;而即将在明天开始进行的是梦幻联赛S22的中国区预选赛&#xff0c;除官方直邀的XG战队直接晋级正赛之外&#xff0c;其…

【Leetcode】2085. 统计出现过一次的公共字符串

文章目录 题目思路代码 题目 2085. 统计出现过一次的公共字符串 思路 使用两个哈希表 words1Count 和 words2Count 分别统计两个数组中每个单词的出现次数。然后遍历 words1Count 中的每个单词&#xff0c;如果该单词在 words1 中出现了一次&#xff0c;且在 words2 中也出…

深入理解计算机系统(2):信息的表示和处理

信息存储 大多数计算机使用 8 位的块&#xff0c;或者字节(byte)&#xff0c;作为最小的可寻址的内存单位&#xff0c;而不是访问内存中单独的位。机器级程序将内存视为一个非常大的字节数组&#xff0c;称为虚拟内存(virtual memory)。内存的每个字节都由一个唯一的数字来标识…

地表最强,接口调试神器Postman ,写得太好了!

postman是一款支持http协议的接口调试与测试工具&#xff0c;其主要特点就是功能强大&#xff0c;使用简单且易用性好 。 无论是开发人员进行接口调试&#xff0c;还是测试人员做接口测试&#xff0c;postman都是我们的首选工具之一 。 那么接下来就介绍下postman到底有哪些功…