本文记录了我学习的第一个爬虫程序的过程。根据《Python数据分析入门》一书中的提示和代码,对自己的知识进行查漏补缺。
在上爬虫程序之前补充一个知识点:User-Agent。它是Http协议中的一部分,属于头域的组成部分,User Agent也简称UA。它是一个特殊字符串头,是一种向访问网站提供你所使用的浏览器类型及版本、操作系统及版本、浏览器内核、等信息的标识。通过这个标识,用户所访问的网站可以显示不同的排版从而为用户提供更好的体验或者进行信息统计;例如用不同的设备访问同一个网页,它的排版就会不一样,这都是网页根据访问者的UA来判断的。
电脑浏览器上可以通过右击网页空白处——检查元素——Network——单击一个元素(如果没有就刷新一下网站页面)——下拉找到User-Agent。
例如本机的UA为:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.121 Safari/537.36
网站服务器有时会通过识别UA的方式来阻止机器人(如requests)入侵,故我们需要在爬虫程序里对自己的UA进行伪装。伪装的具体步骤看下文。
这次爬虫的目标是豆瓣新书速递页面的信息,url为https://book.douban.com/latest。可简单分为请求数据、解析数据、根据标签提取数据、进一步提取数据和“漂亮的”打印五个步骤。
一、请求数据
import requests
from bs4 import BeautifulSoup
#请求数据
url = 'http://book.douban.com/latest'
headers = {'User-Agent':"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.121 Safari/537.36"}
data = requests.get(url,headers=headers)
#暂不输入print(data.text)
- 导入requests库和BeautifulSoup库。BeautifulSoup库是一个灵活又方便的网页解析库,处理高效,支持多种解析器。bs4为BeautifulSoup四代的简称。
- 在这里进行UA的伪装:在requests.get函数中可指定headers参数,指定headers为 {'User-Agent':"UA信息……"}。
- 使用data = requests.get(url,headers=headers)获取到网页上的所有数据。
二、解析数据
#解析数据
soup = BeautifulSoup(data.text, 'lxml')
#暂不输出print(soup)
- 在这里将网页数据data转化为了 BeautifulSoup 对象,并将这个对象命名为 soup。
- lxml是一个HTML解析器。
三、根据标签提取数据
- 针对 BeautifulSoup 对象,先检查元素,观察网页。
- “注意:这里选择检查元素后,将鼠标指针直接移动到右侧,即可看到这部分代码对应的网页内容。而相反地,想通过网页内容定位代码时,可以单机检查元素后左上角的小箭头标志。然后在网页中选中想要的数据,如此即可在右侧自动跳转到对应代码。”
- 通过观察,发现图书的内容分别包管在左右“虚构类”和“非虚构类”两个标签下。
-
对应在网页源代码中的表现是
- 仔细观察可以发现 <div class="article"> 这一个标签目录包含了所有的虚构类图书信息;而对应的 <div class="aside"> 包含了所有非虚构类的图书信息。也就是我们只需要这两部分的内容,那我们按照标签提取它们。上代码。
#观察到网页上的书籍按左右两边分布,按照标签分别提取
books_left = soup.find('ul',{'class':'cover-col-4 clearfix'})
#这一步的find,查找所有标签为ul,类class为cover-col-4 clearfix的第一个内容
books_left = books_left.find_all('li')
#这里的find_all再次查找,查找上一步结果里标签为li的内容
books_right = soup.find('ul',{'class':'cover-col-4 pl20 clearfix'})#为L不为1
books_right = books_right.find_all('li')
books = list(books_left) + list(books_right)
'''
find()查找第一个匹配结果出现的地方,find_all()找到所有匹配结果出现的地方。
一般用find()找到BeautifulSoup对象内任何第一个标签入口。
'''
- 最后一句将两个图书信息快,存储到一个列表内,方便后续统一操作。
四、进一步提取,获取所需信息
#对每一个图书区块进行相同的操作,获取图书信息
img_urls = []
titles = []
ratings = []
authors = []
details = []
for book in books:
#图书封面图片url地址
img_url = book.find_all('a')[0].find('img').get('class="lazy" data-src') #[0]指提取第一个a标签的内容
img_urls.append(img_url)
#图书标题
title = book.find_all('a')[1].get_text() #get_text()方法:用来获取标签里面的文本内容,在括号里面加"strip=True"可以去除文本前后多余的空格
titles.append(title)
#print(title)
#评价星级
rating = book.find('p',{'class':'rating'}).get_text(strip=True)
#rating = rating.replace('\n','').replace(' ',''),这一步的效果等同于在get_text里加上参数strip
ratings.append(rating)
#作者及出版信息
author = book.find('p',{'class':'color-gray'}).get_text()
author = author.replace('\n','').replace(' ','')
authors.append(author)
#图书简介
detail = book.find_all('p')[2].get_text()
#存疑!!detail = book.find('p',{'class':'detail'}).get_text() 报错:'NoneType' object has no attribute 'get_text'
detail = detail.replace('\n','').replace(' ','')
details.append(detail)
- 代码看似有一些复杂,但实质上主要还是使用了 find 和 find_all 两个解析工具。
- 仔细分析检查元素中的源代码和对应的网页元素,可轻松找到网页显示内容的一行、两行代码。我们就用 find 和 find_all 去对这一两行进行操作。
- 举例说明获取图书封面图面的 url 地址的方法
img_url = book.find_all('a')[0].find('img').get('class="lazy" data-src')
img_urls.append(img_url)
"可以看出图片地址在此‘信息块’的第一个 a 标签内,通过 find_all('a') 找到所有 a 标签,再通过索引 [0] 提取第一个 a 标签的内容,观察可发现,URL在此 a 标签下的 img 标签内。同样的方法,定位到此 img 标签。应用 find 返回对象的 get 方法,获取 class="lazy" data-src 对应的值,即为要找到的 URL 地址。将此图书的 URL 加入事先准备好的 img_urls 列表内,方便进一步的利用与存取操作。"
- get_text()
此方法可以去除 find 返回对象内的 html 标签,返回纯文本。在括号里面加 "strip=True" 可以去除文本前后多余的空格,效果同replace(' ','')和replace('\n','')。
五、“漂亮的”打印
- 代码最后得到的是五个装满了信息的列表,我们利用 zip 函数,将每个列表里的数据一一对应输出。
for a,b,c,d,e in list(zip(img_urls,titles,ratings,authors,details)):
print("封面图片链接:{0}\n书名:{1} 评分:{2}\n作者及出版信息:{3}\n简介:{4}\n\n".format(a,b,c,d,e))
- 得到的部分打印结果如下↓,还可以,还是挺“漂亮的”哈哈。
封面图片链接:https://img3.doubanio.com/view/subject/m/public/s32289202.jpg
书名:白日漫游 评分:8.0
作者及出版信息:远子/广西师范大学出版社/2019-5
简介:青年作家远子最新力作,以十四篇彼此独立而又互有呼应的短篇小说,刻画在大都市挣扎求生的年轻人,描述一种渴望自由而又无往不在枷锁之中的生活状态。
封面图片链接:https://img1.doubanio.com/view/subject/m/public/s32281237.jpg
书名:不识字的人 评分:9.5
作者及出版信息:[匈]雅歌塔·克里斯多夫/上海人民出版社/2019-4
简介:28个虚构故事和1部自传体小说。《恶童日记》作者雅歌塔流亡记忆的隐秘回响,冷峻精简的语言质感,道尽暗涌的记忆与真实的人生痛感。
封面图片链接:https://img1.doubanio.com/view/subject/m/public/s32305167.jpg
书名:为何,以及如何谋划一场火灾 评分:8.7
作者及出版信息:[美]杰西·鲍尔(JesseBall)/中信出版集团/2019-4
简介:露西娅的父亲死了,母亲进了精神病院,她和姑妈住在别人的车库里。她又一次被学校勒令退学……在新学校,她遇到一个神秘组织,一群可以改变生活的人。
封面图片链接:https://img3.doubanio.com/view/subject/m/public/s32304855.jpg
书名:呼啸山庄 评分:9.2
作者及出版信息:【英】爱米丽·勃朗特/浙江文艺出版社/2019-5
简介:呼啸山庄里的三代恩怨。爱米丽·勃朗特名著新版。
封面图片链接:https://img1.doubanio.com/view/subject/m/public/s32323469.jpg
书名:苔 评分:8.6
作者及出版信息:周恺/楚尘文化/中信出版集团/2019-5
简介:一个晚清家族,一出袍哥传奇,一场历史风暴,一曲时代挽歌。在“三千年未有之大变局”下,再现了蜀中各个阶层的人物命运。
封面图片链接:https://img1.doubanio.com/view/subject/m/public/s32295228.jpg
书名:推理时钟 评分:8.6
作者及出版信息:[日]贵志祐介/新星出版社/2019-5-1
简介:贵志祐介的推理短篇小说集,共分为四个短篇,主要描写了侦探榎本与犯罪者的头脑战。本格密室推理佳作,在日本年度推理榜单上屡次上榜。
总结:上述代码的主要工作就是,先将网页数据转化为 soup 对象,再运用 soup 对象的一些方法逐步获取需要的数据。常用方法具体可参考 bs4 官方文档。本文所写的是最基础最简单的爬虫,笔者感觉如果想自己的爬虫水平更进一步,一定要熟悉 bs4 的方法,多了解HTML、JS等方面的知识,爬虫所需了解它们的程度不深,但必须对其有所涉及。任重而道远!