隨着時代的發展,國人對於閱讀的需求也是日益增加,既然要閱讀,就要讀好書,什麼是好書呢?本項目選擇以豆瓣圖書網站爲對象,統計其排行榜的前250本書籍。html
本項目使用Python爬蟲技術統計豆瓣圖書網站上排名前250的書籍信息,包括書名、做者、出版社、出版日期、價格、評星、簡述信息mysql
將獲取到的信息存儲在Mysql數據庫中git
第一頁地址爲:https://book.douban.com/top250,打開後頁面呈現爲以下: github
咱們須要得到的信息爲每一本書的全部信息: sql
因此思路爲:數據庫
解析這一頁--->獲得這一頁全部圖書的信息瀏覽器
使用開發者模式查看網頁源代碼(Chrome瀏覽器按F12),選擇network後,刷新網頁,效果以下圖: ide
以後點擊top250--->Response,以下圖:學習
此時就會在右下方看到網頁的源代碼,分析源代碼可知:網站
每一本書都是被「table標籤,class=item」擴起來的,好比《追風箏的人》源代碼在253-307行。
使用requests模塊獲取源代碼,Python代碼以下:
import requests
def parse_index(url): ''' 解析索引頁面 返回圖書全部信息 ''' try: response = requests.get(url) if response.status_code == 200: return response.text except Exception as e: print('error:', e)
『防抄襲:讀者請忽略這段文字,文章做者是博客園的MinuteSheep』
獲取到頁面源代碼後,接下來要作的工做就是解析每一本圖書的詳細信息了。因此思路繼續深刻:
解析這一頁--->獲得這一頁全部圖書的信息--->解析一本圖書--->將圖書詳細信息保存爲字典格式
書名都是被「a標籤」擴起來的,好比《追風箏的人》書名源代碼在268-274行;
做者、出版社、出版日期、價格都是被「p標籤,class=pl」擴起來的,好比《追風箏的人》這些信息源代碼在285行;
評星都是被「span標籤,class=rating_nums」擴起來的,好比《追風箏的人》評星源代碼在292行;
簡述信息都是被「span標籤,class=inq」擴起來的,好比《追風箏的人》簡述信息源代碼在301行。
Python源代碼以下:
from bs4 import BeautifulSoup
def parse(text): ''' 解析圖書詳細信息 ''' soup = BeautifulSoup(text.strip(), 'lxml') books = soup.select('.item') info = {} for book in books: info.clear() info['title'] = book.select('.pl2 a')[0].get_text( ).strip().replace(' ', '').replace('\n', '') info['author'] = book.select( '.pl')[0].get_text().strip().split('/')[0].strip() info['publishers'] = book.select( '.pl')[0].get_text().strip().split('/')[-3].strip() info['date'] = book.select( '.pl')[0].get_text().strip().split('/')[-2].strip() info['price'] = book.select( '.pl')[0].get_text().strip().split('/')[-1].strip() info['star'] = float(book.select('.rating_nums')[0].get_text()) info['summary'] = book.select('.inq')[0].get_text( ).strip() if book.select('.inq') else '' yield info
進入Mysql的交互環境,依次創建數據庫、建立數據表:
create database douban;
use douban;
create table book_top250( -> id int not null primary key auto_increment, -> title char(100) not null unique key, -> author char(100) not null, -> publisher char(100), -> date char(100), -> price char(100) -> star float, -> summary char(100) ->);
以後使用Mysql官方推薦的鏈接庫:mysql.connector
Python代碼以下:
import mysql.connector
def open_mysql(): ''' 鏈接mysql ''' cnx = mysql.connector.connect(user='minutesheep', database='douban') cursor = cnx.cursor() return cnx, cursor def save_to_mysql(cnx, cursor, info): ''' 將數據寫入mysql ''' add_book_top250 = ("INSERT IGNORE INTO book_top250 " "(title,author,publishers,date,price,star,summary) " "VALUES (%(title)s, %(author)s, %(publishers)s, %(date)s, %(price)s, %(star)s, %(summary)s)") cursor.execute(add_book_top250, info) cnx.commit() def close_mysql(cnx, cursor): ''' 關閉mysql ''' cursor.close() cnx.close()
到此爲止,一本圖書的信息就已經保存完畢了
如今只須要將本頁面的全部圖書遍歷一遍,就完成了一個頁面的抓取
『防抄襲:讀者請忽略這段文字,文章做者是博客園的MinuteSheep』
最後只須要將全部頁面遍歷就能夠抓取到250本圖書了。如今觀察每一頁的URL變化:
第一頁:https://book.douban.com/top250 或 https://book.douban.com/top250?start=0
第二頁:https://book.douban.com/top250?start=25
第三頁:https://book.douban.com/top250?start=50
第十頁(最後一頁):https://book.douban.com/top250?start=225
經過觀察可知,後一頁的URL只須要將前一頁的URL最後的數字加25
基於此,Python代碼爲:
def main(): base_url = 'https://book.douban.com/top250?start=' cnx, cursor = open_mysql() for page in range(0, 250, 25): index_url = base_url + str(page) text = parse_index(index_url) info = parse(text) for result in info: save_to_mysql(cnx, cursor, result) close_mysql(cnx, cursor)
import requests from bs4 import BeautifulSoup import mysql.connector def parse_index(url): ''' 解析索引頁面 返回圖書全部信息 ''' try: response = requests.get(url) if response.status_code == 200: return response.text except Exception as e: print('error:', e) def parse(text): ''' 解析圖書詳細信息 ''' soup = BeautifulSoup(text.strip(), 'lxml') books = soup.select('.item') info = {} for book in books: info.clear() info['title'] = book.select('.pl2 a')[0].get_text( ).strip().replace(' ', '').replace('\n', '') info['author'] = book.select( '.pl')[0].get_text().strip().split('/')[0].strip() info['publishers'] = book.select( '.pl')[0].get_text().strip().split('/')[-3].strip() info['date'] = book.select( '.pl')[0].get_text().strip().split('/')[-2].strip() info['price'] = book.select( '.pl')[0].get_text().strip().split('/')[-1].strip() info['star'] = float(book.select('.rating_nums')[0].get_text()) info['summary'] = book.select('.inq')[0].get_text( ).strip() if book.select('.inq') else '' yield info def open_mysql(): ''' 鏈接mysql ''' cnx = mysql.connector.connect(user='minutesheep', database='douban') cursor = cnx.cursor() return cnx, cursor def save_to_mysql(cnx, cursor, info): ''' 將數據寫入mysql ''' add_book_top250 = ("INSERT IGNORE INTO book_top250 " "(title,author,publishers,date,price,star,summary) " "VALUES (%(title)s, %(author)s, %(publishers)s, %(date)s, %(price)s, %(star)s, %(summary)s)") cursor.execute(add_book_top250, info) cnx.commit() def close_mysql(cnx, cursor): ''' 關閉mysql ''' cursor.close() cnx.close() def main(): base_url = 'https://book.douban.com/top250?start=' cnx, cursor = open_mysql() for page in range(0, 250, 25): index_url = base_url + str(page) text = parse_index(index_url) info = parse(text) for result in info: save_to_mysql(cnx, cursor, result) close_mysql(cnx, cursor) if __name__ == '__main__': main()
整個項目地址:https://github.com/MinuteSheep/DoubanBookTop250
Mysql部分數據以下圖:
提醒:僅供學習使用,商用後果自負