1. 程式人生 > >python 通過ajax請求爬取今日頭條內容(僅程式碼+註釋+執行結果)

python 通過ajax請求爬取今日頭條內容(僅程式碼+註釋+執行結果)

學習書籍:《python3 網路爬蟲開發實戰》 –崔慶才
前提:下好MongoDB,以及各種第三方庫

  1. test.py
import json
import os
import re
from hashlib import md5
import pymongo
from urllib.parse import urlencode
import requests
from bs4 import BeautifulSoup
from requests.exceptions import RequestException
from config import *

#引入多程序
from multiprocessing import
Pool #宣告一個MongoDB資料庫物件 client=pymongo.MongoClient(MONGO_URL,connect=False) db=client[MONGO_DB] #獲取索引 def get_page_index(offset,keyword): data={ 'offset':offset, 'format':'json', 'keyword':keyword, 'autoload':'true', 'count': '20', 'cur_tab':'3', 'from'
: 'search_tab' } #進行編碼,加上引數 url='https://www.toutiao.com/search_content/?'+urlencode(data) try: response=requests.get(url) if response.status_code == 200: return response.text return None except RequestException: print('請求索引失敗') return
None #解析索引頁面,即搜尋出來的一個個總集合。需要獲取詳情頁面的url def parse_page_index(html): try: #通過loads將字串轉換成物件 data=json.loads(html) #使用了dict.keys()方法,返回所有鍵值 if data and 'data' in data.keys(): for item in data.get('data'): yield item.get('article_url') finally: print('解鎖成功') #獲取詳情 def get_page_detail(url): try: headers = { 'user-agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36' } response=requests.get(url,headers=headers) if response.status_code == 200: return response.text return None except RequestException: print('請求詳情頁面失敗',url) return None #解析獲取的HTML為json格式 def parse_page_detail(html,url): soup=BeautifulSoup(html,'lxml') title=soup.select('title')[0].get_text() images_pattern=re.compile('gallery: JSON.parse\\((.*?)\\),',re.S) result=re.search(images_pattern,html) if result: #網頁格式改了,需要解析2次才能正確解析 data=json.loads(json.loads(result.group(1))) if data and 'sub_images' in data.keys(): sub_images=data.get('sub_images') #遍歷sub_images,並獲取其中鍵值為url的資料,放入陣列中 images=[item.get('url') for item in sub_images] #已經獲取到所有圖片,迴圈,呼叫下載函式 for image in images:download_image(image) return { 'title':title, 'url':url, 'images':images } #儲存到資料庫,引數採用一個字典 def save_to_mongo(result): if db[MONGO_TABLE].insert(result): print('儲存成功',result) return True return False #下載(注意,這裡和前面不一樣的是請求response.content # content是返回二進位制內容,text返回網頁請求結果 #一般請求網頁用text,請求圖片用content def download_image(url): print('正在下載:',url) try: headers = { 'user-agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36' } response=requests.get(url,headers=headers) if response.status_code == 200: save_image(response.content) return None except RequestException: print('請求圖片下載出錯',url) return None #將download_image中獲取的response.text作為引數傳入 def save_image(content): #路徑包含三部分:哪個資料夾,圖片名,圖片字尾 #為了防止下重複的圖片,使用md5來防止 file_path='{0}/{1}.{2}'.format('F:\\image\\',md5(content).hexdigest(),'jpg') #如果檔案不存在,就儲存下來 if not os.path.exists(file_path): with open(file_path,'wb') as f: f.write(content) f.close() def main(offset): #KEYWORD在配置檔案中 html=get_page_index(offset,KEYWORD) for url in parse_page_index(html): #此處的html是每個詳情頁面的內容 html=get_page_detail(url) if html: result=parse_page_detail(html,url) save_to_mongo(result) if __name__=='__main__': #觀察頭條可發現,向下拉時候會不停發出ajax請求,並且每次 #都是引數offset偏移了20,這裡多程序執行main函式,加上offset引數 #來請求多組資料 groups=[x*20 for x in range(1,20)] #宣告一個程序池 pool=Pool() pool.map(main,groups)

2.config.py

#存入MongoDB
MONGO_URL='localhost'
MONGO_DB='toutiao'
MONGO_TABLE='toutiao1'

#定義一個offset偏移量,用於迴圈
GROUP_START=1
GROUP_END=20

#搜尋的關鍵字
KEYWORD='街拍'

3.執行結果截圖:
這裡寫圖片描述
這裡寫圖片描述