Python 爬虫分析豆瓣 TOP250 之 信息字典 和 马斯洛的锥子
问题
本文是对《Python 爬虫分析豆瓣 TOP250 告诉你程序员业余该看什么书?》 一文的补充
我们以《追风少年》为例
用chrome的developer tool查看源代码
这里发现,源代码的HTML比较难以分析(Parse)。
在原作者的文中,把这些都放在了一起。
[美] 卡勒德·胡赛尼 / 李继宏 / 上海人民出版社 / 2006-5 / 29.00元
而这样并不能满足我的要求(知识图谱)。
一开始,我也尝试着用xpath里面的sibling, next等去抓信息,但是都失败了。后来恍然大悟。其实,如果单单从页面上看,这明明就是key value pair,用冒号隔开。于是,我直接把字符串抓出来,很容易就搞定了。
信息字典
理想情况下,抓出来的信息是这个样子的。
作者: [美] 卡勒德·胡赛尼
出版社: 上海人民出版社
出品方: 世纪文景
原作名: The Kite Runner
译者: 李继宏
出版年: 2006-5
页数: 362
定价: 29.00元
装帧: 平装
丛书: 卡勒德·胡赛尼作品
ISBN: 9787208061644
这样,一行行分析就行了。
但实际上,抓出来的信息是这样的
作者:
[美]
卡勒德·胡赛尼
出版社: 上海人民出版社
出品方: 世纪文景
原作名: The Kite Runner
译者:
李继宏
出版年: 2006-5
页数: 362
定价: 29.00元
装帧: 平装
丛书: 卡勒德·胡赛尼作品
ISBN: 9787208061644
不过,也没关系,用正则表达式抓到所有的key。这样key之间的就是value了。
具体代码如下。(python 3.7)
# -*- coding: utf-8 -*-
"""
Created on Wed Feb 27 12:08:08 2019
@author: eric
"""
import requests
from lxml import etree
from bs4 import BeautifulSoup
import time
import re
class Douban_Book():
url = ""
title_cn=""
title_original="" #原作名
author=""
author_profile = ""
publisher="" #出版社
publish_date=""
pages=""
price=""
series=""
isbn=""
rating = 0.0
votes = 0
summary = ""
HEADERS = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'}
def get_urls():
#https://book.douban.com/top250?start=225
url_base = "https://book.douban.com/top250?start="
urls = [url_base+str(i*25) for i in range(10)]
return urls
def get_dict_value(the_dict, key, defualt_value=""):
if key in the_dict:
return the_dict[key]
return defualt_value
def get_book(book_url):
response = requests.request("get", book_url, headers=HEADERS)
soup = BeautifulSoup(response.text, "html.parser")
book = Douban_Book()
book.url = book_url
book.title_cn = soup.find("h1").text.strip()
#以下是信息字典
soup_info = soup.find("div",{"id":"info"})
info_text = soup_info.text
heads = re.findall("\n.+:",info_text)
info_dict = {}
for i in range(len(heads)-1):
start_at=info_text.find(heads[i])+len(heads[i])
end_at=info_text.find(heads[i+1])
value = info_text[start_at:end_at].strip().replace("\n","")
value = re.sub("\s+"," ",value)
key = heads[i].strip().replace(":","")
info_dict[key]=value
#the last key value pair
start_at=info_text.find(heads[-1])+len(heads[-1])
value = info_text[start_at:].strip().replace("\n","")
key = heads[-1].strip().replace(":","")
info_dict[key]=value
#把信息字典里的信息写入book对象
book.author = get_dict_value(info_dict, "作者")
book.isbn = get_dict_value(info_dict, "ISBN")
book.pages = get_dict_value(info_dict, "页数")
book.price = get_dict_value(info_dict, "定价")
book.publish_date = get_dict_value(info_dict, "出版年")
book.publisher = get_dict_value(info_dict, "出版社")
book.series = get_dict_value(info_dict, "丛书")
book.title_original = get_dict_value(info_dict, "原作名")
#豆瓣评分
book.rating = float(soup.find("strong",{"class":"ll rating_num "}).text.strip())
#<span property="v:votes">405241</span>
book.votes = int(soup.find("span",{"property":"v:votes"}).text)
#简介
intros = soup.find_all("div",{"class":"intro"})
for p in intros[0].find_all("p"):
book.summary+=p.text+"\r\n"
for p in intros[1].find_all("p"):
book.author_profile+=p.text+"\r\n"
return book
def save_book(book):
print("saving book {0} {1}".format(book.title_cn, book.title_original))
pass
#https://book.douban.com/top250?start=0
def parse_list(list_url):
response = requests.request("get", list_url, headers=HEADERS)
tree = etree.HTML(response.text)
trs=tree.xpath("//tr[@class='item']")
for tr_item in trs:
book_url=tr_item.xpath("descendant::a[1]/@href")[0]
book = get_book(book_url)
save_book(book)
def main():
urls = get_urls()
for url in urls[:1]:
parse_list(url)
time.sleep(1.1)
马斯洛的锥子
有时候,我们用惯了爬虫工具,会陷进爬虫工具的牛角尖里面。或者说,「如果你有的只是一個錘子,那麼所有的東西看起來都像一個釘子」 – Abraham Maslow。