一、爬蟲任務
任務背景:爬取貓眼電影Top100資料
任務目標:運用正則運算式去決議網頁原始碼并獲得所需資料
二、決議
任務URL:https://maoyan.com/board/4?offset=0
下圖為貓眼電影的第一頁:

再看看第二頁:

最后看看第三頁:

我們把這三頁的URL復制下來,看一下URL規律:
1 https://maoyan.com/board/4?offset=0 2 https://maoyan.com/board/4?offset=10 3 https://maoyan.com/board/4?offset=20
從上面的URL可以看出,只有offset變化,offset意為偏移量,從中可以看出每一頁的偏移量為10,可以把該引數定義為自變數,然后用回圈爬取前10頁的資料,也就是top100的資料
爬取任務
爬取貓眼電影top100電影的電影排名,圖片地址,演員,電影名,上映時間以及電影評分
決議網頁源代碼

點擊箭頭打開dd標簽塊,看看具體的資訊:

再看看network中的真實資料:

從以上的圖中可以看出貓眼電影的資料都保存在dd標簽塊中,接下來就要用正則運算式去匹配所需的資料,再把這些資料以json格式保存到文本檔案中以及MongoDB資料庫中
三、編碼
獲取網頁原始碼
定義一個去獲取HTML原始碼的方法
1 import requests 2 from requests import exceptions 3 4 def get_one_page(url): 5 ''' 6 headers表示要傳遞的頭資訊,'User-Agent'表示偽裝瀏覽器 7 ''' 8 try: 9 headers = {'User-Agent':'Mozilla/5.0'} 10 response = requests.get(url,headers=headers) 11 if response.status_code == 200: 12 return response.text 13 else: 14 return None 15 except exceptions.RequestException: 16 return None
決議原始碼并獲得資料
1 import re 2 3 def parse_one_page(html): 4 ''' 5 re.compile()方法會將正則運算式字串轉換為正則運算式物件,方便以后的復用 6 re.S表示修飾符,可以忽略換行符 7 re.findall()方法會將所有符合匹配模式的資料回傳,并且以串列形式回傳 8 yield是Python中的關鍵字,表示生成器,類似于return 9 strip()方法可以把空的部分去掉,包括空格,換行符等,但它的操作物件必須是字串 10 ''' 11 pattern = re.compile('<dd>.*?board-index.*?>(\d+)</i>.*?data-src="https://www.cnblogs.com/makerchen/p/(.*?)".*?name"><a' 12 + '.*?>(.*?)</a>.*?star">(.*?)</p>.*?releasetime">(.*?)</p>' 13 + '.*?integer">(.*?)</i>.*?fraction">(.*?)</i>.*?</dd>',re.S) 14 movies_information = re.findall(pattern,html) 15 for movie_information in movies_information: 16 yield { 17 '電影排名':movie_information[0], 18 '圖片地址':movie_information[1], 19 '電影名':movie_information[2].strip(), 20 '演員':movie_information[3].strip()[3:] if len(movie_information) > 3 else '', 21 '上映時間':movie_information[4].strip()[5:] if len(movie_information) > 5 else '', 22 '評分':movie_information[5].strip() + movie_information[6].strip() 23 }
保存資料到文本檔案
1 import json 2 3 def write_movies_data_to_file(movie_information): 4 ''' 5 'a'表示以追加方式把資料寫入檔案中,這樣就不會覆寫之前寫入的資料 6 json.dumps()方法可將json文本字串序列化為json物件 7 ensure_ascii=False表示忽略ASCII碼,默認也為False 8 indent表示json格式的縮進 9 ''' 10 with open('../txt_file/maoyan_movies_information.txt','a',encoding='utf-8') as f: 11 f.write(json.dumps(movie_information,indent=2,ensure_ascii=False) + '\n')
保存資料到MongoDB資料庫
1 import pymongo 2 3 def insert_to_mongodb(content): 4 ''' 5 client表示操作MongoDB資料庫的物件 6 db表示資料庫物件 7 collection表示集合物件,類似于MySQL中的table 8 ''' 9 client = pymongo.MongoClient(host='localhost',port=27017) 10 db = client['spiders'] 11 collection = db['maoyan_movies_data'] 12 try: 13 if content: 14 collection.insert(content) 15 print('Success to insert!') 16 except: 17 print('Failed to insert!')
定義main()方法控制程式的運行
1 def main(offset): 2 ''' 3 offset={offset}表示頁數偏移量,這里用f-string函式把它設定為自變數,從而可以回圈爬取 4 ''' 5 url = f'https://maoyan.com/board/4?offset={offset}' 6 html = get_one_page(url) 7 for movie_information in parse_one_page(html): 8 print(movie_information) 9 write_movies_data_to_file(movie_information) 10 insert_to_mongodb(movie_information)
主程式運行
1 import time 2 3 if __name__ == '__main__': 4 ''' 5 time模塊延遲爬取時間,貓眼已經加了反爬 6 ''' 7 for i in range(10): 8 main(offset=i*10) 9 time.sleep(1)
完整原始碼如下
1 import requests 2 import re 3 import time 4 from requests import exceptions 5 import json 6 import pymongo 7 8 def get_one_page(url): 9 try: 10 headers = {'User-Agent':'Mozilla/5.0'} 11 response = requests.get(url,headers=headers) 12 if response.status_code == 200: 13 return response.text 14 else: 15 return None 16 except exceptions.RequestException: 17 return None 18 19 def parse_one_page(html): 20 pattern = re.compile('<dd>.*?board-index.*?>(\d+)</i>.*?data-src="https://www.cnblogs.com/makerchen/p/(.*?)".*?name"><a' 21 + '.*?>(.*?)</a>.*?star">(.*?)</p>.*?releasetime">(.*?)</p>' 22 + '.*?integer">(.*?)</i>.*?fraction">(.*?)</i>.*?</dd>',re.S) 23 movies_information = re.findall(pattern,html) 24 for movie_information in movies_information: 25 yield { 26 '電影排名':movie_information[0], 27 '圖片地址':movie_information[1], 28 '電影名':movie_information[2].strip(), 29 '演員':movie_information[3].strip()[3:] if len(movie_information) > 3 else '', 30 '上映時間':movie_information[4].strip()[5:] if len(movie_information) > 5 else '', 31 '評分':movie_information[5].strip() + movie_information[6].strip() 32 } 33 34 def write_movies_data_to_file(movie_information): 35 with open('../txt_file/maoyan_movies_information.txt','a',encoding='utf-8') as f: 36 f.write(json.dumps(movie_information,indent=2,ensure_ascii=False) + '\n') 37 38 def main(offset): 39 url = f'https://maoyan.com/board/4?offset={offset}' 40 html = get_one_page(url) 41 for movie_information in parse_one_page(html): 42 print(movie_information) 43 write_movies_data_to_file(movie_information) 44 insert_to_mongodb(movie_information) 45 46 def insert_to_mongodb(content): 47 client = pymongo.MongoClient(host='localhost',port=27017) 48 db = client['spiders'] 49 collection = db['maoyan_movies_data'] 50 try: 51 if content: 52 collection.insert(content) 53 print('Success to insert!') 54 except: 55 print('Failed to insert!') 56 57 if __name__ == '__main__': 58 for i in range(10): 59 main(offset=i*10) 60 time.sleep(1)
運行效果
控制臺輸出:

json格式的txt文本結果:

MongoDB輸出結果:

四、總結
請求庫requests及exceptions模塊
標準庫re
time模塊
json模塊
Python與MongoDB資料庫對接的pymongo庫
更多獨家精彩內容 請掃碼關注個人公眾號,一起Coding吧!
—— —— —— —— — END —— —— —— —— ————
歡迎掃碼關注我的公眾號
小鴻星空科技

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/350692.html
標籤:Python
