第三百三十四節,web爬蟲講解2—Scrapy框架爬蟲—Scrapy爬取百度新聞,爬取Ajax動態生成的信息
crapy爬取百度新聞,爬取Ajax動態生成的信息,抓取百度新聞首頁的新聞rul地址
有多網站,當你瀏覽器訪問時看到的信息,在html源文件里卻找不到,由得信息還是滾動條滾動到對應的位置后才顯示信息,那么這種一般都是 js 的 Ajax 動態請求生成的信息
我們以百度新聞為列:
1、分析網站
首先我們瀏覽器打開百度新聞,在網頁中間部分找一條新聞信息
然后查看源碼,看看在源碼里是否有這條新聞,可以看到源文件里沒有這條信息,這種情況爬蟲是無法爬取到信息的
那么我們就需要抓包分析了,啟動抓包軟件和抓包瀏覽器,前后有說過軟件了,就不在說了,此時我們經過抓包看到這條信息是通過Ajax動態生成的JSON數據,也就是說,當html頁面加載完成后才生成的,所有我們在源文件里無法找到,當然爬蟲也找不到
我們首先將這個JSON數據網址拿出來,到瀏覽器看看,我們需要的數據是不是全部在里面,此時我們看到這次請求里只有 17條信息,顯然我們需要的信息不是完全在里面,還得繼續看看其他js包
我們將抓包瀏覽器滾動條拉到底,以便觸發所有js請求,然后在繼續找js包,我們將所有js包都找完了再也沒看到新聞信息的包了
那信息就不在js包里了,我們回頭在看看其他類型的請求,此時我們看到很多get請求響應的是我們需要的新聞信息,說明只有第一次那個Ajax請求返回的JSON數據,后面的Ajax請求返回的都是html類型的字符串數據,
我們將Ajax請求返回的JSON數據的網址和Ajax請求返回html類型的字符串數據網址,拿來做一下比較看看是否能找到一定規律,
此時我們可以看到,JSON數據的網址和html類型的字符串數據網址是一個請求地址,
只是請求時傳遞的參數不一樣而已,那么說明無論返回的什么類型的數據,都是在一個請求地址處理的,只是根據不同的傳參返回不同類型的數據而已
http://news.baidu.com/widget?id=LocalNews&ajax=json&t=1501348444467 JSON數據的網址 http://news.baidu.com/widget?id=civilnews&t=1501348728134 html類型的字符串數據網址 http://news.baidu.com/widget?id=InternationalNews&t=1501348728196 html類型的字符串數據網址
我們可以將html類型的字符串數據網址加上JSON數據的網址參數,那是否會返回JSON數據類型?試一試,果然成功了
http://news.baidu.com/widget?id=civilnews&ajax=json 將html類型的字符串數據網址加上JSON數據的網址參數 http://news.baidu.com/widget?id=InternationalNews&ajax=json 將html類型的字符串數據網址加上JSON數據的網址參數
這下就好辦了,找到所有的html類型的字符串數據網址,按照上面的方法將其轉換成JSON數據的網址,然后循環的去訪問轉換后的JSON數據的網址,就可以拿到所有新聞的url地址了
crapy實現
# -*- coding: utf-8 -*- import scrapy from scrapy.http import Request,FormRequest import re import json from adc.items import AdcItem from scrapy.selector import Selector class PachSpider(scrapy.Spider): #定義爬蟲類,必須繼承scrapy.Spider name = 'pach' #設置爬蟲名稱 allowed_domains = ['news.baidu.com'] #爬取域名 start_urls = ['http://news.baidu.com/widget?id=civilnews&ajax=json'] qishiurl = [ #的到所有頁面id 'InternationalNews', 'FinanceNews', 'EnterNews', 'SportNews', 'AutoNews', 'HouseNews', 'InternetNews', 'InternetPlusNews', 'TechNews', 'EduNews', 'GameNews', 'DiscoveryNews', 'HealthNews', 'LadyNews', 'SocialNews', 'MilitaryNews', 'PicWall' ] urllieb = [] for i in range(0,len(qishiurl)): #構造出所有idURL kaishi_url = 'http://news.baidu.com/widget?id=' + qishiurl[i] + '&ajax=json' urllieb.append(kaishi_url) # print(urllieb) def parse(self, response): #選項所有連接 for j in range(0, len(self.urllieb)): a = '正在處理第%s個欄目:url地址是:%s' % (j, self.urllieb[j]) yield scrapy.Request(url=self.urllieb[j], callback=self.enxt) #每次循環到的url 添加爬蟲 def enxt(self, response): neir = response.body.decode("utf-8") pat2 = '"m_url":"(.*?)"' url = re.compile(pat2, re.S).findall(neir) #通過正則獲取爬取頁面 的URL for k in range(0,len(url)): zf_url = url[k] url_zf = re.sub("\\\/", "/", zf_url) pduan = url_zf.find('http://') if pduan == 0: print(url_zf) #輸出獲取到的所有url