上一篇我们学习了BeautifulSoup的基本用法,本节我们使用它来爬取豆瓣图书Top250。

一、网页分析

我们爬取的网页的url是https://book.douban.com/top250?icn=index-book250-all。首页如图

与豆瓣电影Top250差不多,将页面拉到最底部,可以看到分页列表

并且每一页的url也是以25递增,所以爬取思路与豆瓣电影Top250一致。

二、爬取目标

我们本篇要爬取的信息包括书名、作者、出版社、价格、评分、推荐语。

三、爬取首页

  • 网页获取源代码
import requestsdef get_html(url):headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'}html = requests.get(url,headers=headers)return html.textif __name__ == '__main__':url = 'https://book.douban.com/top250?start=0'html = get_html(url)print(html)

输出结果

  • 解析提取所需信息

如图,查看源代码我们可以知道页面中书的信息均包含在一个个<table>标签中,所以我们可以先用CSS选择器将一个个<table>节点选出来,然后在使用循环提取每一本书的信息。提取<table>节点的代码如下:

def parse_html(html):soup = BeautifulSoup(html,'lxml')books = soup.select('div.article div.indent table')print(books)

运行结果如下:

可以看到输出为列表,并且第一个元素包含《追风筝的人》的相关信息。这里我们使用BeautifulSoup中的select()加CSS选择器提取<table>节点。传入的CSS选择器为:div.article div.indent table。其中div.article的意思为选择包含属性class="article"的<div>标签,然后跟空格代表嵌套关系,表示接着选择该<div>下的包含class="indent"的<div>标签,再跟空格表示接着嵌套,继续选择第二个<div>标签下的<table>标签。

接下来,对选出来的<table>标签循环,在每一个<table>标签中去提取图书信息。这里我们先提出书名信息,先看一种写法,代码如下:

def parse_html(html):soup = BeautifulSoup(html,'lxml')books = soup.select('div.article div.indent table')for book in books:title = book.div.a.stringprint(title)

输出结果

可以看到确实获取到了书名信息,但是有些书的书名没有得到,返回了None,这就不是很完美了呀。我们先解释写这里获取标题的方法,这里我们使用了节点选择器的嵌套选择:首先选择了<div>标签,然后继续选择其下的<a>标签。为什么不直接选择<a>标签呢,因为包含书名信息的<a>标签是<table>节点下的第二个<a>标签,直接选择<a>只会选择第一个不包含书名信息的那个<a>标签。下面我们来研究下为什么使用string属性不能获取某些书的书名信息,我们先将获取到的<a>标签打印出来。

def parse_html(html):soup = BeautifulSoup(html,'lxml')books = soup.select('div.article div.indent table')for book in books:title = book.div.aprint(title)

并截取返回None的那本书的位置

可以看到《三体》这本书的<a>标签的内部结构不同,所以导致调用string属性返回None,但是我们可以注意到每条<a>标签都包含title属性,我们是否可以通过title属性获取书名?

def parse_html(html):soup = BeautifulSoup(html,'lxml')books = soup.select('div.article div.indent table')for book in books:title = book.div.a['title']print(title)

输出结果如下:

可以看到不仅获取到了想要的信息,而数据更加干净。这里获取title部分说了这么多主要是想告诉大家一个获取相同的信息有很多的方法,当一种获取方式不理想时可以考虑换一种思路。

接下来我们一次性将所有的信息抓取下来。

def parse_html(html):soup = BeautifulSoup(html,'lxml')tables = soup.select('div.article div.indent table')books = []for table in tables:title = table.div.a['title']'''由于information中包含多个信息,某些书与大多数书的信息格式不一致在进行列表索引的时候非常容易引起IndexError异常,为了保证爬虫的健壮性我们对该异常进行处理'''information = table.p.stringinformations = information.split('/')while(len(informations)>4):del informations[1]try:author = informations[0]press = informations[1]date = informations[2]price = informations[3]except IndexError:continue'''像这样子进行数据提取很容易遇到某一个特殊部分的网页结构与大部分的不一样,这会导致首页能抓取到的节点,在该部分会返回None,从而导致调用string属性产生AttributeError异常,我们需要进行异常处理'''try:score = table.find(attrs={'class':'rating_nums'}).stringrecommendation = table.find(attrs={'class':'inq'}).stringexcept AttributeError:continuebook = {'书名':title,'作者':author,'出版社':press,'出版日期':date,'价格':price,'评分':score,'推荐语':recommendation}books.append(book)return books

输出结果:

