練習下BeautifulSoup,requests庫,用python3.3 寫了一個簡易的豆瓣小爬蟲,將爬取的信息在控制台輸出並且寫入文件中。
上源碼:
1 # coding = utf-8 2 '''my words 3 基於python3 需要的庫 requests BeautifulSoup 4 這個爬蟲很基本,沒有采用任何的爬蟲框架,用requests,BeautifulSoup,re等庫。 5 這個爬蟲的基本功能是爬取豆瓣各個類型的書籍的信息:作者,出版社,豆瓣評分,評分人數,出版時間等信息。 6 不能保證爬取到的信息都是正確的,可能有誤。 7 也可以把爬取到的書籍信息存放在數據庫中,這里只是輸出到控制台。 8 爬取到的信息存儲在文本txt中。 9 ''' 10 11 import requests 12 from bs4 import BeautifulSoup 13 import re 14 15 #爬取豆瓣所有的標簽分類頁面,並且提供每一個標簽頁面的URL 16 def provide_url(): 17 # 以http的get方式請求豆瓣頁面(豆瓣的分類標簽頁面) 18 responds = requests.get("https://book.douban.com/tag/?icn=index-nav") 19 # html為獲得響應的頁面內容 20 html = responds.text 21 # 解析頁面 22 soup = BeautifulSoup(html, "lxml") 23 # 選取頁面中的需要的a標簽,從而提取出其中的所有鏈接 24 book_table = soup.select("#content > div > .article > div > div > .tagCol > tbody > tr > td > a") 25 # 新建一個列表來存放爬取到的所有鏈接 26 book_url_list = [] 27 for book in book_table: 28 book_url_list.append('https://book.douban.com/tag/' + str(book.string)) 29 return book_url_list 30 31 #獲得評分人數的函數 32 def get_person(person): 33 person = person.get_text().split()[0] 34 person = re.findall(r'[0-9]+',person) 35 return person 36 37 #當detail分為四段時候的獲得價格函數 38 def get_rmb_price1(detail): 39 price = detail.get_text().split('/',4)[-1].split() 40 if re.match("USD", price[0]): 41 price = float(price[1]) * 6 42 elif re.match("CNY", price[0]): 43 price = price[1] 44 elif re.match("\A$", price[0]): 45 price = float(price[1:len(price)]) * 6 46 else: 47 price = price[0] 48 return price 49 50 #當detail分為三段時候的獲得價格函數 51 def get_rmb_price2(detail): 52 price = detail.get_text().split('/',3)[-1].split() 53 if re.match("USD", price[0]): 54 price = float(price[1]) * 6 55 elif re.match("CNY", price[0]): 56 price = price[1] 57 elif re.match("\A$", price[0]): 58 price = float(price[1:len(price)]) * 6 59 else: 60 price = price[0] 61 return price 62 63 #測試輸出函數 64 def test_print(name,author,intepretor,publish,time,price,score,person): 65 print('name: ',name) 66 print('author:', author) 67 print('intepretor: ',intepretor) 68 print('publish: ',publish) 69 print('time: ',time) 70 print('price: ',price) 71 print('score: ',score) 72 print('person: ',person) 73 74 75 76 77 #解析每個頁面獲得其中需要信息的函數 78 def get_url_content(url): 79 res = requests.get(url) 80 html = res.text 81 soup = BeautifulSoup(html.encode('utf-8'),"lxml") 82 tag = url.split("?")[0].split("/")[-1] #頁面標簽,就是頁面鏈接中'tag/'后面的字符串 83 titles = soup.select(".subject-list > .subject-item > .info > h2 > a") #包含書名的a標簽 84 details = soup.select(".subject-list > .subject-item > .info > .pub") #包含書的作者,出版社等信息的div標簽 85 scores = soup.select(".subject-list > .subject-item > .info > div > .rating_nums") #包含評分的span標簽 86 persons = soup.select(".subject-list > .subject-item > .info > div > .pl") #包含評價人數的span標簽 87 88 print("*******************這是 %s 類的書籍**********************" %tag) 89 90 #打開文件,將信息寫入文件 91 file = open("C:/Users/lenovo/Desktop/book_info.txt",'a') #可以更改為你自己的文件地址 92 file.write("*******************這是 %s 類的書籍**********************" % tag) 93 94 #用zip函數將相應的信息以元祖的形式組織在一起,以供后面遍歷 95 for title,detail,score,person in zip(titles,details,scores,persons): 96 try:#detail可以分成四段 97 name = title.get_text().split()[0] #書名 98 author = detail.get_text().split('/',4)[0].split()[0] #作者 99 intepretor = detail.get_text().split('/',4)[1] #譯者 100 publish = detail.get_text().split('/',4)[2] #出版社 101 time = detail.get_text().split('/',4)[3].split()[0].split('-')[0] #出版年份,只輸出年 102 price = get_rmb_price1(detail) #獲取價格 103 score = score.get_text() if True else "" #如果沒有評分就置空 104 person = get_person(person) #獲得評分人數 105 #在控制台測試打印 106 test_print(name,author,intepretor,publish,time,price,score,person) 107 #將書籍信息寫入txt文件 108 try: 109 file.write('name: %s ' % name) 110 file.write('author: %s ' % author) 111 file.write('intepretor: %s ' % intepretor) 112 file.write('publish: %s ' % publish) 113 file.write('time: %s ' % time) 114 file.write('price: %s ' % price) 115 file.write('score: %s ' % score) 116 file.write('person: %s ' % person) 117 file.write('\n') 118 except (IndentationError,UnicodeEncodeError): 119 continue 120 121 except IndexError: 122 try:#detail可以分成三段 123 name = title.get_text().split()[0] # 書名 124 author = detail.get_text().split('/', 3)[0].split()[0] # 作者 125 intepretor = "" # 譯者 126 publish = detail.get_text().split('/', 3)[1] # 出版社 127 time = detail.get_text().split('/', 3)[2].split()[0].split('-')[0] # 出版年份,只輸出年 128 price = get_rmb_price2(detail) # 獲取價格 129 score = score.get_text() if True else "" # 如果沒有評分就置空 130 person = get_person(person) # 獲得評分人數 131 #在控制台測試打印 132 test_print(name, author, intepretor, publish, time, price, score, person) 133 #將書籍信息寫入txt文件 134 try: 135 file.write('name: %s ' % name) 136 file.write('author: %s ' % author) 137 file.write('intepretor: %s ' % intepretor) 138 file.write('publish: %s ' % publish) 139 file.write('time: %s ' % time) 140 file.write('price: %s ' % price) 141 file.write('score: %s ' % score) 142 file.write('person: %s ' % person) 143 file.write('\n') 144 except (IndentationError, UnicodeEncodeError): 145 continue 146 147 except (IndexError,TypeError): 148 continue 149 150 except TypeError: 151 continue 152 file 153 154 file.write('\n') 155 file.close() #關閉文件 156 157 158 #程序執行入口 159 if __name__ == '__main__': 160 #url = "https://book.douban.com/tag/程序" 161 book_url_list = provide_url() #存放豆瓣所有分類標簽頁URL的列表 162 for url in book_url_list: 163 get_url_content(url) #解析每一個URL的內容
下面是效果圖: