zoukankan      html  css  js  c++  java
  • scrapy中间件之下载中间件使用(网易新闻爬取)

    scrapy项目中的middlewarse.py中间件  

    爬虫中间件:目前先不介绍

    下载中间件(需要在settings.py中开启) 

                    

    (1)请求处理函数:process_request(self, request, spider)
      可以针对url请求指定UA伪装、配置代理等功能(UA伪装可以在settings.py中进行全局配置,代理配置更倾向于在异常处理函数,大部分异常都是因为ip的问题)  
    1   def process_request(self, request, spider):
    2         #UA伪装
    3         # request.headers['User-Agent']=random.choice(UA_list)
    4         
    5         #ip代理配置(一般更多的放在process_exception异常处理函数中)
    6         # request.meta['proxy']='http[s]://ip:port'
    7         return None
    process_request
    (2)响应处理函数:process_response(self, request, response, spider)
      对于一些网页请求,立即相应的数据可能不完全,页面部分内容是通过触发滚轮或者下拉操作才会动态加载的数据,因此获取的到数据并不是完整的,需要对响应对象进行篡改(比如通过selenium模拟浏览器操作获取到完整数据)后返回。
      
    (3)异常处理函数:process_exception(self, request, exception, spider)
      对于请求异常处理,一般可以更换ip设置代理操作
    1  def process_exception(self, request, exception, spider):
    2         #对请求异常进行修正
    3         #更换代理(一定要 return request将请求返回以便再次发起)
    4         # request.meta['proxy']='http[s]://ip:port'
    5         # return request
    6         pass
    process_exception

    网易新闻爬取案例:

      分析页面可以获知不同板块内容都是页面下拉动态加载的:国内、国际、军事、航空、无人机这几个板块内容都是标题都是在div中的一个a标签中,因此统一来进行爬取解析!

       1.新建爬虫项目  

    scrapy startproject firstPro
    cd firstPro
    scrapy genspider middlewareTest www.xxx.com  

      2.编写爬虫文件middlewareTest.py

     1 # -*- coding: utf-8 -*-
     2 import scrapy
     3 from firstPro.items import FirstproItem
     4 from selenium import webdriver
     5 
     6 
     7 class MiddlewaretestSpider(scrapy.Spider):
     8     name = 'middlewareTest'
     9     # allowed_domains = ['www.xxx.com']
    10     start_urls = ['https://news.163.com/']
    11     plate_urls=[]#存放板块的url,以便在下载中间件次改请求获取完整标题数据
    12     def __init__(self):
    13         self.bro=webdriver.Chrome(executable_path=r'E:Python项目爬虫day110_20190809(全站爬取、分布式爬虫)firstProfirstProspiderschromedriver.exe')#初始化浏览器实例
    14     def parse(self, response):
    15         #解析首页标题板块
    16         li_list=response.xpath('//div[@class="ns_area list"]/ul/li')
    17         print(len(li_list))
    18         #确定爬取的板块
    19         index_list=[4,5,7,8,9]
    20         for index in index_list:
    21             item=FirstproItem()
    22             plate=li_list[index-1].xpath('./a/text()').extract_first()
    23             url=li_list[index-1].xpath('./a/@href').extract_first()
    24             self.plate_urls.append(url)
    25             item['plate']=plate
    26             # 对每个板块进行发起请求,获取标题信息
    27             yield scrapy.Request(url,callback=self.parse_title,meta={"item":item})
    28             break
    29     #对每个板块的新闻标题进行解析,但是新闻标题都是动态加载的,因此直接的响应对象不完整,需要通过下载中间件对新闻板块标题获取进行处理
    30     #解决思路:为获取板块完整标题内容,需要模拟浏览器下拉操作,结合使用selenuim在下载中间件进行操作
    31     def parse_title(self, response):
    32         item=response.meta['item']
    33         #解析每个板块中的新闻标题
    34         div_list=response.xpath('//div[@class="ndi_main"]/div')
    35         for div in div_list:
    36             title=div.xpath('./div/div[1]/h3/a/text()').extract_first()
    37             url=div.xpath('./div/div[1]/h3/a/@href').extract_first()
    38             item["title"]=title
    39             #对每个标题详情发起请求
    40             yield scrapy.Request(url,callback=self.parse_detail,meta={"item":item})
    41 
    42     def parse_detail(self,response):
    43         item = response.meta['item']
    44         #解析每个标题对应的详细新闻内容
    45         content="".join(response.xpath('//*[@id="endText"]//text()').extract())
    46         item["content"]=content
    47         yield item
    48 
    49     # 程序全部结束的时候被调用
    50     def closed(self, spider):
    51         print('结束爬虫!!!')
    52         self.bro.quit()
    爬虫脚本middlewareTest.py

      3.定义items.py字段属性

     1 import scrapy
     2 
     3 class FirstproItem(scrapy.Item):
     4     # define the fields for your item here like:
     5     # name = scrapy.Field()
     6     #新闻板块
     7     plate=scrapy.Field()
     8     #新闻标题
     9     title=scrapy.Field()
    10     #新闻详情
    11     content=scrapy.Field()
    12     pass
    items.py

      4.管道pipelines.py持久化

     1 import redis
     2 class FirstproPipeline(object):
     3     #持久化存储在redis数据库中
     4     conn=None
     5     # def open_spider(self,spider):
     6     #     self.conn=redis.Redis(host="127.0.0.1",port=6379)
     7 
     8     def process_item(self, item, spider):
     9         # self.conn.lpush('wangyi',dict(item))
    10         print(item)
    11         return item
    pipelines.py

      5.settings.py配置

     1 #UA伪装
     2 USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36"
     3 
     4 #robots协议
     5 ROBOTSTXT_OBEY = False
     6 
     7 #输出日志等级
     8 LOG_LEVEL="ERROR"
     9 
    10 #打开下载中间件
    11 DOWNLOADER_MIDDLEWARES = {
    12    'firstPro.middlewares.FirstproDownloaderMiddleware': 543,
    13 }
    14 
    15 #打开管道
    16 ITEM_PIPELINES = {
    17    'firstPro.pipelines.FirstproPipeline': 300,
    18 }
  • 相关阅读:
    spring mvc poi excel
    select onchange事件的使用
    eclipse下svn的分支与合并指南
    jquery_final
    ListView
    资源的使用
    Notification
    单选
    复选框
    调试
  • 原文地址:https://www.cnblogs.com/open-yang/p/11341127.html
Copyright © 2011-2022 走看看