简单的用python爬虫爬豆瓣图书TOP250
一个无聊的下午
思考人生,
有什么简单内容可以爬:
突然发现了这个网页:
(https://book.douban.com/top250?start=0 “豆瓣图书”)
看起来挺不错的
然后
开始~
先导一下会用到的模块:
import requests
from bs4 import BeautifulSoup
import pandas
requests 用来请求
bs4 是 用来提取标签中的内容,比正则简单一些
pandas用来将所获取到的数据存入excel中
如果之前没有使用过bs4和pandas,
那么bs4 和 pandas 都需要通过pip安装一下
大家可以百度一下怎么安装呦
res = requests.get('https://book.douban.com/top250?start=0')
soup = BeautifulSoup(res.text , 'html.parser')
请求这个豆瓣的地址,用res接收请求的结果
用BeautifullySoup将获取的数据进行解析,解析成了html代码,为了之后提取标签中的内容做准备。
然后在豆瓣图书界面F12,然后审查元素,如图所示
知道了这个页面的大部分信息在一个class为item的tr中存在
for news in soup.select('.item'):
遍历soup中class为item的内容,即所以的tr标签中的内容
以下为我取出的内容,作为一个例子
<tr class="item">
<td valign="top" width="100">
<a class="nbg" href="https://book.douban.com/subject/1770782/" onclick="moreurl(this,{i:'0'})">
<img src="https://img3.doubanio.com/mpic/s1727290.jpg" width="90"/>
</a>
</td>
<td valign="top">
<div class="pl2">
<a href="https://book.douban.com/subject/1770782/" onclick=""moreurl(this,{i:'0'})"" title="追风筝的人">
追风筝的人
</a>
<img alt="可试读" src="https://img3.doubanio.com/pics/read.gif" title="可试读"/>
<br/>
<span style="font-size:12px;">The Kite Runner</span>
</div>
<p class="pl">[美] 卡勒德·胡赛尼 / 李继宏 / 上海人民出版社 / 2006-5 / 29.00元</p>
<div class="star clearfix">
<span class="allstar45"></span>
<span class="rating_nums">8.9</span>
<span class="pl">(
289413人评价
)</span>
</div>
<p class="quote" style="margin: 10px 0; color: #666">
<span class="inq">为你,千千万万遍</span>
</p>
</td>
</tr>
接下来我们把需要的信息一点一点取出来
首先我们想知道书的名字:
title = news.select('a')[1].text.replace(' ','')
取出这段文字中第二个a标签的内容(下标从0开始),并且使用replace(’ ‘,”)将多余的空格去除,便于阅读。
由于作者,出版社,时间,价格等很多内容在一个p标签中,我们要想办法将其分割开
a = news.select('p')[0].text
price = a.split('/')[-1]
time = a.split('/')[-2]
store = a.split('/')[-3]
我们先找到这个p段落中的内容:
想办法将其分隔开,但是问题来了,作者的人数为1个或者2个,无法确定,那么怎么才能分别取出来呢?我想了一个机智的办法,从后面往前取不就好了么~
将其根据(‘/’)符号分割,取出倒数第一个内容为价格,倒数第二个内容为出版时间,倒数第三个内容为出版社
name1 = news.select('p')[0].text.split('/')[:-3][0]
name2 = ""
try:
name2 = "," + news.select('p')[0].text.split('/')[:-3][1]
except:
pass;
然后我们要取作者的名字了 ,有的作者有一个名字,有的作者是一个外国作者和一个中国译者,为了解决这个问题,我们先根据(‘/’)分割,取出[0:-3]的内容,即出版社之前的内容。
用name1 接收所取出的第一个元素,也就是第一个名字。
第二个名字不一定存在,怎么办呢,我们先默认它为空 :””
然后用try,except语句将接下来的内容进行包括,将有第二个名字的取出,没有的则pass掉。如果不用try语句,则会出现下标越界,程序出错。
然后要取出书籍的简介如图:
可以找到它的类名为inq,但是运行的时候会有错,提示下标越界,运行了几次之后我发现每次都在一个地方停止,如图:
什么鬼,250本书里居然藏着一个没有简介的,坑啊,于是机智的我又做了一个try来取出这个简介语句如下:
jianjie = ""
try:
jianjie = news.find_all(class_='inq')[0].text
except:
pass;
为了世界和平,我还给豆瓣发了个e-mail,提醒他们这个错误 : )
最后需要取出的是评价的人数
person = news.find_all(class_='pl')[1].text.replace(' ','')
依然用这一条语句,并且去除多余的空格
以上终于完成了内容的取出,那么将取出的内容放在哪里呢?
答案是一个字典数组~,你可以在这个整个代码的import 之下创建一个数组
newsary = []
然后回到我们刚才所写的地方,向数组中通过append添加内容:
newsary.append({'title': title , 'name': name1 + name2 , 'person':person , 'jianjie': jianjie , 'price' : price , 'time' : time , 'store' : store })
这里大家应该都可以看懂~需要注意的是name 的value 为name1 + name2
然后在循环的外面
由于我们现在获得的只是一页的内容,那么怎么获得下一页的内容呢?
我们经过测试可以得到下一页的链接是:
https://book.douban.com/top250?start=25
下下页是
https://book.douban.com/top250?start=50
明白了么?
for i in range(10):
res = requests.get('https://book.douban.com/top250?start=' + str(i*25))
我们只需要这样的一个循环,并且多次向douban发送请求,就可以获得到完整的250条数据了!
之后写:
newsdf = pandas.DataFrame(newsary)
newsdf.to_excel('doubanbook1.xlsx')
使用pandas的DataFrame方法处理newsary,
并且将newsdf的内容存入doubanbook1.xlsx(excel表格)中,
记得提前在这个py文件的同级创建一个doubanbook1.xlsx文件哦。
然后运行这个py文件,等待它运行完成,打开doubanbook1.xlsx文件,就可以看到以下内容:
这个简单的爬虫就结束了~
以下附源码供大家参考:
import requests
from bs4 import BeautifulSoup
import pandas
newsary = []
for i in range(10):
res = requests.get('https://book.douban.com/top250?start=' + str(i*25))
soup = BeautifulSoup(res.text , 'html.parser')
for news in soup.select('.item'): #定位
person = news.find_all(class_='pl')[1].text.replace(' ','')
title = news.select('a')[1].text.replace(' ','')
jianjie = ""
try:
jianjie = news.find_all(class_='inq')[0].text
except:
pass;
name = news.select('p')[0].text
a = news.select('p')[0].text
price = a.split('/')[-1]
time = a.split('/')[-2]
store = a.split('/')[-3]
# author = a.split('/')[-4]
# name = a.split('/')[:-4]
name1 = news.select('p')[0].text.split('/')[:-3][0]
name2 = ""
try:
name2 = "," + news.select('p')[0].text.split('/')[:-3][1]
except:
pass;
newsary.append({'title': title , 'name': name1 + name2 , 'person':person , 'jianjie': jianjie , 'price' : price , 'time' : time , 'store' : store })
newsdf = pandas.DataFrame(newsary)
newsdf.to_excel('doubanbook1.xlsx')
谢谢大家的观看,我只是一个初学者,有什么不足的地方欢迎大家指教和批评~
我的github地址是https://github.com/dangsh
欢迎大家来py哦 : )