scrapy中間件php
scrapy中間件分爲兩種: 一種是:下載器和引擎之間的下載器中間件 做用: 處於引擎和下載器之間,此中間件能夠攔截整個工程中發起的請求和響應數據 另外一種是: 爬蟲程序跟引擎之間的下載器中間件 攔截請求幹什麼? 代理ip : request.meta['proxy'] = 'http://ip:port' UA假裝 : request.headers['User-Agent'] = 'xxxxxx' 攔截響應幹什麼? 篡改響應數據 (基本上不會對響應數據進行修改) 更換響應對象 (基本上就是用來更改代理ip)
在scrapy中使用selenium
在爬蟲類中定義一個bro屬性(selenium實例化的一個瀏覽器對象)
在爬蟲類中重寫一個closed(self,spider),在該方法中關閉瀏覽器對象
在中間件的process_response中經過spider參數爬取爬蟲類中的bro屬性
在中間件中編寫瀏覽器自動化操做獲取頁面源碼數據
將頁面源碼數據做爲新響應對象的響應數據
將新的響應對象返回
基於crawlSpider的全站數據爬取html
crawlSpider和Spider之間的關聯
crawlSpider是Spider的一個子類
建立一個基於crawlSpider的爬蟲文件
scrapy genspider -t crawl pcpro www.xxx.com
實例代碼:web
爬蟲文件代碼:chrome
import scrapy from scrapy.linkextractors import LinkExtractor from scrapy.spiders import CrawlSpider, Rule from sunShinePro.items import SunshineproItem,sunConetent # http://wz.sun0769.com/index.php/question/questionType?type=4&page=30 class SunSpider(CrawlSpider): name = 'sun' # allowed_domains = ['www.xxx.com'] start_urls = ['http://wz.sun0769.com/index.php/question/questionType?type=4&page='] #連接提取器 #做用:根據 指定的規則(allow:正則) 提取頁面源碼中指定的鏈接 link = LinkExtractor(allow=r'type=4&page=\d+') link_detail = LinkExtractor(allow='question/\d+/\d+\.shtml') rules = ( #規則解析器:將鏈接提取器提取到的鏈接對應的頁面源碼數據 根據指定規則(callback) 進行數據解析 Rule(link, callback='parse_item', follow=False), Rule(link_detail, callback='parse_detail'), ) def parse_detail(self,response): content = response.xpath('/html/body/div[9]/table[2]//tr[1]/td/div[2]//text()').extract() content = ''.join(content) item = sunConetent() item['content'] = content yield item def parse_item(self, response): #注意:若是xpath定位的標籤中存在tbody,則須要跳過tbody tr_list = response.xpath('//*[@id="morelist"]/div/table[2]//tr/td/table//tr') for tr in tr_list: title = tr.xpath('./td[2]/a[2]/text()').extract_first() status = tr.xpath('./td[3]/span/text()').extract_first() item = SunshineproItem() item['title'] = title item['status'] = status yield item
pipelines.py中瀏覽器
class SunshineproPipeline(object): def process_item(self, item, spider): if item.__class__.__name__ == 'SunshineproItem': print(item['title'], item['status']) else: print(item['content']) return item
記得要在settings.py中打開管道dom
spider和selenium一塊兒使用scrapy
實例代碼:ide
爬蟲文件代碼.pyui
import scrapy from selenium import webdriver class WangyiSpider(scrapy.Spider): name = 'wangyi' # allowed_domains = ['www.xxx.com'] start_urls = ['https://news.163.com/world/'] #實例化一個瀏覽器對象 bro = webdriver.Chrome(executable_path=r'C:\Users\old-boy\Desktop\爬蟲\day05爬蟲\chromedriver.exe') def parse(self, response): div_list = response.xpath('/html/body/div/div[3]/div[4]/div[1]/div/div/ul/li/div/div') for div in div_list: title = div.xpath('.//div[@class="news_title"]//a/text()').extract_first() detail_url = div.xpath('.//div[@class="news_title"]//a/@href').extract_first() yield scrapy.Request(detail_url,self.parse_detail) print(title,detail_url) def parse_detail(self,response): content = response.xpath('//*[@id="endText"]//text()').extract() content = ''.join(content) print(content) def closed(self,spider): self.bro.quit()
middlewares.py中url
class WangyiproDownloaderMiddleware(object): #spider表示的就是爬蟲類實例化的對象 def process_response(self, request, response, spider): #將不符合需求的響應對象修改爲符合需求的 #body:響應數據 #如何獲取爬蟲類中生成的瀏覽器對象呢? if request.url == 'https://news.163.com/world/': bro = spider.bro bro.get('https://news.163.com/world/') sleep(2) #滾動條滾動到最底部 bro.excute_script('window.scrollTo(0,document.body.scrollHeight)') sleep(1) bro.excute_script('window.scrollTo(0,document.body.scrollHeight)') sleep(1) bro.excute_script('window.scrollTo(0,document.body.scrollHeight)') sleep(1) page_text = bro.page_source new_response = HtmlResponse(url=bro.current_url,body=page_text,encoding='utf-8',request=request) return new_response else: return response #必定要返回原始數據,不然只能獲取到一部份內容
在settings.py中咱們要配置如下參數:
#下載器和引擎之間的中間件
DOWNLOADER_MIDDLEWARES = { 'wangyiPro.middlewares.WangyiproDownloaderMiddleware': 543, }