需求:爬取這國內、國際、軍事、航空、無人機模塊下的新聞信息
1.找到這五個板塊對應的url
2.進入每個模塊請求新聞信息
我們可以明顯發現‘’加載中‘’,因此我們判斷新聞數據是動態加載出來的。
3.拿到新聞的標題和詳情url
4.請求詳情頁 獲取新聞內容
5.思路:思路已經很清晰了,請求五大板塊拿到五大板塊的詳情頁,獲取每一個板塊下的新聞標題和新聞詳情頁url,再對新聞詳情頁請求拿到新聞的內容。
需要注意的一點是,新聞都是動態加載出來的,因此我們用selenium來抓取新聞的數據。
6.代碼實現
爬蟲文件: wangyi.py
# -*- coding: utf-8 -*- import scrapy from selenium import webdriver from wangYi.items import WangyiItem class WangyiSpider(scrapy.Spider): name = 'wangyi' # allowed_domains = ['www.xxx.com'] start_urls = ['https://news.163.com/'] urls = [] def __init__(self): self.bro = webdriver.Chrome(executable_path='D:\OldBoy_Luffy\code_practice\chapter11\爬蟲\scrapy框架\chromedriver.exe') def parse(self, response): li_list = response.xpath('//*[@id="index2016_wrap"]/div[1]/div[2]/div[2]/div[2]/div[2]/div/ul/li') # 五大模塊所在li標簽的索引 index_list = [3,4,6,7,8] # 獲取五大模塊的url for index in index_list: model_src = li_list[index].xpath('./a/@href').extract_first() self.urls.append(model_src) # 發送請求 for url in self.urls: yield scrapy.Request(url=url, callback=self.parse_model) def parse_model(self,response): item = WangyiItem() # 每條新聞所在的div標簽 div_list = response.xpath('/html/body/div/div[3]/div[4]/div[1]/div/div/ul/li/div/div') for div in div_list: # 獲取標題與詳情頁的url title = div.xpath('./div/div[1]/h3/a/text()').extract_first() detail_url = div.xpath('./div/div[1]/h3/a/@href').extract_first() item['title'] = title # 部分的新聞中可能會有廣告信息 因此可能會匹配為空 跳過循環 if detail_url is None: continue # 請求詳情頁 請求傳參 yield scrapy.Request(url=detail_url, callback=self.detail_parse,meta={'item':item}) def detail_parse(self,response): item = response.meta['item'] # 獲取新聞內容 content = response.xpath('//div[@id="endText"]//text()').extract() content = ''.join(content) item['content'] = content # 存入管道 yield item def closed(self,spider): # 重寫父類方法 爬蟲結束時執行 self.bro.quit()
中間件middlewares.py
def process_response(self, request, response, spider): # spider就是爬蟲文件中 爬蟲類的實例化對象 # 拿到瀏覽器對象 bro = spider.bro if request.url in spider.urls: # 獲取動態加載的數據 bro.get(request.url) page_text = bro.page_source # 封裝成響應對象返回 new_response = HtmlResponse(url=request.url,body=page_text,encoding='utf-8',request=request) return new_response else: return response
items.py
class WangyiItem(scrapy.Item): # define the fields for your item here like: # name = scrapy.Field() title = scrapy.Field() content = scrapy.Field()
pipelines.py
class WangyiPipeline: def open_spider(self,spider): self.fp = open('news.txt','w',encoding='utf-8') print('爬取開始...') def process_item(self, item, spider): title = item['title'] content = item['content'] if title is None: title='' if content is None: content = '' self.fp.write(title+'\n'+content) return item def close_spider(self,spider): self.fp.close() print('爬取結束')