爬虫 | 百行代码爬取14.5W条豆瓣图书信息

前言

先上一波爬取的结果:


数据库中部分截图

实战

引入类库

import requests
from bs4 import BeautifulSoup
from requests.exceptions import RequestException
from urllib.parse import urlencode
import pymongo
import numpy as np
import time
from faker import Faker

分析页面请求

分析目标页面

打开开发者模式,查看链接

点击任意标签,分析页面请求

分别请求不同的标签页面,分析请求链接,可以发现如下规律:
tag_url = 'https://book.douban.com' + 标签页中a标签括起来的内容

由此,我们可以构建以下代码,以获取标签页面所有标签链接:

# 解析总标签页面,并拼接获得所有标签页页面链接
def splice_tags_indexhtml(html):
    url = 'https://book.douban.com'
    book_tags = []
    tags_url = []
    soup = BeautifulSoup(html, 'lxml')
    tagurl_lists = soup.select('#content > div > div.article > div > div > table > tbody > tr > td > a')
    for tag_url in tagurl_lists:
        # 获取全部标签的a标签内容,并拼接到一起
        book_tags += [tag_url.attrs["href"]]
    for book_tag in book_tags:
        tags_url.append([url + book_tag])
    return tags_url

我们进入单个标签页面,分析图书列表页面,解析我们需要存储的字段
我们通过bs4解析我们需要的字段,如:出版时间,作者/译者,豆瓣评分,售价,评价人数等。

# 解析单个tag页面下单页的信息
def parse_tag_page(html):
    try:
        soup = BeautifulSoup(html,"lxml")
        tag_name = soup.select('title')[0].get_text().strip()
        list_soup = soup.find('ul', {'class': 'subject-list'})
        if list_soup == None:
            print('获取信息列表失败')
        else:
            for book_info in list_soup.findAll('div', {'class': 'info'}):
                # 书名
                title = book_info.find('a').get('title').strip()
                # 评价人数
                people_num = book_info.find('span', {'class': 'pl'}).get_text().strip()
                # 出版信息,作者
                pub = book_info.find('div', {'class': 'pub'}).get_text().strip()
                pub_list = pub.split('/')
                try:
                    author_info = '作者/译者: ' + '/'.join(pub_list[0:-3])
                except:
                    author_info = '作者/译者: 暂无'
                try:
                    pub_info = '出版信息: ' + '/'.join(pub_list[-3:-1])
                except:
                    pub_info = '出版信息: 暂无'
                try:
                    price_info = '价格: ' + '/'.join(pub_list[-1:])
                except:
                    price_info = '价格: 暂无'
                try:
                    rating_num= book_info.find('span', {'class': 'rating_nums'}).get_text().strip()
                except:
                    rating_num = '0.0'
                book_data = {
                    'title': title,
                    'people_num': people_num,
                    'author_info': author_info,
                    'pub_info': pub_info,
                    'price_info': price_info,
                    'rating_num': rating_num
                }
                # return book_data
                if book_data:
                    save_to_mongo(book_data,tag_name)
    except:
        print('解析错误')
        return None

到这里,我们已经可以获取到单个tag下单页的图书信息,这个时候我们只需要加入翻页功能就可以实现单个tag下所有图书的信息爬取。

点击下一页,分析页面请求

可以看到页面多了start和type两个参数,同时start参数是从0开始并以20的偏移量递增的,我们按照这个规律可以构建一个生成器以生成start参数。
从文章的第一张图,可以看出不同的tag页有不同的数量的图书,那页面数量也不尽相同,这时应该如何构建生成器?
这个时候我们发现所有的tag在第50页之后都请求不出信息了,所以我们只需构建前50页的页面链接即可,第51页显示如下:
第51页的显示结果
# 请求tag下的每个页面
def get_tag_page(tag_url,page):
        formdata = {
            'start': page,
            'type': 'T'
        }
        url = tag_url[0]+'?'+ urlencode(formdata)
        try:
            reponse = requests.get(url, headers=headers)
            if reponse.status_code == 200:
                return reponse.text
            return None
        except RequestException:
            print('请求列表页错误')
            return None

