利用爬虫框架Scrapy来爬取学校阳光长跑个人信息与长跑信息,并储存在MongoDB中。
具体步骤:
以下简述具体的爬取逻辑与代码,该项目源代码。
学习scrapy最好的方式为看官方文档,详见。
创建Scrapy项目。
scrapy startproject sunny_sport
创建爬虫。
123# 该命令样式# scrapy genspider mydomain mydomain.comscrapy genspider sunnysport hzaspt.sunnysport.org.cn配置该项目相关配置。
12345678910111213141516171819202122# sunny_sport/sunny_sport/settings.py# 以下为添加的配置# 不遵循 robots.txt 的规则ROBOTSTXT_OBEY = False# 开启 cookies 的 debugCOOKIES_DEBUG = True# 设置请求头信息DEFAULT_REQUEST_HEADERS = {'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8','Accept-Language': 'zh-CN,zh;q=0.8,en;q=0.6','User-Agent': 'Mozilla/5.0 (Macintosh;'' Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko)'' Chrome/57.0.2987.133 Safari/537.36'}# 激活 MongoDB 的 pipelineITEM_PIPELINES = {'sunny_sport.pipelines.MongoPipeline': 300,}编写爬取的个人信息Item与长跑信息Item。
12345678910111213141516171819202122232425262728293031323334353637# sunny_sport/sunny_sport/items.py# -*- coding: utf-8 -*-from scrapy import Item, Fieldclass StudentItem(Item):"""name 姓名student_num 学号total_mileage 总里程total_avg_speed 总平均速度valid_cnt 有效次数"""name = Field()student_num = Field()total_mileage = Field()total_avg_speed = Field()valid_cnt = Field()class SportItem(Item):"""cnt 长跑次数date 长跑日期time 长跑时段mileage 长跑里程avg_speed 长跑平均速度is_valid 长跑是否有效 (1有效 0无效)"""cnt = Field()date = Field()time = Field()mileage = Field()avg_speed = Field()is_valid = Field()编写爬虫逻辑代码。
需要注意的是,Scrapy框架会自动处理你的cookie,详见CookiesMiddleware。
只需要在请求的时候在
meta
添加cookiejar
即可。不过在该项目使用之后出现了302重定向,即未取得cookie值,目前尚未通晓什么原因,后续更新…
因此,在该项目中我先登录一遍页面获取了cookie值后直接添加请求中,略显笨拙。
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485# sunny_sport/sunny_sport/spiders/sunnysport.py# -*- coding: utf-8 -*-from scrapy.http import Request, FormRequestfrom scrapy.spiders import CrawlSpiderfrom sunny_sport.items import StudentItem, SportItemclass SunnysportSpider(CrawlSpider):name = "sunnysport"allowed_domains = ["hzaspt.sunnysport.org.cn"]start_url = 'http://hzaspt.sunnysport.org.cn/runner/index.html'def start_requests(self):"""模拟表单登录"""return [FormRequest(url='http://hzaspt.sunnysport.org.cn/login/',formdata={'username': '2015002507','password': '2015002507'},# meta={'cookiejar': 1},callback=self.after_login)]def after_login(self, response):"""登录后,爬取基本信息页面和长跑信息页面"""return [Request(url=self.start_url,# meta={'cookiejar': response.meta['cookiejar']},cookies={'sessionid': 'clyid4a5s1c81hpygz2a26iqovla78jz'},dont_filter=True,callback=self.parse_main_page)]def parse_main_page(self, response):"""解析个人信息页面"""name = response.xpath('//div[@class="col-md-3"][1]/div[1]/div[2]/label/text()').extract_first()student_num = response.xpath('//div[@class="col-md-3"][1]/div[1]/div[3]/label/text()').extract_first()total_mileage = response.xpath('//div[@class="col-md-3"][2]/div[1]/div[2]//tr[1]/td[2]/text()').extract_first()total_avg_speed = response.xpath('//div[@class="col-md-3"][2]/div[1]/div[2]//tr[2]/td[2]/text()').extract_first()valid_cnt = response.xpath('//div[@class="col-md-3"][2]/div[1]/div[2]//tr[3]/td[2]/text()').extract_first()yield StudentItem(name=name,student_num=student_num,total_mileage=total_mileage,total_avg_speed=total_avg_speed,valid_cnt=valid_cnt)yield Request(url='http://hzaspt.sunnysport.org.cn/runner/achievements.html',# meta={'cookiejar': response.meta['cookiejar']},cookies={'sessionid': 'clyid4a5s1c81hpygz2a26iqovla78jz'},callback=self.parse_sport_page)def parse_sport_page(self, response):"""解析长跑信息"""trs = response.xpath('//div[@class="col-md-8"]//tbody/tr')for tr in trs:cnt = tr.xpath('.//td[1]/text()').extract_first()date = tr.xpath('.//td[2]/text()').extract_first()time = tr.xpath('.//td[3]/text()').extract_first()mileage = tr.xpath('.//td[4]/text()').extract_first()avg_speed = tr.xpath('.//td[5]/text()').extract_first()is_valid = tr.xpath('.//td[6]/span[contains(@class,"glyphicon-ok")]').extract_first() and 1 or 0yield SportItem(cnt=cnt,date=date,time=time,mileage=mileage,avg_speed=avg_speed,is_valid=is_valid)将爬取的数据储存进MongoDB中。
pipeline就像管道一样,将你之前定义的Item输入具体目的地。
使用前要安装MongoDB与pymongo包。
如何在Mac下使用MongoDB,请参见我之前的博文。
1234567891011121314151617181920212223242526272829303132# sunny_sport/sunny_sport/pipelines.py# -*- coding: utf-8 -*-import pymongoclass MongoPipeline(object):collection_name = 'sunny_sport'def __init__(self, mongo_uri, mongo_db):self.mongo_uri = mongo_uriself.mongo_db = mongo_db@classmethoddef from_crawler(cls, crawler):return cls(mongo_uri=crawler.settings.get('MONGO_URI'),mongo_db=crawler.settings.get('MONGO_DATABASE', 'test'))def open_spider(self, spider):self.client = pymongo.MongoClient(self.mongo_uri)self.db = self.client[self.mongo_db]def close_spider(self, spider):self.client.close()def process_item(self, item, spider):self.db[self.collection_name].insert(dict(item))return item运行该项目。
在终端输入
scrapy crawl sunnysport
即可。