使用scrapy爬取四川大學(xué)公共管理學(xué)院教師信息實(shí)驗(yàn)報(bào)告

在參考zl、lly以及各種教程的代碼后,完成了爬取教師名稱、職稱、專業(yè)、郵箱、圖片、簡(jiǎn)介、研究成果、獲獎(jiǎng)成果、科研項(xiàng)目和人才培養(yǎng)信息的實(shí)驗(yàn)。具體代碼可從我的github上面下載運(yùn)行。

一. 實(shí)驗(yàn)環(huán)境

windows 10
python2.7.15
IDE:Eclipse+PyDev
scrapy 1.5.0

二. 實(shí)驗(yàn)前需安裝的庫(kù)

scrapy, PIL
安裝指令

pip install scrapy
pip install pillow

scrapy在windows下需要成功運(yùn)行的話,還需要安裝pywin32

三. 需要掌握的知識(shí)

scrapy的基礎(chǔ)知識(shí)
xpath或者css的選擇器如何使用
如何使用瀏覽器查看指定網(wǎng)頁(yè)元素的標(biāo)簽元素

四. 爬取邏輯

  1. 通過(guò)初始鏈接,先循環(huán)抓取第一頁(yè)每一位老師的姓名、職稱、專業(yè)、郵箱、圖片鏈接、詳情頁(yè)信息。
  2. 詳情頁(yè)信息是在循環(huán)中,抓取到一位老師的詳情頁(yè)鏈接后,將鏈接插入爬取隊(duì)列,爬取完詳情頁(yè)老師的剩余信息后,保存這位老師的所有信息,然后再抓取下一位老師的信息。
  3. 然后抓取下一頁(yè)按鈕的鏈接,若有,重復(fù)以上循環(huán);沒(méi)有,則結(jié)束。


    爬取流程

五. 項(xiàng)目目錄

scrapy_learn/
    scrapy.cfg
    scrapy_learn/
        __init__.py
        filterTags.py  #網(wǎng)上找到的去除HTML標(biāo)簽的方法
        items.py  #定義爬取內(nèi)容
        pipelines.py  #圖片下載器
        settings.py    #項(xiàng)目設(shè)置文件
        spiders/
            __init__.py
            tutorSpider.py    #爬蟲(chóng)文件(編寫爬蟲(chóng)規(guī)則)

六. 關(guān)鍵代碼

  1. items.py
    定義要爬取的內(nèi)容

# -*- coding: utf-8 -*-

# Define here the models for your scraped items
#
# See documentation in:
# https://doc.scrapy.org/en/latest/topics/items.html

import scrapy


class TutorItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    name = scrapy.Field() #姓名
    position = scrapy.Field() #職稱
    major = scrapy.Field() #專業(yè)
    email = scrapy.Field() #郵箱
    description = scrapy.Field()  #簡(jiǎn)介
    researchResult = scrapy.Field() #代表性研究成果
    award = scrapy.Field() #獲獎(jiǎng)情況
    sciResearPro = scrapy.Field() #科研項(xiàng)目
    talentTrain = scrapy.Field() #人才培養(yǎng)
    image_urls = scrapy.Field() #圖片鏈接
    image = scrapy.Field() #圖片
    image_paths = scrapy.Field()
  1. TutorSpider.py
    編寫爬蟲(chóng)規(guī)則
# -*- coding:UTF-8 -*-
import scrapy
from scrapy_learn.items import TutorItem
from scrapy_learn.filterTags import filter_tags



