使用python爬豆瓣書單
背景介紹:非計算機專業,具有一點python編程基礎。 曾自學廖雪峰的《笨辦法學 Python(第四版)》、網易公開課《麻省理工學院公開課:計算機科學及編程導論》(以python為開發工具),另外購買了紙質版《python核心編程》以便遇到問題查看。爬蟲相關書籍看過《OReilly.Web.Scraping.with.Python》
目的:爬取豆瓣書籍信息,包括書名、作者、譯者、出版社及時間、評分人數及星星等級,並存儲於mysql資料庫。
使用的工具:python3.5,jupyter notebook,sublime text,mysql。
個人理解爬蟲過程主要分為三個步:
- 獲取網頁內容
- 解析網頁內容
- 存儲爬下來的數據
(1)獲取網頁內容
關鍵在於模擬成瀏覽器操作。
涉及到的知識:http相關基礎知識、cookie、session、幾個python的包requests、beautifulsoup等
1、首先,import需要的庫,包括:requests,beautifulsoup。獲取瀏覽器headers(可在瀏覽器開發工具請求報文中看),這一步是爬蟲偽裝成瀏覽器。根據具體情況看是否需要cookie。
import requestsfrom bs4 import BeautifulSoupheaders={"User-Agent":"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36","Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"}url="https://book.douban.com/"session=requests.session()
2、獲取網頁內容,涉及到知識:http相關知識,beautifulsoup、requests包,函數:beautifulsoup(),其中『lxml』格式需要自己另外安裝,findall()及find()。
def get_Content(url): res=session.get(url,headers=headers) req=BeautifulSoup(res.content,lxml) book_content=req.findAll("div",{"class":"info"}) return book_content
(2)解析網頁內容
涉及到知識點:正則表達式、數據類型的轉換、for循環語句、find()and findall()、get_text()函數、sub()、replace()、join()、split()等
1、import re(正則表達式庫),遍歷已經獲取的頁面內容(在getcontent函數中返回,其中findall函數返回的數據類型是list,這點跟find函數有所區別)通過find、gettext函數獲取需要的書籍信息,數據類型為字元型str。由於獲取到的內容的格式,並不是最終想要的格式,需要進行數據清洗,包括去掉
,多餘的空白、括弧、還有欄位「4524人評價」需要提取「4524」並存儲為數值型。對於為什麼需要判斷if not rate?是由於部分數據由於評價人員過少,缺失rating內容,這時候令rating=0,否則爬蟲爬到這本書的時候會報錯停止,最後通過float()將rating轉換成浮點型數值。針對"234評價"及"少於10人評價"情況的處理,用spilt(),跟正則表達式D+(非數值)將數字跟漢字分開,再通過join只留下人數並轉換成INT整型。
import re def get_items(book_content):global Tagfor i in book_content: title=get_cleandata(i.find("a").get_text()) tran=get_cleandata(i.find("div",{"class":"pub"}).get_text()) rate=i.find("span",{"class":"rating_nums"}) if not rate: rating=0 else: rating=float(get_cleandata(rate.get_text())) pl=int(.join(re.split(D+,get_cleandata(i.find("span",{"class":"pl"}).get_text())))) store(Tag,title,tran,rating,pl)def get_cleandata(data): cleandata=re.sub("
+","",data) cleandata=cleandata.replace("(","") cleandata=cleandata.replace(")","") cleandata=re.sub(" +","",cleandata) return cleandata
2、獲取所有需要爬取的url,一般有幾種方式獲取:
1.獲取「下一頁」的url,不斷的循環獲取,爬完一頁接著一頁。直到獲取下一頁的url為空停止。
2、分析不同頁數的url,找出規律,例如豆瓣讀書,下一頁的參數都是增加20(https://book.douban.com/tag/小說?start=20&type=T),這樣子就可以列出所有url,一直爬到返回的頁面內容為空停止。
我採用的是第二種辦法
1、首先,觀察頁數最大值找到合適的值,觀察到豆瓣最大的頁數是99
a=[a*20 for a in range(0,100)]
url參數的增加,通過urllib.parse.urlencode來增加。if not content 停止循環。最後通過time.sleep()控制循環時間,控制請求速度,模擬人點擊頁面,避免反爬策略。
import import urllib.parseimport timedef get_Start(url):global Tagfor i in Tag: a=[a*20 for a in range(0,100)] for r in a: time.sleep(3) values={"type":"T",start:r} data=urllib.parse.urlencode(values) a=url+"tag/"+i+?+data content=get_Content(a) if not content: break else: get_items(content)
其中還有獲取Tag的值,由於不想爬全部的書籍,就直接通過修改Tag的內容來爬感興趣的:
#def get_Tab(url): #r=session.get(url+"/tag/",headers=headers) #bsObj=BeautifulSoup(r.content,lxml) #Tag_contents=bsObj.findAll("a",href=re.compile("^/tag/.*")) #Tag=[tag.get_text()for tag in Tag_contents] #return TagTag=[哲學]
(3)存儲爬下來的信息
需要安裝mysql,一些資料庫操作的語句及基本知識
1、首先,import pymysql庫及設置好連接,在mysql裡面建立好database及相關的表
import pymysqlconn = pymysql.connect(host=localhost,user=root,passwd=lym*,db=mysql,charset=utf8)cur = conn.cursor()cur.execute("USE douban")
2、調用def store()函數存儲相關的數據
def store(Tag,title,tran,rating,pl): cur.execute("insert into philosophy(Tag,book,content,point,comment_num) values(%s,%s,%s,%s,%s)",(Tag,title,tran,rating,pl)) cur.connection.commit()
總結,整一個爬蟲流程是先import相關的庫,設置好開始的headers、開始url,然後getStart(url),獲取需要爬的url,再調用getitems(),獲取頁面內容,通過get_cleandata()對數據進行清洗,最後調用store()進行存儲爬下來的數據
下次,搞搞多線程
推薦閱讀:
※Python 關於讀寫txt的問題?
※Kivy中文編程指南:配置修改
※【Python】基本的搜索與排序演算法
※在Windows與MAC中同時安裝Python3.X與2.X的方法
※python3 csv/xls/json/pickle 等序列化反序列化代碼速查