我们在之前的文章中基本上掌握了 Python 爬虫的原理和方法, 不知道大家有没有练习呢今天我就来找一个简单的网页进行爬取, 就当是给之前的兵书做一个实践不然不就是纸上谈兵的赵括了吗
好了, 我们这次的目标是豆瓣图书 Top250, 地址是:
https://book.douban.com/top250?start=0
准备
爬一个网页我们至少要知道自己需要什么信息, 大家看截图:
红色箭头标记的地方就是我们要获取的信息了, 包括书的名字, 作者和出版社信息, 豆瓣评分和一句话简介我们有了目标信息, 就需要找到信息所在的页面源码, 然后通过解析源码来获取到信息数据那么, 我们怎样获得页面 html 源代码呢? 翻阅兵书, 我们知道可以使用 requests 之计代码实现如下:
- import requests
- resp = requests.get('https://book.douban.com/top250?start=0')
- print(resp.text)
运行程序, 我们就轻松的获得了敌军的 HTML 信息了但是问题又来了, 我们得到 HTML 信息后, 怎样得到我们的目标数据呢?
深夜了, 一轮弯月躲在云朵后面, 窗外下着雨, 我们坐在烛火前, 翻阅兵书, 顿时茅塞顿开, BeautifulSoup 大法好
我们打开浏览器, 按 f12 到开发者工具, 我们从网页源码里查找到数据位置, 截图如下:
可以看到书名信息包含在 class='pl2' div 里面的 a 标签内, 是 a 标签的 title 属性发现目标位置后, 就简单多了我们利用 BeautifulSoup 来获得一个对象, 按找标准的缩进显示的 html 代码:
- from bs4 import BeautifulSoup
- soup = BeautifulSoup(resp.text, 'lxml')
推荐大家使用 lxml 解析器, 因为他快如果安装 lxml 遇到问题的可以参考 上一篇文章 的方法当然, 如果大家怕麻烦, 也完全可以使用 Python 的内置标准库 html.parser. 对我们获得结果并没有影响
开始工作
现在我们要用到 BeautifulSoup 的 find_all()选择器, 因为我们这一页有很多书, 而每一本书的信息都包含在 class=pl2 的 div 标签内, 我们使用 find_all()就可以直接得到本页所有书的书名了我们用 find()方法和 find_all()方法来做一个比较:
- # find_all()方法,
- # 注意 class 是 Python 关键词, 后面要加下划线_:
- alldiv = soup.find_all('div', class_='pl2')
- for a in alldiv:
- names = a.find('a')['title']
- print('find_all():', names)
- # find()方法:
- alldiv2 = soup.find('div', class_='pl2')
- names2 = alldiv2.find('a')['title']
- print('find():', names2 )
运行结果:
find_all(): 追风筝的人
find_all(): 小王子
- # ...
- # ... 省略部分
- # ...
find_all(): 三体
find(): 追风筝的人
Process finished with exit code 0
我们通过结果就可以看到两者之间的差距了, 前者输出了一页的数据, 而后者只输出了第一条数据所以包括后面的信息, 由于每一天数据所在标签是一样的, 我们都是用 find_all()方法
上面的代码写的优雅点, 就是这样实现, 注意结果是一个 list:
- # 书名, 注意是 L 小写, 不是阿拉伯数字 1
- alldiv = soup.find_all('div', class_='pl2')
- names = [a.find('a')['title'] for a in alldiv]
- print(names)
- # 作者, 由于信息在一个 p 标签内部,
- # 我们获取到标签直接 get_text()方法获得文本内容
- allp = soup.find_all('p', class_='pl')
- authors = [p.get_text() for p in allp]
- ['[美] 卡勒德. 胡赛尼 / 李继宏 / 上海人民出版社 / 2006-5 / 29.00 元',
- '[法] 圣埃克苏佩里 / 马振聘 / 人民文学出版社 / 2003-8 / 22.00 元',
- '钱锺书 / 人民文学出版社 / 1991-2 / 19.00',
- '余华 / 南海出版公司 / 1998-5 / 12.00 元',
- # ...
- # ... 省略部分结果
- # ...
- '高铭 / 武汉大学出版社 / 2010-2 / 29.80 元',
- '刘慈欣 / 重庆出版社 / 2010-11 / 38.00 元']
- # 评分
- starspan = soup.find_all('span', class_='rating_nums')
- scores = [s.get_text() for s in starspan]
- # 简介
- sumspan = soup.find_all('span', class_='inq')
- sums = [i.get_text() for i in sumspan]
- for name, author, score, sum in zip(names, authors, scores, sums):
- name = '书名:' + str(name) + '\n'
- author = '作者:' + str(author) + '\n'
- score = '评分:' + str(score) + '\n'
- sum = '简介:' + str(sum) + '\n'
- data = name + author + score + sum
- # 文件名
- filename = '豆瓣图书 Top250.txt'
- # 保存文件操作
- with open(filename, 'w', encoding='utf-8') as f:
- # 保存数据
- f.writelines(data + '=======================' + '\n')
- print('保存成功')
- ==================
- # ...
- # ...
- base_url = 'https://book.douban.com/top250?start='
- urllist = []
- # 从 0 到 225, 间隔 25 的数组
- for page in range(0, 250, 25):
- allurl = base_url + str(page)
- urllist.append(allurl)
- # -*- coding:utf-8 -*-
- # author: yukun
- import requests
- from bs4 import BeautifulSoup
- # 发出请求获得 HTML 源码的函数
- def get_html(url):
- # 伪装成浏览器访问
- headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) ApplewebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'}
- resp = requests.get(url, headers=headers).text
- return resp
- # 解析页面, 获得数据信息
- def html_parse():
- # 调用函数, for 循环迭代出所有页面
- for url in all_page():
- # BeautifulSoup 的解析
- soup = BeautifulSoup(get_html(url), 'lxml')
- # 书名
- alldiv = soup.find_all('div', class_='pl2')
- names = [a.find('a')['title'] for a in alldiv]
- # 作者
- allp = soup.find_all('p', class_='pl')
- authors = [p.get_text() for p in allp]
- # 评分
- starspan = soup.find_all('span', class_='rating_nums')
- scores = [s.get_text() for s in starspan]
- # 简介
- sumspan = soup.find_all('span', class_='inq')
- sums = [i.get_text() for i in sumspan]
- for name, author, score, sum in zip(names, authors, scores, sums):
- name = '书名:' + str(name) + '\n'
- author = '作者:' + str(author) + '\n'
- score = '评分:' + str(score) + '\n'
- sum = '简介:' + str(sum) + '\n'
- data = name + author + score + sum
- # 保存数据
- f.writelines(data + '=======================' + '\n')
- # 获得所有页面的函数
- def all_page():
- base_url = 'https://book.douban.com/top250?start='
- urllist = []
- # 从 0 到 225, 间隔 25 的数组
- for page in range(0, 250, 25):
- allurl = base_url + str(page)
- urllist.append(allurl)
- return urllist
- # 文件名
- filename = '豆瓣图书 Top250.txt'
- # 保存文件操作
- f = open(filename, 'w', encoding='utf-8')
- # 调用函数
- html_parse()
- f.close()
- print('保存成功')
来源: http://www.jqhtml.com/13275.html