孔XX旧书网数据采集,举一反三学爬虫,Python爬虫120例第21例

举报
梦想橡皮擦 发表于 2022/01/01 20:16:16 2022/01/01
【摘要】 电商类网站爬虫,永远是爬虫圈必爬项目。今天我们就拿《孔夫子旧书网》练练手。 爬取目标源数据分析本次要爬取的目标网址为 https://book.kongfz.com/Cxiaoshuo/v6/,打开页面寻找分页数据,在下图所示位置可以进行页码切换。在切换页码的同时,捕获到分页链接,并寻找分页规则。https://book.kongfz.com/Cxiaoshuo/v6w1/https://b...

电商类网站爬虫,永远是爬虫圈必爬项目。今天我们就拿《孔夫子旧书网》练练手。

爬取目标源数据分析

本次要爬取的目标网址为 https://book.kongfz.com/Cxiaoshuo/v6/,打开页面寻找分页数据,在下图所示位置可以进行页码切换。

在切换页码的同时,捕获到分页链接,并寻找分页规则。

https://book.kongfz.com/Cxiaoshuo/v6w1/
https://book.kongfz.com/Cxiaoshuo/v6w2/
https://book.kongfz.com/Cxiaoshuo/v6w3/

提炼列表页地址模板为 https://book.kongfz.com/C{类别}/v6w{页码}/

上述内容梳理完毕,就可以对列表页进行采集爬取了,本次爬取分为三个步骤进行。

  1. 提取所有图书分类;
  2. 采集每个类别下的列表页(测试数据,只采集单一分类下的 5 页数据);
  3. 提取目标数据,例如图书名称,作者,出版社,出版时间,店铺名称等信息。

接下来按照步骤实现即可。

提取所有图书分类

通过开发者工具,捕获图书分类区域 HTML 代码,如下所示:

上述数据,可访问任意分类页即可获取,核心代码如下所示,其中 self.get_headers() 函数,可参考之前的博客,或者下载代码查阅。

import requests
from lxml.html import etree
import random
import time


class SSS:
    def __init__(self):

        self.url_format = 'https://book.kongfz.com/C{}/v6w{}/'
        # 待抓取的分类,可以扩展
        self.types = ["wenxue", "xiaoshuo"]
        self.session = requests.Session()
        self.headers = self.get_headers()
        self.categorys =[]

    def get_categorys(self):

        with self.session.get(url='https://book.kongfz.com/Cfalv/',headers=self.headers) as res:
            if res:
                html = etree.HTML(res.text)
                items = html.cssselect('.tushu div.link-item a')
                # 匹配出URL中的type
                for item in items:
                    # print(item)
                    # print(item.get("href"))
                    href = item.get("href")
                    type = href[href.find('C')+1:-1]
                    self.categorys.append(type)

此时简单运行之后,就会得到如下清单,即孔夫子旧书网所有图书分类。

xiaoshuo
wenxue
yuyan
lishi
dili
yishu
……

此时遍历该列表,即可获取所有图书列表页数据,学习阶段,可取其中一条进行分析,例如我选择的文学与小说分类,self.types = ["wenxue", "xiaoshuo"]

采集分类页静态页面数据

对于静态页面数据,采用之前的方法保存到本地即可,在 SSS 类中增加 get_detailrun 函数,页码由于数据量的原因,最大为 200,可以先设置为 5,便于爬取,下述代码在运行时,注意提前建立好 孔夫子 文件夹。

代码继续使用 session.get 方法,进行数据请求。

    def get_detail(self, type, page):
        with self.session.get(url=self.url_format.format(type, page), headers=self.headers, timeout=5) as res:
            if res.text:
                with open(f"./孔夫子/{type}_{page}.html", "w+", encoding="utf-8") as f:
                    f.write(res.text)
            else:
                # 如果无数据,重新请求
                print(f"页码{page}请求异常,重新请求")
                self.get_detail(page)

    def run(self):
        pagesize = 5
        for type in self.types:
            for page in range(1, pagesize):
                self.get_detail(type, page)
                time.sleep(2)
                print(f"分类:{type},页码:{page}页面储存完毕!")

运行代码,得到如下数据,实测过程中,并未发现反爬措施,为了便于测试,可针对性控制请求速度。

提取数据

最后对本地 HTML 进行操作,获取最终的目标数据。

在进行提取的时候,依旧是 CSS 选择器 的使用熟练程度起决定性作用,当然对于异常数据的处理,也需要注意一下。

# 数据提取类
class Analysis:
    def __init__(self):
        # 待抓取的分类,可以扩展
        self.types = ["wenxue", "xiaoshuo"]

    # 去除特殊字符
    def remove_character(self, origin_str):
        if origin_str is None:
            return
        origin_str = origin_str.replace('\n', '')
        origin_str = origin_str.replace(',', ',')
        return origin_str

    def format(self, text):
        html = etree.HTML(text)
        # 获取所有项目区域 div
        div_books = html.cssselect('div#listBox>div.item')
        for book in div_books:
            # 获取标题属性值
            title = book.cssselect('div.item-info>div.title')[0].get('title')
            # 作者默认给空值
            author = None
            author_div = book.cssselect('div.item-info>div.zl-isbn-info>span:nth-child(1)')
            if len(author_div)>0:
                author = author_div[0].text
            # 出版社相同操作
            publisher = None
            publisher_div = book.cssselect('div.item-info>div.zl-isbn-info>span:nth-child(2)')
            if len(publisher_div)>0:
                # 进行数据提取与截取
                publisher = publisher_div[0].text.split(' ')[1]
            print(publisher)

    def run(self):
        pagesize = 5
        for type in self.types:
            for page in range(1, pagesize):
                with open(f"./孔夫子/{type}_{page}.html", "r", encoding="utf-8") as f:
                    text = f.read()
                    # print(text)
                    self.format(text)

提取过程中出现了部分异常数据,针对异常数据进行特殊化处理即可,例如下述截图数据。

学习阶段,就不再继续提取更多的数据,仅提取书名,作者和出版社。

长篇小说:达哈士孔的狒狒(精装) []阿尔丰斯·都德  著;李劼人  译 四川文艺出版社
剑王朝.4 论剑 无罪 长江出版社
只有月亮听得见 康玲玲 四川文艺出版社
元尊1·潜龙在渊 天蚕土豆  著 长江出版社
畅销书女王:张爱玲的33堂写作课 端木向宇 天津人民出版社
区块链改变世界 严行方 中国纺织出版社
我们还会再见吗 苗勇刚、贾宇萍  译 中国出版集团,现代出版社
仲夏夜之恋I 小妮子  著 作家出版社
长篇霸都亚纳(精装) []赫勒·马郎  著;李劼人  译 四川文艺出版社
【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。