requests正則表示式爬取貓眼電影
目標
通過Request+正則表示式爬取貓眼電影TOP100電影的排名、名字、電影封面圖片、主演、上映時間、貓眼評分,將爬取的內容寫入檔案中。
流程框架
進入到貓眼電影TOP100的頁面,此時的URL為http://maoyan.com/board/4,點選第2頁,會發現此時的URL為http://maoyan.com/board/4?offset=10,點選第3頁,會發現URL變成了http://maoyan.com/board/4?offset=20,由此可以推斷出offset引數為偏移量,如果偏移量為n,則顯示電影序號就是n+1到n+10,每頁顯示10個,所以,如果想獲取TOP100電影,只需要分開請求10次,而10次的offset引數分別設定為0、10、20......90即可,這樣獲取不同的頁面之後,再用正則表示式提取出相關資訊,就可以得到TOP100的所有電影資訊了。獲取資訊後,可以將資訊寫入txt檔案,當然可以存入資料庫(此處為了偷懶,就不存入資料庫了)。為了加快爬取網頁的速度,可以開啟迴圈和多執行緒(當需要爬取的資訊很大時,這是一個不錯的技巧)。
下圖展示了具體的流程框架:
(1)抓取單頁內容
# 獲取單個頁面的HTML程式碼 def get_one_page(url): try: # 此處如果不加headers進行偽裝,將會返回403錯誤(拒絕訪問) headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36" } response = requests.get(url, headers = headers) # 如果返回的狀態碼是200,表示請求正常,返回頁面HTML程式碼 # 否則,返回None if response.status_code == 200: return response.text return None except RequestException: return None
接下來測試一下是否可以獲取頁面內容:
if __name__ == '__main__':
url = 'http://maoyan.com/board/4'
html = get_one_page(url)
print(html)
(2)正則表示式分析
可以對get_one_page(url)函式爬取的HTML程式碼進行分析(此處為了方便觀看,直接在瀏覽器控制檯分析),利用正則表示式獲取到有用的資訊(電影的排名、名字、電影封面圖片、主演、上映時間、貓眼評分)。
# 解析單個頁面的HTML程式碼,利用re模組提取出有效資訊 def parse_one_page(html): # re.S:表示“.”的作用擴充套件到整個字串,包括“\n” pattern = re.compile('<dd>.*?board-index.*?>(\d+)</i>.*?data-src="(.*?)".*?name"><a' +'.*?>(.*?)</a>.*?star">(.*?)</p>.*?releasetime">(.*?)</p>.*?integer">' +'(.*?)</i>.*?fraction">(.*?)</i>.*?</dd>', re.S) items = re.findall(pattern, html) for item in items: # 構造生成器函式 yield{ 'index': item[0], 'image': item[1], 'title': item[2], 'actor': item[3].strip()[3:], 'time': item[4].strip()[5:], 'score': item[5]+item[6] }
接下來測試一下是否可以得到我們想要的內容:
if __name__ == '__main__':
url = 'http://maoyan.com/board/4'
html = get_one_page(url)
items = parse_one_page(html)
for item in items:
print(item)
控制檯輸出如下:
單個頁面資訊解析正確,那麼,想要獲得多個頁面的資訊,只需寫一個迴圈遍歷即可:
def main(offset):
url = 'http://maoyan.com/board/4?offset=' + str(offset)
html = get_one_page(url)
for item in parse_one_page(html):
print(item)
if __name__ == '__main__':
for i in range(10):
main(i*10)
(3)儲存至檔案
只需寫一個簡單的函式即可完成,但此處需要注意一點,為保證輸出檔案為中文,在讀寫檔案時要新增引數endcoding="utf-8"。
# 將解析出的內容寫入檔案
def write_to_file(content):
# 新增endcoding="utf-8"確保輸出到檔案中為中文
with open('result.txt', 'a', encoding='utf-8 ') as f:
# 此處建議將解析出的內容編碼為json格式再寫入檔案,json的好處在此不過多敘述
# 如果使用了json進行編碼,務必新增引數ensure_ascii=False確保編碼資料為中文
# json.dumps():編碼json資料
f.write(json.dumps(content, ensure_ascii=False) + '\n')
f.close()
執行程式碼,目標資訊被寫入result.txt檔案中:
(4)開啟迴圈及多執行緒
為了加快頁面爬取速度,可以使用多執行緒(針對大量資料時非常有效)。
if __name__ == '__main__':
pool = Pool()
pool.map(main, [i*10 for i in range(10)])
專案完整程式碼已託管到github:https://github.com/panjings/python-spider