從零開始學習scrapy:一,使用scrapy模擬登錄並獲取頁面數據
前言
本次需要獲取數據的網址是 http://www.zimuzu.tv/today
這是登錄情況下訪問顯示的界面
我們的目標是獲取所有當天更新的美劇名字
假設
我們嘗試一下在沒有登錄情況下訪問這個頁面,會是一個什麼樣的情況
我們可以看到,“請登錄網站”的字樣。
這個我們可以作爲程序判斷是否需要運行模擬登錄流程的條件
過程
本過程是直接從新建了scrapy項目並在Pycharm上運行開始
第一步
定義數據實體
找到項目中的items.py文件
import scrapy
class MovieItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
name = scrapy.Field()
因爲我們這次簡單例子只是想獲取美劇的名字,所以只定義一個name就可以了
編寫爬蟲邏輯
import scrapy
from scrapy import log
from movie.items import MovieItem
class MeijuSpider(scrapy.Spider):
name = 'meiju'
allowed_domains = ['zimuzu.tv']
start_urls = ['http://www.zimuzu.tv/today']
header = {"User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36"} # 供登錄模擬使用
我們新建的MeijuSpider
只繼承了最普通的Spider
,但是由於我們有可能需要做登錄的操作,所以我們需要重載函數start_requests
def start_requests(self):
return [scrapy.FormRequest(
url='http://www.zimuzu.tv/today',
dont_filter=True,
meta={'cookiejar': 1},
callback=self.parse
)]
參數一個個來解析:
url
:就是本次需要訪問地址dont_filter
:是用於重複請求的,第一次請求發現需要登錄操作,在登錄操作完成後,要再一次訪問這個url,如果不添加這個,會出現以下錯誤:
2018-06-21 00:05:35 [scrapy.dupefilters] DEBUG: Filtered duplicate request: <GET http://www.zimuzu.tv/today> - no more duplicates will be shown (see DUPEFILTER_DEBUG to show all duplicates)
2018-06-21 00:05:35 [scrapy.core.engine] INFO: Closing spider (finished)
2018-06-21 00:05:35 [scrapy.statscollectors] INFO: Dumping Scrapy stats:
meta={'cookiejar': 1}
:這代表本次請求開啓cookiecallback
:設置本次訪問成功後的回調函數
首次回調
def parse(self, response):
log.msg(response.body.decode('utf-8'))
# 判斷有沒有登錄
if "請登錄" in response.body.decode('utf-8'):
log.msg("need to login")
log.msg("start login")
return self.login(response)
else:
log.msg(response.body.decode('utf-8'))
return self.getMovieList(response)
首先我們拿到response後需要把它轉換成utf-8的格式才能進行判斷
如果有請登錄
,就進入登錄流程,調用login
函數
def login(self,response):
fd = {'account':'xxxxxxx',#你的賬號
'password':'*******',#你的密碼
'remember':'1',
'url_back':'http%3A%2F%2Fwww.zimuzu.tv%2F'}
return [scrapy.FormRequest(
url='http://www.zimuzu.tv/User/Login/ajaxLogin',
formdata=fd,
meta={'cookiejar': response.meta['cookiejar']},
callback=self.afterLogin
)]
就是做登錄的請求,至於請求需要的字段,就是在瀏覽器抓取的
這次因爲帶有登錄信息,所以就一次表單請求
formdata
:請求的表單數據集
回調函數是afterLogin
def afterLogin(self,response):
cookie = response.headers.getlist('Set-Cookie')
print('cookie:',cookie)
url = 'http://www.zimuzu.tv/today'
return [scrapy.FormRequest(
url=url,
dont_filter=True,
meta={"cookiejar": True},
callback=self.parse
)]
這個的日誌我們可以看到打印出來的cookie信息:
cookie: [b’GINFO=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; Max-Age=0; path=/; domain=.zimuzu.tv’, b’GKEY=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; Max-Age=0; path=/; domain=.zimuzu.tv’, b’GINFO=uid%3D3548633%26nickname%3Dnickey0781%26group_id%3D1%26avatar_t%3Dhttp%3A%2F%2Ffiles.zmzjstu.com%2Fftp%2Favatar%2Ff_noavatar_t.gif%26main_group_id%3D0%26common_group_id%3D59; expires=Sun, 18-Jun-2028 15:40:04 GMT; Max-Age=315360000; path=/; domain=.zimuzu.tv’, b’GKEY=bb9df3e025695bfa45484ad26d7a3ac3; expires=Sun, 18-Jun-2028 15:40:04 GMT; Max-Age=315360000; path=/; domain=.zimuzu.tv; httponly’]
接下來就可以用回第一個回調函數parse
,這次因爲帶上了cookie信息,所以是可以獲得數據的,就會調用函數getMovieList
def getMovieList(self, response):
movies = response.xpath('//table[@class="d_r_t"][@day="06-17"]/tr')
for m in movies:
movieName = m.xpath('./td/a/text()').extract()
# print('move name size:',len(movieName))
print('move name:',movieName)
if (len(movieName) > 0):
item = MovieItem()
item['name'] = movieName[0]
yield item