class TutorSpider(scrapy.Spider):
    name = 'tutor'
    allowed_domains = ['ggglxy.scu.edu.cn']
    start_urls=['http://ggglxy.scu.edu.cn/index.php?c=article&a=type&tid=18']
    # 初始化item對(duì)象保存爬取的信息
    item = TutorItem()
    
    def parse(self,response):
        for tutor in response.xpath("http://li[@class='fl']"):
            # 爬取姓名,職稱,專業(yè),郵箱
            item = TutorItem()
            item['image_urls'] = {"http://ggglxy.scu.edu.cn"+tutor.xpath("div[@class='l fl']/a/img/@src").extract_first()}
            item['name'] = tutor.xpath("div[@class='r fr']/h3[@class='mb10']/text()").extract_first()
            item['position'] = tutor.xpath("div[@class='r fr']/p[@class='color_main f14']/text()").extract_first()
            item['major'] = tutor.xpath("div[@class='r fr']/div[@class='desc']/p[1]/text()").extract_first()
            item['email'] = tutor.xpath("div[@class='r fr']/div[@class='desc']/p[2]/text()").extract_first()
             
            # 獲取詳情頁(yè)的地址并傳送給單個(gè)頁(yè)面處理函數(shù)進(jìn)行處理 -> parse_details()
            href = tutor.xpath("div[@class='l fl']/a/@href").extract_first()
            url = response.urljoin(href)
            request = scrapy.Request(url,callback=self.parse_details)
            request.meta['item'] = item
            yield request

        ## 是否還有下一頁(yè),如果有的話,則繼續(xù)
        next_page=response.xpath("http://div[@class='pager cf tc pt10 pb10 mobile_dn']/li[last()-1]/a/@href").extract_first()
        if next_page is not None:
            next_pages = response.urljoin(next_page)
            ## 將 「下一頁(yè)」的鏈接傳遞給自身,并重新分析
            yield scrapy.Request(next_pages, callback = self.parse)

    # 編寫詳情頁(yè)爬取方法
    def parse_details(self, response):
        item = response.meta['item']
        item['description'] = response.xpath("http://div[@class='r fr']/div/text()").extract_first()
        item['researchResult'] = filter_tags(response.xpath("http://div[@class='right_info p20']/div[2]").extract_first())
        item['award'] = filter_tags(response.xpath("http://div[@class='right_info p20']/div[3]").extract_first())
        item['sciResearPro'] = filter_tags(response.xpath("http://div[@class='right_info p20']/div[4]").extract_first())
        item['talentTrain'] = filter_tags(response.xpath("http://div[@class='right_info p20']/div[5]").extract_first())
        yield item
  1. pipelines.py
    下載圖片
# -*- coding: utf-8 -*-

# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://doc.scrapy.org/en/latest/topics/item-pipeline.html



import scrapy
from scrapy.pipelines.images import ImagesPipeline
from scrapy.exceptions import DropItem

class ScrapyLearnPipeline(object):
    def process_item(self, item, spider):
        return item
 
class TutorImagesPipeline(ImagesPipeline):
    def get_media_requests(self, item, info):
        for image_url in item['image_urls']:
            yield scrapy.Request(image_url)
 
    def item_completed(self,results,item,info):
        image_paths = [x['path'] for ok,x in results if ok]
#         if not image_paths:
#             raise DropItem("Item contains no images")
        item['image_paths'] = image_paths
        return item
  1. filterTags.py
    去除HTML標(biāo)簽
# -*- coding: utf-8-*-  
import re  
##過(guò)濾HTML中的標(biāo)簽  
#將HTML中標(biāo)簽等信息去掉  
#@param htmlstr HTML字符串.  
def filter_tags(htmlstr):  
    #先過(guò)濾CDATA  
    re_cdata=re.compile('//<!CDATA\[[>]?//CDATA\[[>]?//\]>',re.I) #匹配CDATA  
    re_script=re.compile('<\s*script[^>]*>[^<]*<\s*/\s*script\s*>',re.I)#Script  
    re_style=re.compile('<\s*style[^>]*>[^<]*<\s*/\s*style\s*>',re.I)#style  
    re_br=re.compile('<br\s*?/?>')#處理?yè)Q行  
    re_h=re.compile('</?\w+[^>]*>')#HTML標(biāo)簽  
    re_comment=re.compile('<!--[^>]*-->')#HTML注釋  
    s=re_cdata.sub('',htmlstr)#去掉CDATA  
    s=re_script.sub('',s) #去掉SCRIPT  
    s=re_style.sub('',s)#去掉style  
    s=re_br.sub('\n',s)#將br轉(zhuǎn)換為換行  
    s=re_h.sub('',s) #去掉HTML 標(biāo)簽  
    s=re_comment.sub('',s)#去掉HTML注釋  
    #去掉多余的空行  
    blank_line=re.compile('\n+')  
    s=blank_line.sub('\n',s)  
    s=replaceCharEntity(s)#替換實(shí)體  
    return s  
  
