一莺奔、采集前的準(zhǔn)備
首先進(jìn)入四川大學(xué)公共管理學(xué)院官網(wǎng)欣范,查看其師資隊(duì)伍師資隊(duì)伍板塊對(duì)教師信息的陳列方式。未來(lái)采集將從這里開(kāi)始令哟。
從網(wǎng)站陳列的方式可以看到:
教師分為三類(lèi):全職教師恼琼、客座教師、退休教師屏富、博士后流動(dòng)站晴竞。
通過(guò)點(diǎn)擊每個(gè)版塊的教師查看具體信息,每個(gè)老師的信息包括(教師的圖片包含進(jìn)入具體頁(yè)的鏈接):
姓名狠半、職稱(chēng)噩死、專(zhuān)業(yè)、郵箱神年。
姓名已维、職稱(chēng)、簡(jiǎn)短簡(jiǎn)歷已日、代表性研究成果衣摩、獲獎(jiǎng)情況、科研項(xiàng)目捂敌、人才培養(yǎng)
從師資隊(duì)伍開(kāi)始采集全職教師的姓名艾扮、職稱(chēng)、專(zhuān)業(yè)占婉、郵箱泡嘴、圖片,并進(jìn)行翻頁(yè)逆济。對(duì)每個(gè)老師而言酌予,進(jìn)入詳細(xì)頁(yè)面繼續(xù)采集簡(jiǎn)短簡(jiǎn)歷磺箕、代表性研究成果、獲獎(jiǎng)情況抛虫、科研項(xiàng)目松靡、人才培養(yǎng)的內(nèi)容。
對(duì)于部分教師建椰,其信息沒(méi)有上傳到官網(wǎng).應(yīng)考慮沒(méi)有信息的默認(rèn)采集格式雕欺。
二、開(kāi)始采集
在這一次才采集過(guò)程棉姐,依然按照scrapy教程的步驟進(jìn)行采集實(shí)踐屠列。
首先建立這一次的采集項(xiàng)目,項(xiàng)目名稱(chēng)是jsinfo(教師信息):
可以看到在jsinfo項(xiàng)目之下的內(nèi)容目錄呈以下結(jié)構(gòu):
在正式采集之前伞矩,現(xiàn)在items.py這個(gè)文件中定義即將采集的字段(實(shí)際上定義了之后笛洛,感覺(jué)太難也沒(méi)用)。
在spiders下建立jsinfo_spider.py文件乃坤,開(kāi)始寫(xiě)第一個(gè)爬蟲(chóng)(這部分并沒(méi)有什么意義苛让。。湿诊。)狱杰。
import scrapy
class JsInfoSpider(scrapy.Spider):
name = "infos"
def start_requests(self):
urls = [
'http://ggglxy.scu.edu.cn/index.php?c=article&a=type&tid=18'
]
for url in urls:
yield scrapy.Request(url=url, callback=self.parse)
def parse(self, response):
page = response.url.split("/")[-2]
filename = 'infos-%s.html' % page
with open(filename, 'wb') as f:
f.write(response.body)
self.log('Saved file %s' % filename)
然后執(zhí)行infos爬蟲(chóng),可以得到師資隊(duì)伍的html文件枫吧。
root@iZwz9bmo44a33isf69hxp5Z:~/venv/jsinfo# scrapy crawl infos
接著提取師資隊(duì)伍頁(yè)面的部分內(nèi)容九杂,如下:
這時(shí)我想繼續(xù)提取教師的專(zhuān)業(yè)以及他們各自的郵箱,這時(shí)發(fā)現(xiàn)專(zhuān)業(yè)與郵箱都相同標(biāo)簽下的文本內(nèi)容甥捺,如何在同一標(biāo)簽下分條目抓取內(nèi)容我未遇到過(guò)。考慮通過(guò)定位p[0],p[1]將同一標(biāo)簽下的字段截?cái)嘀茫囘^(guò)之后結(jié)果是第一個(gè)字段沒(méi)有數(shù)據(jù),而第二個(gè)字段的數(shù)據(jù)都采集下來(lái)的數(shù)據(jù)是原本第一個(gè)字段的數(shù)據(jù)。
于是推測(cè)疏旨,在這里,數(shù)據(jù)字段是從“1”開(kāi)始的。修改代碼之后帝蒿,可以得到正確的結(jié)果绣张。
'jsmajor': info.xpath("http://div[@class='desc']/p[1]/text()").extract_first(),
'jsmail': info.xpath("http://div[@class='desc']/p[2]/text()").extract_first()
在解決這個(gè)問(wèn)題之前,我是將專(zhuān)業(yè)和郵箱采集到一起。當(dāng)然還是分開(kāi)采集更加顯著了招狸。
這時(shí)爬蟲(chóng)infos的代碼如下:
start_urls = [
'http://ggglxy.scu.edu.cn/index.php?c=article&a=type&tid=18&page_1_page=1'
]
def parse(self, response):
for info in response.xpath("http://div[@class='r fr']"):
yield {
'jsname': info.xpath("http://h3[@class='mb10']/text()").extract_first(),
'jstitle': info.xpath("http://p[@class='color_main f14']/text()").extract_first(),
'jsmajormail': info.xpath("http://div[@class='desc']/p/text()").extract(),
}
第一頁(yè)的采集下來(lái)了,接下來(lái)沒(méi)有去采集子頁(yè)面的內(nèi)容,打算先實(shí)現(xiàn)翻頁(yè)功能。于是,先嘗試用指導(dǎo)文檔中的翻頁(yè)設(shè)置:
next_page = response.xpath("http://li[@href]/@href").extract_first()
if next_page is not None:
next_page = response.urljoin(next_page)
yield scrapy.Request(next_page, callback=self.parse)
結(jié)果翻頁(yè)是不成功的试溯,或者出現(xiàn)將首頁(yè)重復(fù)兩次的情況试读。多次試驗(yàn)比藻,依然失敗。于是考慮到公共管理學(xué)院師資隊(duì)伍就16頁(yè)倘屹,或許可以以循環(huán)的方式將url全部寫(xiě)出來(lái)纽匙。然后照著其他資料提示,改了spider內(nèi)容喷舀。
start_urls = []
def start_requests(self):
i = 1
while i <= 16:
url = "http://ggglxy.scu.edu.cn/index.php?c=article&a=type&tid=18&page_1_page=%d" % i
yield self.make_requests_from_url(url)
i += 1
然后運(yùn)行爬蟲(chóng)‘infosone’杠河,可以發(fā)現(xiàn)已經(jīng)成功實(shí)現(xiàn)了翻頁(yè)。結(jié)果發(fā)現(xiàn)將每個(gè)頁(yè)面重復(fù)爬取多次(貌似重復(fù)8次赶掖,也是不懂為什么了)。后面嘗試修改代碼以避免重復(fù)頁(yè)面抓取颈走,但是始終修改不對(duì)膳灶。
于是我就先把這個(gè)問(wèn)題放到一邊。然后先去采集詳情頁(yè)的內(nèi)容立由,預(yù)想直接加入基本頁(yè)代碼之中轧钓,看能不能連接到一起。并且沒(méi)有加入翻頁(yè)的結(jié)構(gòu)锐膜,只是在第一頁(yè)進(jìn)行試驗(yàn)毕箍。
import scrapy
class JsInfoSpider(scrapy.Spider):
name = "infostwo"
start_urls = [
'http://ggglxy.scu.edu.cn/index.php?c=article&a=type&tid=18'
]
def parse(self, response):
for info in response.xpath('//li[@class="f1"]'):
yield {
'jsname': info.xpath("http://h3[@class='mb10']/text()").extract_first(),
'jstitle': info.xpath("http://p[@class='color_main f14']/text()").extract_first(),
'jsmajor': info.xpath("http://div[@class='desc']/p[1]/text()").extract_first(),
'jsmail': info.xpath("http://div[@class='desc']/p[2]/text()").extract_first()
}
for href in response.xpath('//li[@class="f1"]/div[@class="1 f1"]/a/@href').extract():
yield scrapy.Request(response.urljoin(href),
callback=self.parse_txxinfo)
@staticmethod
def parse_txxinfo(self, response):
for intro in response.xpath('//div[@class="r fr"]'):
yield {
'jsname': intro.xpath('h3/text()').extract_first(),
'jsresume': intro.xpath('div[@class="desc"]/text()').extract_first(),
}
然而結(jié)果不是想象那樣,我就覺(jué)得是我邏輯出了錯(cuò)道盏,于是問(wèn)了其他同學(xué)而柑,發(fā)現(xiàn)邏輯差不多。難道是代碼錯(cuò)了荷逞,比對(duì)了一下媒咳,大體機(jī)構(gòu)相似。后來(lái)甚至改成相同的种远,結(jié)果人家的能出來(lái)詳情頁(yè)結(jié)果涩澡,然而我的就是出來(lái)不了。不行坠敷。妙同。射富。
然后我就單獨(dú)寫(xiě)了一個(gè)爬蟲(chóng)去爬取詳情頁(yè)內(nèi)容。因?yàn)樯厦娴难h(huán)url不能 使用粥帚,依然采取了教程中的“下一頁(yè)”方式辉浦。
分頁(yè)的代碼:
import scrapy
class JsInfoSpider(scrapy.Spider):
name = 'infosthree'
start_urls = ['http://ggglxy.scu.edu.cn/index.php?c=article&a=type&tid=18'
]
def parse(self, response):
# follow links to author pages
for href in response.xpath('//li[@class="f1"]/div[@class="1 f1"]/a/@href').extract():
yield scrapy.Request(response.urljoin(href),
callback=self.parse)
# follow pagination links
next_page = response.xpath('//div[@class="pager cf tc pt10 pb10 mobile_dn"]/li/a/@href').extract_first()
if next_page is not None:
next_page = response.urljoin(next_page)
yield scrapy.Request(next_page, callback=self.parse_moreinfos)
def parse_moreinfos(self, response):
def extract_with_xpath(query):
return response.xpath(query).extract_first ().strip ()
yield {
'jsname': extract_with_xpath('//div[@class="r fr"]/h3/text()'),
'jsresume': extract_with_xpath('//div[@class="r fr"]/div[@class="desc"]/text()'),
}
不分頁(yè)的代碼:
import scrapy
class JsInfoSpider(scrapy.Spider):
name = 'infosthree'
start_urls = ['http://ggglxy.scu.edu.cn/index.php?c=article&a=type&tid=18']
def parse(self, response):
# follow links to author pages
for href in response.xpath('//div[@class="1 f1"]/a/@href'):
yield response.follow(href, self.parse_infosthree)
@staticmethod
def parse_infosthree(response):
def extract_with_xpath(query):
return response.xpath(query).extract_first().strip()
yield {
'jssrc': extract_with_xpath('//div[@class="1 f1"]/img/src'),
'jsname': extract_with_xpath('//div[@class="r fr"]/h3/text()'),
'jsresume': extract_with_xpath('//div[@class="r fr"]/div[@class="desc"]/text()'),
}
結(jié)果依然不行啊。于是決定只是爬取第一頁(yè)的詳情頁(yè)內(nèi)容看看茎辐,這時(shí)發(fā)現(xiàn)反復(fù)報(bào)的是同樣的錯(cuò)宪郊。