简单的python爬虫爬豆瓣图书TOP250

744 阅读5分钟

简单的用python爬虫爬豆瓣图书TOP250

仅测试技术可行性,请勿大量爬取他人网站

一个无聊的下午 思考人生, 有什么简单内容可以爬: 突然发现了这个网页: (book.douban.com/top250?star… "豆瓣图书") 看起来挺不错的 这里写图片描述 然后 开始~

先导一下会用到的模块:

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="&quot;moreurl(this,{i:'0'})&quot;" 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 然后在循环的外面 由于我们现在获得的只是一页的内容,那么怎么获得下一页的内容呢? 我们经过测试可以得到下一页的链接是: book.douban.com/top250?star… 下下页是 book.douban.com/top250?star… 明白了么?

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')