##替換常用HTML字符實(shí)體.  
#使用正常的字符替換HTML中特殊的字符實(shí)體.  
#你可以添加新的實(shí)體字符到CHAR_ENTITIES中,處理更多HTML字符實(shí)體.  
#@param htmlstr HTML字符串.  
def replaceCharEntity(htmlstr):  
    CHAR_ENTITIES={'nbsp':' ','160':' ',  
                'lt':'<','60':'<',  
                'gt':'>','62':'>',  
                'amp':'&','38':'&',  
                'quot':'"''"','34':'"',}  
      
    re_charEntity=re.compile(r'&#?(?P<name>\w+);')  
    sz=re_charEntity.search(htmlstr)  
    while sz:  
        entity=sz.group()#entity全稱,如>  
        key=sz.group('name')#去除&;后entity,如>為gt  
        try:  
            htmlstr=re_charEntity.sub(CHAR_ENTITIES[key],htmlstr,1)  
            sz=re_charEntity.search(htmlstr)  
        except KeyError:  
            #以空串代替  
            htmlstr=re_charEntity.sub('',htmlstr,1)  
            sz=re_charEntity.search(htmlstr)  
    return htmlstr  
  
def repalce(s,re_exp,repl_string):  
    return re_exp.sub(repl_string,s)  

七. 項(xiàng)目設(shè)置

要輸出中文到文件中,需要在settings.py中加入

FEED_EXPORT_ENCODING = 'utf-8'

要爬取圖片到本地,需要在settings.py中加入

ITEM_PIPELINES = {
    'scrapy_learn.pipelines.TutorImagesPipeline': 1,
}
IMAGES_STORE = 'D:\MyWorkspace\PythonWorkspace\scrapy_learn\img' #圖片存儲(chǔ)目錄
# 30天的圖片失效期限
IMAGES_EXPIRES = 30

八. 遇到的問(wèn)題

  1. 爬取圖片的時(shí)候,沒(méi)有辦法爬取其他設(shè)置的item
    解決:
    爬取圖片,寫items.py文件的時(shí)候,一定要寫這三行
image_urls = scrapy.Field() #圖片鏈接
image = scrapy.Field() #圖片
image_paths = scrapy.Field() #圖片路徑
  1. 爬取圖片時(shí),只能爬取帶圖片的老師的信息
    解決:
    將TutorImagePipeline類中 item_completed函數(shù)中這兩行注釋掉:
#         if not image_paths:
#             raise DropItem("Item contains no images")

這兩行的意思是,這一整個(gè)item如果沒(méi)有圖片的話,則丟掉整個(gè)item。所以才會(huì)導(dǎo)致沒(méi)有圖片的老師信息爬取不到。

  1. 環(huán)境問(wèn)題
    安裝和運(yùn)行scrapy的過(guò)程中會(huì)遇到很多環(huán)境上的問(wèn)題,這是因?yàn)橄鄳?yīng)的依賴沒(méi)有安裝好。這個(gè)時(shí)候就需要查看錯(cuò)誤信息,然后利用百度、谷歌去搜索相應(yīng)的依賴應(yīng)該如何安裝。

九. 運(yùn)行爬蟲(chóng)及爬取結(jié)果

當(dāng)代碼編寫無(wú)誤后,在命令行界面中,進(jìn)入項(xiàng)目文件夾,即scrapy_learn目錄下,運(yùn)行以下代碼即可開(kāi)始爬蟲(chóng)。

scrapy crawl tutor -o tutor.json

以上代碼是運(yùn)行爬蟲(chóng),并將爬取的內(nèi)容保存為json格式的文件。
爬取結(jié)果:


tutor.json

爬取照片:


爬取教師照片
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容