关于任务思考:
1.确定爬虫入口:
start_urls = [
'http://ggglxy.scu.edu.cn/index.php?c=article&a=type&tid=18&page_1_page=1',
]
确定爬虫入口应该是编写爬虫的第一步,但是很不幸,我在第一步就走偏了
,从公共管理学院首页进到师资队伍页面获得的网址是
但是从这个网址我无法获得下一页的绝对链接,在执行爬虫的过程中,我就遇上了URLERROR的错误。
- 爬取思路:
从这张图,可以看出,我们可以在目录页抓取教师姓名、教师职位、教师所属专业、教师邮箱,因此我们只需要在详情页获取教师的简介就可以了。
从网站的目录页中,每页有八项数据,我需要拿到每一项的数据的链接,同时还需要拿到「下一页」的链接。因为下一页的结构和第一页的结构相同,所以我将下一页的连接传给pasre处理,而每一项数据的链接交给pasre_content处理。
- 代码实现:
3.1 items.py文件:
class TeacherItem(scrapy.Item)
name = scrapy.Field() #教师姓名
position = scrapy.Field() #教师职位
intro = scrapy.Field() #教师
email = scrapy .Field() #教师邮箱
major = scrapy.Field()#教师所属专业
pass
3.2 spider代码:
处理目录页的教师信息的代码:
def parse(self,response):
for quote in response.css('ul.teachers_ul.mt20.cf li.fl'):
item = TeacherItem()
item['name'] = quote.css('div.r.fr h3.mb10::text').extract_first()#教师名字
item['position'] = quote.css('div.r.fr p.color_main.f14::text').extract_first()#教师职位
item['major'] = quote.css('div.r.fr div.desc p::text').extract_first()#教师所属专业
item['email'] = response.xpath('//div[@class="r fr"]/div[@class="desc"]/p[last()]/text()').extract()#教师邮箱
url = response.urljoin(quote.css('div.l.fl a::attr("href")').extract_first())#教师详情页链接
request=scrapy.http.Request(url,callback=self.parse_content)#将获取的信息传给详情页处理器
request.meta['item']=item
yield request
处理下一页的链接的代码:
next_page = response.xpath('//div[@class="pager cf tc pt10 pb10 mobile_dn"]/li[last()-1]/a/@href').extract_first() #获取下一页的链接
if next_page is not None:
next_full_url = response.urljoin(next_page)
yield scrapy.Request(next_full_url, callback=self.parse) #判断是有有下一页,有的话,就将url传给自身
处理每一项数据链接的代码:
def parse_content(self,response):
for site in response.css('div.js_infobox.cf'):
item = response.meta['item']#接收meta传递过来的数据,即姓名、邮箱、职位等信息
item['intro']= site.css('div.r.fr div.desc::text').extract_first()
yield item
在编写这个代码的过程中,我认为元素的定位是最难的,路径不对数据就爬不出。
3.3 执行爬虫
同样使用scrapy crawl quotes
命令来执行爬虫,爬取之后下载文件,打开:
由于文件默认的是unicode编码格式,所以我爬取到的数据是一堆我看不懂数据。我首先尝试了同学使用过并可行的
scrapy crawl quotes -o teacher.json -s FEED_EXPORT_ENCODING=utf-8
命令,结果生成的还是unicode编码格式的文件。
3.4 处理unicode编码问题
通过网上查找,我运用了下面的方法解决问题:
修改pipelines.py文件:
import json
import codecs
class QuotesPipeline(object):
def __init__(self):
self.file =codecs.open('teacher.json','wb',encoding='utf-8')
def process_item(self, item, spider):
line=json.dumps(dict(item))+'\n'
self.file.write(line.decode("unicode_escape"))
return item
在pipelines.py这个文件中,通过编写QuotesPipeline来实现对item的处理。它主要完成数据的查重、丢弃,验证item中的数据,将得到的item数据保存等工作。其中 process_item方法将得到的item实现解码,以便正常显示中文,最终保存到json文件中。
在编写完pipelines.py后,为了启动它,必须将其加入到ITEM_PIPELINES配置中:
ITEM_PIPELINES = {
'quotes.pipelines.QuotesPipeline':300
}
修改完这些文件后,我再次执行spiders,将得到的结果保存并下载:
这次,数据显示正常,共抓取到了128位老师的信息,其中包括了教师的姓名、职位、所属专业、邮箱与简介。