scrapy遞迴解析和post請求
阿新 • • 發佈:2019-01-14
遞迴解析
遞迴爬取解析多頁頁面資料
每一個頁面對應一個url,則scrapy工程需要對每一個頁碼對應的url依次發起請求,然後通過對應的解析方法進行作者和段子內容的解析。
實現方案:
1.將每一個頁碼對應的url存放到爬蟲檔案的起始url列表(start_urls)中。(不推薦)
2.使用Request方法手動發起請求。(推薦)
import scrapy from choutiPro.items import ChoutiproItem class ChoutiSpider(scrapy.Spider): name= 'chouti' # allowed_domains = ['www.xxx.com'] # 通用url的封裝 url = 'https://dig.chouti.com/r/scoff/hot/%d' pageNum = 1 start_urls = ['https://dig.chouti.com/r/scoff/hot/1'] def parse(self, response): div_list = response.xpath('//div[@id="content-list"]/div') for div indiv_list: title = div.xpath('./div[3]/div[1]/a/text()').extract_first() author = div.xpath('./div[3]/div[2]/a[4]/b/text()').extract_first() # item = ChoutiproItem() item['title'] = title item['author'] = author yield itemif self.pageNum < 5: # 頁碼的一個範圍 # 封裝集成了一個新的頁碼的url self.pageNum += 1 new_url = format(self.url % self.pageNum) # 手動的請求傳送:callback表示的指定的解析方法 yield scrapy.Request(url=new_url, callback=self.parse) # 在scrapy框架中yield的使用場景: # 1.yield item:向管道提交item # 2.yield scrapy.Request():進行手動請求傳送
items
import scrapy class ChoutiproItem(scrapy.Item): # define the fields for your item here like: # name = scrapy.Field() title = scrapy.Field() author = scrapy.Field()
pipelines
class ChoutiproPipeline(object): def process_item(self, item, spider): print(f"{item['title']}:{item['author']}") # 持久化儲存,測試沒寫 return item
settings
BOT_NAME = 'choutiPro' # 使用UA USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36' SPIDER_MODULES = ['choutiPro.spiders'] NEWSPIDER_MODULE = 'choutiPro.spiders' # Crawl responsibly by identifying yourself (and your website) on the user-agent # 關閉root協議 ROBOTSTXT_OBEY = False # 開啟管道 ITEM_PIPELINES = { 'choutiPro.pipelines.ChoutiproPipeline': 300, }
五大核心元件工作流程
- 引擎(Scrapy)
用來處理整個系統的資料流處理, 觸發事務(框架核心) - 排程器(Scheduler)
用來接受引擎發過來的請求, 壓入佇列中, 並在引擎再次請求的時候返回. 可以想像成一個URL(抓取網頁的網址或者說是連結)的優先佇列, 由它來決定下一個要抓取的網址是什麼, 同時去除重複的網址 - 下載器(Downloader)
用於下載網頁內容, 並將網頁內容返回給蜘蛛(Scrapy下載器是建立在twisted這個高效的非同步模型上的) - 爬蟲(Spiders)
爬蟲是主要幹活的, 用於從特定的網頁中提取自己需要的資訊, 即所謂的實體(Item)。使用者也可以從中提取出連結,讓Scrapy繼續抓取下一個頁面 - 專案管道(Pipeline)
負責處理爬蟲從網頁中抽取的實體,主要的功能是持久化實體、驗證實體的有效性、清除不需要的資訊。當頁面被爬蟲解析後,將被髮送到專案管道,並經過幾個特定的次序處理資料。
下圖是一個請求再返回來的流程
紅色是傳送請求
藍色是返回的流程
post請求
其實是因為爬蟲檔案中的爬蟲類繼承到了Spider父類中的start_requests(self)這個方法,該方法就可以對start_urls列表中的url發起請求:
# 原始作用:將起始url料表中url進行GET請求 # def start_requests(self): # 模擬get請求的簡化流程 # for url in self.start_urls: # yield scrapy.Request(url=url,callback=self.parse)
實現post請求其實就是重寫父類的start_requests
# 重寫 父類的 start_requests,讓其進行POST請求 def start_requests(self): data = { 'kw': 'dog' } for url in self.start_urls: # scrapy.FormRequest:指 POST 請求 # callback=self.parse 指回調函式 # formdata=data 指post請求傳送的資料 yield scrapy.FormRequest(url=url, callback=self.parse, formdata=data)
列如百度翻譯我就可以這樣傳送post請求
# -*- coding: utf-8 -*- import scrapy class PostSpider(scrapy.Spider): name = 'post' allowed_domains = ['www.xxx.com'] start_urls = ['https://fanyi.baidu.com/sug'] # 原始作用:將起始url料表中url進行GET請求 # def start_requests(self): # 模擬get請求的簡化流程 # for url in self.start_urls: # yield scrapy.Request(url=url,callback=self.parse) # 重寫 父類的 start_requests,讓其進行POST請求 def start_requests(self): data = { 'kw': 'dog' } for url in self.start_urls: # scrapy.FormRequest:指 POST 請求 # callback=self.parse 指回調函式 # formdata=data 指post請求傳送的資料 yield scrapy.FormRequest(url=url, callback=self.parse, formdata=data) def parse(self, response): # print(response.bady) print(response.text)baidu—post
訪問人人個人首頁
# -*- coding: utf-8 -*- import scrapy class LoginSpider(scrapy.Spider): name = 'login' # allowed_domains = ['www.xxx.com'] start_urls = ['http://www.renren.com/ajaxLogin/login?1=1&uniqueTimestamp=201873958471'] def start_requests(self): formdata = { 'email': '17701256561', 'icode': '', 'origURL': 'http://www.renren.com/home', 'domain': 'renren.com', 'key_id': '1', 'captcha_type': 'web_login', 'password': '7b456e6c3eb6615b2e122a2942ef3845da1f91e3de075179079a3b84952508e4', 'rkey': '44fd96c219c593f3c9612360c80310a3', 'f': 'https%3A%2F%2Fwww.baidu.com%2Flink%3Furl%3Dm7m_NSUp5Ri_ZrK5eNIpn_dMs48UAcvT-N_kmysWgYW%26wd%3D%26eqid%3Dba95daf5000065ce000000035b120219', } for url in self.start_urls: yield scrapy.FormRequest(url=url, formdata=formdata, callback=self.parse) def parse(self, response): url = 'http://www.renren.com/960481378/profile' yield scrapy.Request(url=url, callback=self.personalPage) def personalPage(self, response): page_text = response.text print(response)人人個人首頁