前言
-
需求:爬取网易新闻中的五大板块的新闻数据(标题和内容)
-
1.通过网易新闻的首页解析出五大板块对应的详情页的url(没有动态加载)
-
2.每一个板块对应的新闻标题都是动态加载出来的(动态加载)
-
3.通过解析出每一条新闻详情页的url获取详情页的页面源码,解析出新闻内容
-
代码实现
先通过首页解析出五大板块对应详情页的url。
定义parse函数,对板块定位并发起请求。在首页打开开发者工具,定位到五大板块的标签,发现其各自在多个ul标签下的li标签中。我们的五大板块对应的li标签分别是3,4,6,7,8。因此从这几个li标签中提取各大板块对应的url。接下来对五个url发起请求。
def parse(self, response):
li_list = response.xpath('//*[@id="index2016_wrap"]/div[1]/div[2]/div[2]/div[2]/div[2]/div/ul/li')
alist = [3,4,6,7,8]
for index in alist:
model_url = li_list[index].xpath('./a/@href').extract_first()
self.models_urls.append(model_url)
#依次对每一个板块对应的页面进行请求
for url in self.models_urls:#对每一个板块的url进行请求发送
yield scrapy.Request(url,callback=self.parse_model)
定义parse_model函数,解析每一个板块页面中对应的新闻标题与新闻详情页的url,在板块页面中定位新闻标题,解析其标题与详情页url。
def parse_model(self,response):#解析每一个板块页面中对应新闻的标题和新闻详情页的url
div_list=response.xpath('/html/body/div/div[3]/div[4]/div[1]/div[1]/div/ul/li/div/div')
for div in div_list:
title=div.xpath('./div/div[1]/h3/a/text()').extract_first()
news_detail_url=div.xpath('./div/div[1]/h3/a/@href').extract_first()
解析出新闻标题title后,在items文件中定义一个WangyiproItem类,用来保存要提取的内容(title,content)。随后可通过scrapy.Field将其提交管道。
#items文件
import scrapy
class WangyiproItem(scrapy.Item):
title=scrapy.Field()
content=scrapy.Field()
item=WangyiproItem()
item['title']=title
对新闻详情页url发起请求,需加上参数meta
yield scrapy.Request(url=news_detail_url,callback=self.parse_detail,meta={'item':item})
定义parse_detail函数解析新闻内容
def parse_detail(self,response):#解析新闻内容
content=response.xpath('//*[@id="content"]/div[2]//text()').extract()
content=''.join(content)
item=response.meta['item']
item['content']=content
yield item
关闭spider文件
def close(self, spider):
self.driver.quit()
因为每个板块加载出来的标题是动态加载的,因此使用中间件进行拦截五大板块对应的响应对象,进行篡改。
定义process_response函数进行篡改
def process_response(self, request, response, spider):#spider表示的是爬虫对象
driver=spider.driver#获取了爬虫类中定义的浏览器对象
# 挑选出指定的响应对象进行篡改
# 通过url指定request
# 通过request指定response
if request.url in spider.models_urls:
driver.get(request.url)#五个板块对应的url进行请求
sleep(2)
page_text=driver.page_source#包含了动态加载的新闻数据
#response#五大板块所对应的响应对象
#针对定位到的这些response进行篡改
#实例化一个新的响应对象(符合需求:包含动态加载出的新闻数据),替换原来旧的响应对象
#如何让获取动态加载出的新闻数据呢?
#基于selenium便捷的获取动态加载数据
new_response=HtmlResponse(url=request.url,body=page_text,encoding='utf-8',request=request)
return new_response
else:
# response#其他请求对应的响应对象
return response
return response
在setting中开启下载中间件,即可。