这里可以看到输出结果虽然为字典,但是不好看。保存为字典格式只是方便存储与后续使用,假如我们要将其打印到屏幕上的话,并不好看,所以我们接着写一个打印函数,专门用于输出:

def print_(books):for book in books:print('*'*50)for key,value in zip(book.keys(),book.values()):print(key+':'+value)print('*'*50)

我们将爬取首页的代码汇总在一起,看看输出效果

import requests
from bs4 import BeautifulSoupdef get_html(url):headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'}html = requests.get(url,headers=headers)return html.textdef parse_html(html):soup = BeautifulSoup(html,'lxml')tables = soup.select('div.article div.indent table')books = []for table in tables:title = table.div.a['title']'''由于information中包含多个信息,某些书与大多数书的信息格式不一致在进行列表索引的时候非常容易引起IndexError异常,为了保证爬虫的健壮性我们对该异常进行处理'''information = table.p.stringinformations = information.split('/')while(len(informations)>4):del informations[1]try:author = informations[0]press = informations[1]date = informations[2]price = informations[3]except IndexError:continue'''像这样子进行数据提取很容易遇到某一个特殊部分的网页结构与大部分的不一样,这会导致首页能抓取到的节点,在该部分会返回None,从而导致调用string属性产生AttributeError异常,我们需要进行异常处理'''try:score = table.find(attrs={'class':'rating_nums'}).stringrecommendation = table.find(attrs={'class':'inq'}).stringexcept AttributeError:continuebook = {'书名':title,'作者':author,'出版社':press,'出版日期':date,'价格':price,'评分':score,'推荐语':recommendation}books.append(book)return booksdef print_(books):for book in books:print('*'*50)for key,value in zip(book.keys(),book.values()):print(key+':'+value)print('*'*50)if __name__ == '__main__':url = 'https://book.douban.com/top250?start=0'html = get_html(url)books = parse_html(html)print_(books)

输出结果:

注意,这里我们没有写存储的相关函数,因为这里只为演示BeautifulSoup的用法,假如需要存储数据参考爬虫系列第三篇 使用requests与正则表达式爬取豆瓣电影Top250

四、爬取整个豆瓣图书Top250

与前面个爬虫实例一样,构造url列表,使用循环即可。全部代码如下

import requests
from bs4 import BeautifulSoupdef get_html(url):headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'}html = requests.get(url,headers=headers)return html.textdef parse_html(html):soup = BeautifulSoup(html,'lxml')tables = soup.select('div.article div.indent table')books = []for table in tables:title = table.div.a['title']'''由于information中包含多个信息,某些书与大多数书的信息格式不一致在进行列表索引的时候非常容易引起IndexError异常,为了保证爬虫的健壮性我们对该异常进行处理'''information = table.p.stringinformations = information.split('/')while(len(informations)>4):del informations[1]try:author = informations[0]press = informations[1]date = informations[2]price = informations[3]except IndexError:continue'''像这样子进行数据提取很容易遇到某一个特殊部分的网页结构与大部分的不一样,这会导致首页能抓取到的节点,在该部分会返回None,从而导致调用string属性产生AttributeError异常,我们需要进行异常处理'''try:score = table.find(attrs={'class':'rating_nums'}).stringrecommendation = table.find(attrs={'class':'inq'}).stringexcept AttributeError:continuebook = {'书名':title,'作者':author,'出版社':press,'出版日期':date,'价格':price,'评分':score,'推荐语':recommendation}books.append(book)return booksdef print_(books):for book in books:print('*'*50)for key,value in zip(book.keys(),book.values()):print(key+':'+value)print('*'*50)if __name__ == '__main__':urls = [f'https://book.douban.com/top250?start={i*25}' for i in range(0,10)]for url in urls:  html = get_html(url)books = parse_html(html)print_(books)

五、总结

通过本篇的学习,读者应该着重掌握:

  • BeautifulSoup库三种节点选择方式的灵活运用
  • 对可能的异常要进行处理(请求部分的异常一般不用处理)
  • 与正则表达式进行优劣比较
  • 读者可以自行将正则表达式与BeautifulSoup结合起来灵活使用

这里解释一下为什么请求部分的异常一般不需要处理,因为请求出现异常一般意味着url错误、网络连接有问题等,这些异常都需要我们处理好而不是用try...except语句跳过它,否则爬虫无法继续。

如果觉得本篇文章不错,欢迎关注我的爬虫系列教程公众号【痕风雨】,一起学习交流。

requests 获取div_爬虫系列第五篇 使用requests与BeautifulSoup爬取豆瓣图书Top250相关推荐

  1. 爬虫项目实操三、用scrapy框架爬取豆瓣读书Top250的书名,出版信息和评分

    安装方法:Windows:在终端输入命令:pip install scrapy:mac:在终端输入命令:pip3 install scrapy,按下enter键,再输入cd Python,就能跳转到P ...

  2. xpath解析爬虫爬取豆瓣图书Top250的数据

    这是在学习阶段写的爬虫,爬取的是豆瓣图书Top250榜的名称,作者,评分等数据 第一次写文章,如果有什么问题,欢迎各位大佬进行指正,谢谢来踩. 1.首先需要明确自己想要爬取的内容,并在网页中查看数据是 ...

  3. python爬取豆瓣书籍_Python爬虫-爬取豆瓣图书Top250

    豆瓣网站很人性化,对于新手爬虫比较友好,没有如果调低爬取频率,不用担心会被封 IP.但也不要太频繁爬取. 涉及知识点:requests.html.xpath.csv 一.准备工作 需要安装reques ...

  4. python爬豆瓣top250书籍_python爬虫练习-爬取豆瓣图书top250

    个人自学,完整学习请访问以下链接 学习链接:https://study.163.com/course/courseMain.htm?courseId=1004714034 代码 # -*-coding ...

  5. python爬虫爬取豆瓣图书

    爬取豆瓣图书top250的第一页 我最终爬取的是图书的书名,链接 先要做个说明,如果你是编程高手的话,这边文章你就不用看了,如果你是个python爬虫小白的话,可以看看这篇原创 我将用到的软件是pyc ...

  6. 使用Requests和Lxml库,爬取豆瓣读书TOP250

    from lxml import etree import requests import csv #导入需要的库fp = open('C://Users/Administrator/Desktop/ ...

  7. Python爬虫系列之多多买菜小程序数据爬取

    Python爬虫系列之多多买菜小程序数据爬取 小程序爬虫接单.app爬虫接单.网页爬虫接单.接口定制.网站开发.小程序开发> 点击这里联系我们 < 微信请扫描下方二维码 代码仅供学习交流, ...

  8. Python爬虫系列之MeiTuan网页美食版块商家数据爬取

    Python爬虫系列之MeiTuan网页美食版块商家数据爬取 小程序爬虫接单.app爬虫接单.网页爬虫接单.接口定制.网站开发.小程序开发> 点击这里联系我们 < 微信请扫描下方二维码 代 ...

  9. 一起学爬虫——通过爬取豆瓣电影top250学习requests库的使用

    一起学爬虫--通过爬取豆瓣电影top250学习requests库的使用 学习一门技术最快的方式是做项目,在做项目的过程中对相关的技术查漏补缺. 本文通过爬取豆瓣top250电影学习python req ...

最新文章

  1. MAC OSX在视图port哪个程序占用,杀死进程的方法
  2. Mybaits-plus实战(二)
  3. nginx react vue location history 配置
  4. 利用python进行数据分析—8.数据清洗与准备
  5. C语言回溯算法求幂集,回溯法与树的遍历 - 求幂集
  6. Topaz Gigapixel AI打开软件闪退及加载图片闪退 解决办法
  7. mkdir命令、chmod修改权限、利用scp 远程上传下载文件/文件夹
  8. python获取当前工作路径、保存路径
  9. cmf5 excel 导入
  10. 暮光之城破晓 - 看看会发生什么
  11. 游戏设计模式阅读笔记3——重访设计模式(观察者模式)
  12. 鼠标侧键设置工具X-Mouse安装教程
  13. 我想哭,可是欲哭无泪
  14. ORA-00392: log 15 of thread 1 is being cleared, operation not allowed
  15. Markdown如何画时序图,一篇就够了
  16. Badusb 攻击之MacOSX系统实战
  17. 【JavaScript】- 实现图片放大镜效果
  18. B域,M域,O域具体是指什么
  19. 生成AaBb-Zz之间的所有字符
  20. 关于深度学习人工智能模型的探讨(五)(4)

热门文章

  1. 真格量化-50ETF期权波动率策略
  2. 通用唯一识别码UUID
  3. Flask爱家租房--订单(房东接单、拒单)
  4. mysql语法题_mysql数据库题语法练习
  5. div table 超出了_div包裹的table,table的宽度超出了的宽度,出现的滚动条的在windows下无法拖动...
  6. 订阅内容解码失败(非base64码)_【火眼金睛】超强解码能力——邦纳全新ABR系列读码器来袭!...
  7. MySQL 之 索引
  8. android 编译luajit,Android 嵌入 LuaJIT 的曲折道路
  9. java虚方法和抽象方法_虚方法和抽象方法--基础回顾
  10. HTML块,含样式的标签