python爬虫(案例)——豆瓣读书爬虫


本篇文章为豆瓣读书爬虫的案例,采用了xpath解析式,比较基础,未涉及其他深入的爬虫知识

要爬取的内容

根据豆瓣图书中不同的分类爬取图书的相关信息 ( 每个分类豆瓣最多给50页数据 )

一级页面(分类中图书的列表)

在这里插入图片描述

爬取 : 书名(文本和url),作者,出版社,出版日期,评价数,缩略图链接,短简介


二级页面(每本书的详情页)

在这里插入图片描述
通过一级页面 书名的url链接进入二级页面

爬取 : 评分,内容简介,作者简介,标签


本案例中的防封ip小技巧

多用几个user-agent(随机抽取)

def header_x():
    # 随机获取一个headers
    user_agents = ['Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36',
                   'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0',
                   'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.57.2 (KHTML, like Gecko) Version/5.1.7 Safari/534.57.2',
                   'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36',
                   'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.71 Safari/537.1 LBBROWSER',
                   'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.84 Safari/535.11 SE 2.X MetaSr 1.0'
                   ]

    headers = {
        "User-Agent": random.choice(user_agents)
    }
    return headers

常见user-agent大全:https://www.cnblogs.com/zrmw/p/9332801.html(转,大佬写的(非本人))

设置间隔时间

设置每条数据的时间间隔

time.sleep(random.randint(5, 8))

设置换页的时间等待时间

time.sleep(random.randint(3, 5))

注意:随机数千万不要从0开始,不要太小,容易被封ip

完整代码

import requests
from lxml import etree
import csv
import re
import time
import random

def header_x():
    # 随机获取一个headers
    user_agents = ['Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36',
                   'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0',
                   'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.57.2 (KHTML, like Gecko) Version/5.1.7 Safari/534.57.2',
                   'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36',
                   'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.71 Safari/537.1 LBBROWSER',
                   'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.84 Safari/535.11 SE 2.X MetaSr 1.0'
                   ]

    headers = {
        "User-Agent": random.choice(user_agents)
    }
    return headers

# 要爬取的 豆瓣读书中的 分类名称
kinds = ['','']


for book_kind in kinds:

    # 为每个分类创建一个csv文件
    csvFile = open("{}.csv".format(book_kind), mode="w+", encoding="utf-8")

    for i in range(1, 51):
        print('{name}   开始爬取第 {index} 页'.format(name=book_kind,index=i))

        # 拼接url
        url = 'https://book.douban.com/tag/{name}?start={num}&type=T'.format(name=book_kind,num=i*20-20)

        headers = header_x()

        resp = requests.get(url, headers=headers)
        html = etree.HTML(resp.text)

        lis = html.xpath("//div[@id='subject_list']/ul/li")

        for li in lis:
            try:
                name = li.xpath("./div[@class='info']/h2/a/@title")   # 书名
                img_url = li.xpath("./div[@class='pic']/a/@href")     # 缩略图链接
                author = li.xpath("./div[@class='info']/div[@class='pub']/text()")[0].strip().split('/')[0]  # 作者
                publisher = li.xpath("./div[@class='info']/div[@class='pub']/text()")[0].strip().split('/')[-3]  # 出版社
                publish_time = li.xpath("./div[@class='info']/div[@class='pub']/text()")[0].strip().split('/')[-2]  # 出版年
                # 判断出版社,出版年份是否在指定位置 如果不在 则跳过
                if(publish_time.find('-')==-1):
                    continue
                grade = li.xpath(".//span[@class='pl']/text()")[0].strip()   # 评价数

                # 处理grade 提取数字
                grade_num = []
                grade_num = re.findall("\d+\.?\d*", grade)

                intro_1 = li.xpath("./div[@class='info']/p/text()")[0].strip()   # 小简介

                # 子链接
                son_url = li.xpath("./div[@class='info']/h2/a/@href")[0]   #子链接


                resp_son = requests.get(son_url, headers=headers)
                html_son = etree.HTML(resp_son.text)

                # 评分
                score = html_son.xpath("//strong[@class='ll rating_num ']/text()")[0].strip()
                # 简介
                intro = ''.join(html_son.xpath("//div[@id='link-report']//div[@class='intro']/p/text()"))
                # 作者简介
                author_intro = ''.join(html_son.xpath("//div[@class='indent ']//div[@class='']/div/p/text()"))
                # 标签
                label = html_son.xpath("//div[@id='db-tags-section']//a/text()")
                label = ' '.join(label)
            except IndexError:
                continue

            # 把字符串转换成列表
            author = list(author.split('&&'))
            publisher = list(publisher.split('&&'))
            publish_time = list(publish_time.split('&&'))
            intro_1 = list(intro_1.split('&&'))

            score = list(score.split('&&'))
            intro = list(intro.split('&&'))
            author_intro = list(author_intro.split('&&'))
            label = list(label.split('&&'))

            # 把数据放入列表
            result = []
            result.extend(name)
            result.extend(author)
            result.extend(img_url)
            result.extend(publisher)
            result.extend(publish_time)
            result.extend(grade_num)
            result.extend(intro_1)

            result.extend(score)
            result.extend(intro)
            result.extend(author_intro)
            result.extend(label)

            # 将列表写入 csv文件
            write = csv.writer(csvFile)
            write.writerow(result)

            # 设置每条数据的时间间隔
            time.sleep(random.randint(5, 8))

        print("{name}    第 {index} 页爬取完成!!!".format(name=book_kind,index=i))

        # 设置换页的时间等待时间
        time.sleep(random.randint(3, 5))


注: 修改kinds列表,就可以直接开始爬取数据了,最长2.5个小时爬取完一个分类(50页)

注: 因为豆瓣中每个详情页的结构可能不同(我也很是费解),所以有些值爬出来的可能为空,导致处理时程序报错,小编为了方便,遇到为空的就 try…except 直接跳过当前详情页了

  • 8
    点赞
  • 104
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值