在前面兩篇(爬蟲學習之基於Scrapy的網絡爬蟲和爬蟲學習之簡單的網絡爬蟲)文章中咱們經過兩個實際的案例,採用不一樣的方式進行了內容提取。咱們對網絡爬蟲有了一個比較初級的認識,只要發起請求獲取響應的網頁內容,而後對內容進行格式化存儲。不少時候咱們抓取到的內容可能會發生重複,也有多是須要計算或者組織過的全新的內容甚至是須要登陸後才能訪問的內容, 那麼這一篇咱們來學習一下Scrapy的Item部分以及瞭解如何使用Scrapy來進行自動登陸。html
首先咱們使用Scrapy的命令行建立一個新的項目git
scrapy startproject douban
運行後,咱們就有了下面這樣的目錄結構github
+ douban # 根目錄 |- douban # Python的項目目錄 |- spiders # 爬蟲Spider部分,用於提取網頁內容 |- __init__.py |- __init__.py |- items.py # 爬蟲item, 用於定義數據結構 |- pipelines.py # 爬蟲pipeline,用於處理提取的結構,好比清洗數據、去重等 |- settings.py # Scrapy框架參數項目參數設置 |- scrapy.cfg # 爬蟲部署相關設置
Scrapy爲咱們生成了已經組織好的目錄結構,上面的註釋部分解釋了每一個文件及目錄的做用。瀏覽器
本篇咱們來創建兩個目標,這兩個目標都是基於豆瓣網:服務器
目標一:抓取豆瓣TOP250的圖書信息並保存成csv文件cookie
目標二:抓取個人第一頁豆郵標題(須要登陸),並保存成csv文件網絡
目標一是豆瓣的TOP250圖書信息,首先咱們進入到TOP250的列表(https://book.douban.com/top250) ,我用圖示圈出咱們此次要爬取的內容,具體請看圖示:session
從圖上的框線中咱們主要圈出了書名、價格、出版年份、出版社、評分,其中出版年份,出版社以及價格是在一行中,這個咱們須要進一步處理。數據結構
分頁的處理:總記錄是250條,每頁是25條圖書信息,共分了10頁。app
須要用到的概念:
Item
Item Pipeline
首先創建Scrapy的Item, Scrapy的Item就是咱們須要存儲的數據結構,先修改items, 而後在spiders目錄中新建一個名爲bookspider.py的Python文件,因爲咱們須要在一堆字符串中提取出出版社和價格等信息因此咱們這裏須要對抓取的內容進一步處理, 在這以前還須要修改settings.py文件:
加入faker的模擬USER_AGENT數據防止被豆瓣屏蔽,
也能夠設置DEFAULT_REQUEST_HEADERS參數。
修改ITEM_PIPELINES
代碼以下所示:
items.py
# -*- coding: utf-8 -*- '''by sudo rm -rf http://imchenkun.com''' import scrapy class DoubanBookItem(scrapy.Item): name = scrapy.Field() # 書名 price = scrapy.Field() # 價格 edition_year = scrapy.Field() # 出版年份 publisher = scrapy.Field() # 出版社 ratings = scrapy.Field() # 評分
bookspider.py
# -*- coding:utf-8 -*- '''by sudo rm -rf http://imchenkun.com''' import scrapy from douban.items import DoubanBookItem class BookSpider(scrapy.Spider): name = 'douban-book' allowed_domains = ['douban.com'] start_urls = [ 'https://book.douban.com/top250' ] def parse(self, response): # 請求第一頁 yield scrapy.Request(response.url, callback=self.parse_next) # 請求其它頁 for page in response.xpath('//div[@class="paginator"]/a'): link = page.xpath('@href').extract()[0] yield scrapy.Request(link, callback=self.parse_next) def parse_next(self, response): for item in response.xpath('//tr[@class="item"]'): book = DoubanBookItem() book['name'] = item.xpath('td[2]/div[1]/a/@title').extract()[0] book['price'] = item.xpath('td[2]/p/text()').extract()[0] book['ratings'] = item.xpath('td[2]/div[2]/span[2]/text()').extract()[0] yield book
pipelines.py
# -*- coding: utf-8 -*- '''by sudo rm -rf http://imchenkun.com''' class DoubanBookPipeline(object): def process_item(self, item, spider): info = item['price'].split(' / ') # [法] 聖埃克蘇佩裏 / 馬振聘 / 人民文學出版社 / 2003-8 / 22.00元 item['name'] = item['name'] item['price'] = info[-1] item['edition_year'] = info[-2] item['publisher'] = info[-3] return item
最後咱們到douban的根目錄中執行如下命令來運行爬蟲來執行並導出數據到csv文件
scrapy crawl douban-book -o douban_book_top250.csv
csv文件截圖以下:
目標二是創建在理解了目標一的基礎上進行的,由於豆瓣登陸次數過多會有驗證碼出現,這裏提供一種手工填寫驗證碼的方式,暫時不討論如何去識別驗證碼,目標二的核心概念是如何提交POST表單和登陸成功後帶Cookie的請求。首先咱們能夠看到頁面結構以下圖所示:
定義Item
# -*- coding: utf-8 -*-import scrapy '''by sudo rm -rf http://imchenkun.com''' class DoubanMailItem(scrapy.Item): sender_time = scrapy.Field() # 發送時間 sender_from = scrapy.Field() # 發送人 url = scrapy.Field() # 豆郵詳細地址 title = scrapy.Field() # 豆郵標題
定義doumailspider
# -*- coding:utf-8 -*- '''by sudo rm -rf http://imchenkun.com''' import scrapy from faker import Factory from douban.items import DoubanMailItem import urlparse f = Factory.create() class MailSpider(scrapy.Spider): name = 'douban-mail' allowed_domains = ['accounts.douban.com', 'douban.com'] start_urls = [ 'https://www.douban.com/' ] headers = { 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Accept-Encoding': 'gzip, deflate, br', 'Accept-Language': 'zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3', 'Connection': 'keep-alive', 'Host': 'accounts.douban.com', 'User-Agent': f.user_agent() } formdata = { 'form_email': '您的帳號', 'form_password': '您的密碼', # 'captcha-solution': '', # 'captcha-id': '', 'login': '登陸', 'redir': 'https://www.douban.com/', 'source': 'None' } def start_requests(self): return [scrapy.Request(url='https://www.douban.com/accounts/login', headers=self.headers, meta={'cookiejar': 1}, callback=self.parse_login)] def parse_login(self, response): # 若是有驗證碼要人爲處理 if 'captcha_image' in response.body: print 'Copy the link:' link = response.xpath('//img[@class="captcha_image"]/@src').extract()[0] print link captcha_solution = raw_input('captcha-solution:') captcha_id = urlparse.parse_qs(urlparse.urlparse(link).query, True)['id'] self.formdata['captcha-solution'] = captcha_solution self.formdata['captcha-id'] = captcha_id return [scrapy.FormRequest.from_response(response, formdata=self.formdata, headers=self.headers, meta={'cookiejar': response.meta['cookiejar']}, callback=self.after_login )] def after_login(self, response): print response.status self.headers['Host'] = "www.douban.com" return scrapy.Request(url='https://www.douban.com/doumail/', meta={'cookiejar': response.meta['cookiejar']}, headers=self.headers, callback=self.parse_mail) def parse_mail(self, response): print response.status for item in response.xpath('//div[@class="doumail-list"]/ul/li'): mail = DoubanMailItem() mail['sender_time'] = item.xpath('div[2]/div/span[1]/text()').extract()[0] mail['sender_from'] = item.xpath('div[2]/div/span[2]/text()').extract()[0] mail['url'] = item.xpath('div[2]/p/a/@href').extract()[0] mail['title'] = item.xpath('div[2]/p/a/text()').extract()[0] print mail yield mail
這裏須要注意的有三個地方:
第一個是meta中的cookiejar
Scrapy 經過使用 cookiejar Request meta key來支持單spider追蹤多cookie session。默認狀況下其使用一個cookie jar(session),不過您能夠傳遞一個標示符來使用多個。
start_requests 咱們這裏重寫了爬蟲爬取得第一個頁面,這裏一開始就進去到登陸頁面
當執行爬蟲的時候,咱們須要把打印出來的驗證碼地址粘貼到瀏覽器中,手動輸入到控制上完成驗證。
同目標一同樣須要設置settings中的相關參數,惟一不一樣的是ITEM_PIPELINES。
最後咱們使用如下命令來啓動爬蟲
scrapy crawl douban-mail -o douban_mail_page1.csv
csv文件截圖以下:
Github地址:https://github.com/imchenkun/ick-spider/tree/master/douban
本篇咱們學習了若是定義Item以及如何對Item進行進一步處理(Item Pipeline), 還經過登陸豆瓣的案例來了解了若是使用Scrapy進行表單提交和Cookie追蹤,也瞭解了對於有驗證碼的狀況該如何處理,固然咱們這裏暫時還不討論如何識別驗證碼。關於Scrapy的更高級的一些用法和特性能夠進一步閱讀Scrapy官網的文檔。
特別申明:本文所提到的豆瓣網只是拿來進行爬蟲的技術交流學習,讀者涉及到的全部侵權問題都與本人無關,也但願你們在學習實戰的過程當中不要大量的爬取內容對服務器形成負擔
本文首發在sudo rm -rf 採用署名(BY)-非商業性使用(NC)-禁止演繹(ND) 轉載請註明原做者
--EOF--