最近和朋友聊天,讨论到读书的问题,说是读书到底有什么用?我半开玩笑的给他讲了一个故事。

男孩将女孩送到宿舍楼下,看着一路上两人始终保持着的那一步的距离,男孩终于鼓起勇气,说道:“今晚的月色好美。”

女孩顿了一下,转身问:“你看过《西游记》么?”

男孩点头。

于是女孩在他头上敲了三下。

哈哈哈,其实上面的只是一个段子而已,但是若真讨论到读书能给我们带来什么的话,我想这一段话算是对读书最好的诠释吧。

我读过很多书,但后来大部分都忘记了,你说这样的阅读究竟有什么意义?”“当我还是个孩子时,我吃过很多食物,现在已经记不起来吃过什么了。但可以肯定的是,它们中的一部分已经长成我的骨头和肉。”你读过的书其实早已融进你的骨血,只要一个触动点,就会喷薄而出。

上面说了那么多,其实还是为了引出今天的主题,爬取当当网前500畅销书籍,现在奉上。



首先让我们输入链接:

http://bang.dangdang.com/books/fivestars/01.00.00.00.00.00-recent30-0-0-1-1,

先来说下我们准备获取什么信息。

书籍排名
书籍名称
书籍出版信息
其他信息自选

    老样子让我们审查元素,从当前的html中搜索第一本书书名,发现第一本书的信息全部包含在\<li>标签内,具体信息又包含在\<li>中的每个\<div>内,包括list_num(书籍排名),pic(封面),name(书名),star(星级),publisher_info(出版信息),biaosheng(五星评分次数),price(价格)。

py爬取当当网前500畅销书,送给书荒的你_类名


我们的目标是爬取前五百本书籍信息,但是

http://bang.dangdang.com/books/fivestars/01.00.00.00.00.00-recent30-0-0-1-1

这个页面只有20本书怎么办?点击下一页发现地址为:

http://bang.dangdang.com/books/fivestars/01.00.00.00.00.00-recent30-0-0-1-2

,第三页地址为....-3,以此类推,所以网页请求可以用以下形式实现。

获取书籍排名:前三本书类名为"list_num red",但从第四本书开始类名变为"list_num",他们有共同点"list_num"

<div class="list_num red">1.</div>
<div class="list_num ">4.</div>


我们要找的目标是其中的数字,因此匹配正则可以写为:

list_num.*?(\d*?)\..*?>

书籍名称\<div>类名均为"name"

<div class="name"><a href="http://product.dangdang.com/25197810.html" target="_blank" title="尤尔小屋的猫">尤尔小屋的猫</a></div>

我们要找的目标是title的值,因此匹配正则可以写为:

<div class="name">.*?title="(.*?)">.*?>

书籍出版信息:同样出版信息\<div>类名均为"publisher_info":

<div class="publisher_info"><a href="http://search.dangdang.com/?key=朱光潜" title="朱光潜,酷威文化 出品" target="_blank">朱光潜</a>

我们要找的目标是title的值,因此匹配正则可以写为:

<div class="publisher_info">.*?title="(.*?)">.*?>

经过上文的分析后让我们进入编码环节:

# -*- coding: utf-8 -*-
# [url=home.php?mod=space&uid=238618]@Time[/url]
# [url=home.php?mod=space&uid=686208]@AuThor[/url]
# @FileName: book_crawler.py
# @Software: PyCharm
import requests
import re
from bs4 import BeautifulSoup
import json
#get请求方法,返回结果文本字符串
def request_dandan(url):
try:
response = requests.get(url)
if response.status_code == 200:
return response.text
except requests.RequestException:
return None
#写入txt文件方法
def write_item_to_file(item):
print('开始写入数据 ====> ' + str(item))
with open('book.txt', 'a', encoding='UTF-8') as f:
f.write(json.dumps(item, ensure_ascii=False) + '\n')
f.close()
#主方法
def main(page):
#获取当当网好评榜页面html
url = 'http://bang.dangdang.com/books/fivestars/01.00.00.00.00.00-recent30-0-0-1-' + str(page)
html = request_dandan(url)
#解析返回的html
soup = BeautifulSoup(html, 'lxml')
#找到所有<li>标签项(本次实战爬取书名、出版信息;都可在li标签内找到)
all_lis = soup.find_all('li')
#循环爬取所有<li>中的目标对象
for li in all_lis:
init_dict = {}
#正则匹配书名,出版信息
searchObj1 = re.search(r'list_num.*?(\d*?)\..*?>', str(li), re.M | re.I)
searchObj2 = re.search(r'<div class="name">.*?title="(.*?)">.*?>', str(li), re.M | re.I)
searchObj3 = re.search(r'<div class="publisher_info">.*?title="(.*?)">.*?>', str(li), re.M | re.I)
#书名与出版信息非空时,将匹配结果赋值给字典
if searchObj1 and searchObj2 and searchObj3:
init_dict['list_num']=searchObj1.group(1)
init_dict["name"] = searchObj2.group(1)
init_dict["publisher_info"] = searchObj3.group(1)
if init_dict:
write_item_to_file(init_dict)

if __name__ == "__main__":
#获取1-26页信息
for i in range(1,26):
main(i)

然后运行代码就可以看到本地会多出来一个book.txt的文档,所有的图书信息都在里面了,希望大家能够多看书争取做到:胸藏文墨怀若谷,腹有诗书气自华。