反反爬
豆瓣的反爬简单粗暴,直接封IP,为了爬虫的健壮,可以使用代理或者随机Header+随机时延的方式,随机时延可以设置为30到40之间,不过这样大大影响了爬取速率,如果需要快速爬取可以采用代理+多线程+随机Header+随机时延这样就能避过反爬又能快速爬取。

#使用Faker库随机生成虚假header
from faker import Faker
fake = Faker()
headers ={'User-Agent':fake.user_agent()}

留心

  • 写给之后的自己
    文章是写完代码后,重新回顾的时候写的,回顾之后发现有很多需要优化的地方,比如异常处理部分经常考虑不周导致在爬取的时候异常中断,不得不重新排查错误。还有爬虫的断点续传的功能应该去了解学习下。

尾言

  • 写给公众号的读者
    公众号的资源已经都整合到一篇文章中了,后台回复「资源」即可获取公众号资源合集,失效部分已补在留言部分。
    我是讲不了段子,编不了故事的咸鱼,这篇文章是咸鱼的第9篇原创文章,感谢大家的支持。

推荐阅读

爬虫 | 爬取拉勾网python岗位信息(超详细)

资源汇总 | 从入门到入职,和咸鱼一起进步

咸鱼普拉思

一只咸鱼在编程路上的摸爬滚打,记录摸索中的点点滴滴。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
很好的问题!以下是一些 Python 爬虫开源项目,可以用来爬取多种网站,包括微信、淘宝、豆瓣、知乎、微博等。 1. Scrapy:一个高效的Python爬虫框架,可用于从多个网站获取数据。 2. Beautiful Soup:一个用于解析HTML和XML文档的Python库,可用于爬取网站。 3. Selenium:一个自动化测试工具,也可用于模拟用户行为进行网站爬取。 4. Requests:一个Python HTTP库,可用于向网站发送请求并获取响应。 5. PyQuery:一个用于解析HTML文档的Python库,类似于jQuery。 6. Pyspider:一个强大的爬虫框架,可用于爬取多个网站。 7. Crawlera:一个智能代理池,可用于绕过网站的反爬虫机制。 8. Frontera:一个高效的分布式爬虫框架,可用于爬取大规模数据。 9. Newspaper:一个Python库,可用于从新闻网站中提取文章和元数据。 10. Feedparser:一个Python库,可用于解析RSS和Atom新闻源。 11. Grab:一个Python爬虫框架,可用于爬取多个网站。 12. ParseHub:一个基于云端的数据提取工具,可用于从网站中提取结构化数据。 13. Webbot:一个用于模拟用户行为的Python库,可用于爬取网站。 14. PySpider:一个基于分布式架构的Python爬虫框架,可用于爬取多个网站。 15. Grablib:一个Python爬虫框架,可用于爬取多个网站。 16. Python-Goose:一个Python库,可用于从新闻网站中提取文章和元数据。 17. Scrapy-redis:一个基于Redis的分布式爬虫框架,可用于爬取多个网站。 18. Scrapy-splash:一个基于Splash的JavaScript渲染爬虫框架,可用于爬取JavaScript动态生成的网页。 19. Scrapy-UserAgents:一个Scrapy中的中间件,可用于随机更换用户代理。 20. Scrapy-Proxies:一个Scrapy中的中间件,可用于随机更换代理IP。 21. Scrapy-rotating-proxies:一个Scrapy中的中间件,可用于随机更换代理IP。 22. Scrapy-selenium:一个Scrapy中的中间件,可用于使用Selenium进行网站爬取。 23. Scrapy-fake-useragent:一个Scrapy中的中间件,可用于随机更换用户代理。 希望这些开源项目能够帮助你进行网站爬取
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值