無聊的時候,咱們總會打開豆瓣電影榜,從上到下刷着電影,彷彿那些經典臺詞立刻就在咱們耳邊響起,如《肖申克的救贖》中:生活能夠歸結爲一種簡單的選擇:不是忙於生存,就是趕着去死;《霸王別姬》中:說的是一生!差一年,一個月,一天,一個時辰,都不算一生!可是,豆瓣電影那麼多,還有那麼多頁,一頁一頁的找豈不是太費時間了,今天我就來從前端的角度來爬取豆瓣電影榜top250的首頁。豆瓣top250javascript
因爲咱們須要向豆瓣的服務器發送一個請求來獲得豆瓣首頁的html代碼,請求與響應在網絡傳輸中須要必定的時間,然後續的操做須要在這個響應的基礎上進行,所以,咱們須要將主函數定義爲異步的。以上實現須要引入下面兩個包(注意:request 是對等依賴,須要與request-promise 分開安裝)html
npm i request
npm i request-promise
複製代碼
let request = require('request-promise')
const main = async() => {
let html = await request({
url: 'https://movie.douban.com/top250'
})
console.log(html)
}
main();
複製代碼
這樣,咱們就獲得了豆瓣首頁的html代碼,可是咱們須要的只是不多的一部分信息,因此咱們要對其中的信息進行提取,所以咱們引入一個npm包cheerio來提取html 特定選擇器中的文本內容前端
npm i cherrio
複製代碼
而後在第二行引入java
let cheerio = require('cheerio');
複製代碼
接下來咱們要作的就是利用cheerio 將獲得的html文本載入內存構建DOM,並使用選擇器對目標標籤中的文本進行提取,所以咱們須要分析豆瓣首頁的html結構node
根據上面咱們對結構的分析,咱們就可使用下列語句獲得咱們選擇器內的每個itempython
let movieNodes = $('#content .article .grid_view').find('.item');
複製代碼
而後咱們對保存了全部item的這樣一個數組遍歷,將其中每一項的關鍵值提取出來並保存,選擇器的構建方法與上述的item得到的方法一致npm
let movies = [];
for (let i = 0; i < movieNodes.length; i++) {
let $ = cheerio.load(movieNodes[i]);
let titles = $('.info .hd span');
titles = ([]).map.call(titles, t => $(t).text());
let bd = $('.info .bd');
let info = bd.find('p').text();
let score = bd.find('.star .rating_num').text();
movies.push({
'titles': titles,
'info': info,
'score': score
})
}
複製代碼
不一樣的是,因爲.hd 的選擇器下面有四個span,所以咱們獲得的是一個對象數組,咱們不能直接進行提取不然會出現對象循環引用的錯誤,咱們先使用map對空數組的每個元素進行映射,而後再經過改變this指針,使用選擇器對空數組中每個元素進行賦值。而後將提取出來的每個字段append到數組中。編程
接下來,咱們在第三行加上json
let fs = require('fs');
複製代碼
在for循環的外面繼續補充api
fs.writeFile('./mainjs.json', JSON.stringify(movies), 'utf-8', (err) => {
if (err)
console.log('寫入失敗');
else
console.log('寫入成功');
});
複製代碼
就能夠將咱們剛剛在存在數組中的數據以json格式寫入文件中啦,打開這個文件就會發現豆瓣top250的首頁內容就存到了這個文件中,咱們就能夠挑選本身喜歡的電影觀看了。 如今,讓咱們回過頭來看看豆瓣top250首頁的頁面結構
body豆瓣的首頁由100%的body佔據,body又分爲上中下三部分,每一個版塊又按照必定的功能再劃分爲相應的子模塊,直到劃分爲一個最小的模塊爲止,每個模塊佔據網頁的必定位置,實現某一個特定的功能,每一個模塊之間互不干擾。經過對豆瓣的爬取,咱們知道了,若是一個網站的結構帶有必定規律,並有良好的可讀性,會讓咱們的爬取更加簡單,相反,若是一個網站亂糟糟的,毫無章法可言,那麼這樣的網站簡直就是災難。所以,咱們在從此的編程中,應當多看看一些大型網站的html代碼,學習其中的結構設計和命名規範。而後咱們可使用BEM(Block Element Modifier)命名規範,對每個模塊使用合適的選擇器,這樣不只提升了代碼的可重用行,也利於網站的管理和維護。 暑假閒來無事看了點python視頻,雖然已經忘得都差很少了,可是用了node爬取了一次,又讓我又拾起的對python的熱情,因而一番折騰,查了相關文檔,終於給搗鼓出來了,畢竟,生命在於折騰嘛! 如下是python的爬蟲方式,基本思路與上述爬蟲方式相似,只是對數據處理的語法上有所差別:
須要安轉requests和beautifulsoup4模塊
pip install requests
pip install beautifulsoup4
複製代碼
import requests
from bs4 import BeautifulSoup
import json
def gettext(x):
return x.get_text()
#設置請求頭假裝
header = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36'}
# 先使用requests發送網絡請求從而獲取網頁
html = requests.get('https://movie.douban.com/top250', headers=header)
# print(html.status_code)
# 傳入html構建DOM
soup=BeautifulSoup(html.content,'html.parser')
movieNodes = soup.find('ol', attrs={'class': 'grid_view'})
movies=[]
for movie in movieNodes.find_all('li'):
title=movie.find('div',attrs={'class':'hd'})
titles=title.find_all('span')
titles1=map(gettext,titles)
tit=[]
for ti in titles1:
tit.append(ti)
info=movie.find('p').get_text()
score=movie.find('span',attrs={'class':'rating_num'}).get_text()
movies.append({
"titles": tit,
"info": info,
"score": score
})
f = open("mainpy.json", "w", encoding='utf-8')
json.dump(movies, f, ensure_ascii=False)
f.close()
複製代碼
可能有時候寫程序就是這樣,出一個問題而後你就去解決這個問題,而後又出現另外的問題,你又得想怎麼去解決新出現的問題,而後一直一直....結果發現直接使用一個api就行了...可是寫程序注重的是過程,bug是咱們編程道路上的補品,咱們不能作一個apier,不是嗎?