找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 4361|回復(fù): 0
收起左側(cè)

編寫(xiě)網(wǎng)絡(luò)爬蟲(chóng)—挖掘就業(yè)信息

[復(fù)制鏈接]
ID:73735 發(fā)表于 2015-2-19 01:04 | 顯示全部樓層 |閱讀模式
       說(shuō)起網(wǎng)絡(luò)爬蟲(chóng),我孤陋寡聞了,聽(tīng)上去像蠕蟲(chóng),就以為是網(wǎng)頁(yè)病毒來(lái)著,度娘了下,原來(lái)是抓取網(wǎng)頁(yè)信息的程序或是腳本 。最近又要交個(gè)無(wú)題的作業(yè),加上前不久學(xué)長(zhǎng)都在某某論壇里看就業(yè)信息,所以一來(lái)勁就做了個(gè)就業(yè)信息挖掘機(jī)。
       首先看看這個(gè)網(wǎng)頁(yè),地址我就不說(shuō)了,大家都懂得。頁(yè)面布局同大多的論壇差不多:一個(gè)首頁(yè)、尾頁(yè)選項(xiàng),上一頁(yè)、下一頁(yè)選項(xiàng),跳轉(zhuǎn)選項(xiàng),以及有針對(duì)性的板內(nèi)查詢(xún)選項(xiàng)。要找到有利的信息,當(dāng)然就要看這個(gè)查詢(xún)功能了,我可不想天天像跟美劇的一樣時(shí)刻關(guān)注,也許是時(shí)候未到吧?



       進(jìn)入查詢(xún)頁(yè)面,這讓我情何以堪,只能按標(biāo)題、作者、時(shí)間來(lái)搜!那么問(wèn)題就來(lái)了,木有關(guān)鍵詞?木有模糊搜索?簡(jiǎn)直和在頁(yè)面上看標(biāo)題的效率差不多。。。對(duì)于改進(jìn),最初的想法是做一個(gè)搜索的引擎,可以無(wú)監(jiān)督學(xué)習(xí),按給定的關(guān)鍵詞給出相關(guān)聯(lián)的結(jié)果,就像成語(yǔ)接龍一樣,由近及遠(yuǎn),但細(xì)想一下,要這樣絕不是一兩個(gè)星期就可以解決的,所以就退一步,不搞搜索了,我把這些信息的時(shí)間、標(biāo)題、鏈接以及主要的關(guān)鍵詞都采集出來(lái),以此幫助我篩選信息。


[color=#f79646,strength=3)"]//***分析*******************************************************************************************************************************//
       說(shuō)做就做,首先對(duì)于網(wǎng)頁(yè),我首選腳本提高程序效率,不搞花哨的UI,腳本語(yǔ)言目前只會(huì)Python。在Python下寫(xiě)網(wǎng)絡(luò)爬蟲(chóng),有個(gè)很方便的網(wǎng)絡(luò)抓取框架:Scrapy。下面是Scrapy的數(shù)據(jù)流程圖。

       一開(kāi)始,由Schedule將起始的URL交給Download處理,下載完后給Spider分析,Spider分析出下一鏈接就交給Schedule,分析出要提取的內(nèi)容就交給ItemPipeline保存處理。
       其次,該網(wǎng)頁(yè)出現(xiàn)了中英文。對(duì)英文分詞很簡(jiǎn)單,因?yàn)橛锌崭窦皊plit()函數(shù),在英文下的詞性檢測(cè)算法也較多;關(guān)鍵在中文上,網(wǎng)頁(yè)源碼采用JavaScript編寫(xiě),GB2312編碼,在抓取中可能出現(xiàn)亂碼問(wèn)題,還有關(guān)鍵詞,漢字真是博大精深,同樣的詞在不同語(yǔ)境下有不同的意思,想了好久,決定直接用jieba中文分詞組件,只要有自定義的詞庫(kù),調(diào)用簡(jiǎn)單,但肯定是會(huì)有各種抓取不準(zhǔn)的問(wèn)題。
       最后,對(duì)于無(wú)監(jiān)督學(xué)習(xí)也想了一些思路,要一個(gè)較為智能的學(xué)習(xí),首先要有一個(gè)正確的文本集,可以考慮聚類(lèi),比如:Apriori算法、FP-growth算法;然后就是在學(xué)習(xí)的基礎(chǔ)上分類(lèi),SVM算法、AdaBoost元算法;大數(shù)據(jù)需要降維,PCA、SVD都可以,還可以高大上的分布式。 當(dāng)然這也僅限為思路,說(shuō)說(shuō)的。

[color=#f79646,strength=3)"]//***實(shí)踐********************************************************************************************************************************//
        由于沒(méi)有在windows下成功搭建起Python開(kāi)發(fā)平臺(tái)的組件,以及eclipse,所以轉(zhuǎn)向Linux,命令行一下就ok了,所以整個(gè)爬蟲(chóng)環(huán)境搭建在Ubuntu 14.04下。

1)新建一個(gè)爬蟲(chóng)工程:命令行# scrapy startproject jobSearch
     新建后出現(xiàn)如下信息及scrapy.cfg、jobSearch文件夾;在jobSearch文件夾下有items.py(告訴爬蟲(chóng)抓取的目標(biāo)),pipelines.py(保存抓取結(jié)果),settings.py(用于爬蟲(chóng)的配置),spiders(文件夾為爬蟲(chóng)的核心目錄,完成抓取功能)


2)在python_save/jobSearch/下新建文件夾dict:其為關(guān)鍵詞(集合了自己的專(zhuān)業(yè)詞匯以及搜狗輸入法的專(zhuān)業(yè)相關(guān)詞匯,14萬(wàn)左右)、停用詞集;
      
python_save/jobSearch/下新建文件jobSearchAdv.py用于網(wǎng)頁(yè)鏈接里的文本10個(gè)關(guān)鍵詞的提取。源碼大致如下:
USAGE="usage: python jobSearchAdv.py [file name.json]"
parser=OptionParser(USAGE)
opt, args=parser.parse_args()
if len(args)<1:
        print USAGE
        sys.exit(1)
file_name=args[0]
data=[]

#read info.json to get the big data
def readJSON(fname):
        with open(fname) as f:
                for line in f:
                        data.append(json.loads(line))
        data.sort(reverse=True)

#to find the keywords
def findKeywords(data):
        jieba.analyse.set_stop_words("./dict/stop_words.txt")
        jieba.analyse.set_idf_path("./dict/mydict.txt.big")
        # jieba.analyse.set_idf_path("myidf.txt.big")
        for i in range(len(data)):
                try:
                        detailURL=urllib2.urlopen(data['detailLink']).read().decode('gbk')
                        detail=re.findall(u"標(biāo)  題: (.*?)--", detailURL, re.S)
                        tags=jieba.analyse.extract_tags(detail[0],10)
                        data['keywords']=", ".join(tags)
                except:
                        data['keywords']="?"
                        continue


readJSON(file_name)
findKeywords(data)
subdata="\r\n"
for item in data:
        subdata+="insert into jobinfo (catalog, publishTime, name, detailLink, keywords) values"
        subdata+="('%s','%s','%s','%s','%s');\r\n" %(item['catalog'], item['publishTime'], item['name'], item['detailLink'], item['keywords'])
file_object=codecs.open('detail.sql', 'w', encoding='utf-8')
file_object.write(subdata)
file_object.close()
print "success"



3)在python_save/jobSearch/jobSearch下編寫(xiě)items.py:其中catalog為信息編號(hào),publishTime為信息發(fā)布時(shí)間, name信息標(biāo)題 ,detailLink詳細(xì)鏈接,keywords為關(guān)鍵詞。
class JobsearchItem(scrapy.Item):
    # define the fields for your item here like:
    catalog = scrapy.Field()
    publishTime = scrapy.Field()
    name = scrapy.Field()
    detailLink = scrapy.Field()
    keywords = scrapy.Field()

     
在python_save/jobSearch/jobSearch下編寫(xiě)pipelines.py:
class JobsearchPipeline(object):        def __init__(self):
                # self.file=codecs.open('info.csv', 'w', encoding='utf-8')
                self.file=codecs.open('info.json', 'w', encoding='utf-8')
        def process_item(self, item, spider):
                  line=json.dumps(dict(item), ensure_ascii=False)+ "\n"
                  self.file.write(line)
                  return item
          def spider_closed(self, spider):
                  self.file.close()

4)在python_save/jobSearch/jobSearch/spiders下新建jobInfo.py,這里爬蟲(chóng)的核心程序:
class JobSpider(CrawlSpider):
        """docstring for JobSpider"""
       
        allowed_domains=["sjtu.edu.cn"]
        start_urls=[
                "http://bbs.sjtu.edu.cn/bbsdoc?board=jobInfo",
        ]
        rules=[
                Rule(sle(allow=("/bbsdoc,board,JobInfo,page,53\d{2}")), follow=True, callback='parse_item')
        ]
        def parse_item(self, response):
                items=[]
                sel=Selector(response)
                #get "http://bbs.sjtu.edu.cn/"
                base_url=get_base_url(response)
                #get the detail of current url
                for sites_even in sel.xpath('//table[@border="0"]//tr/td'):       
                          namex=sites_even.xpath('a[contains(@href, "html")]/text()')
                          if str(namex) != "[]":
                                  item=JobsearchItem()
                                item['catalog']=sites_even.xpath('../td[1]/text()').extract()[0]
                                url_detail=sites_even.xpath('a[contains(@href, "html")]/@href').extract()[0]
                                item['detailLink']=urljoin_rfc(base_url, url_detail)
                                  item['name']=namex.extract()[0]
                                item['publishTime']=sites_even.xpath('../td[4]/text()').extract()[0]
                                item['keywords']=""
                                items.append(item)
                info('parsed '+str(response))
                return items
        def _process_request(self, request):
                info('process '+str(request))
                return request       

這樣一個(gè)爬蟲(chóng)的基本功能得以實(shí)現(xiàn)!

[color=#f79646,strength=3)"]//***運(yùn)行測(cè)試****************************************************************************************************************************//

1)命令行:# scrapy crawl jobinfo,生成如下信息和info.json文件(包含關(guān)鍵詞(無(wú)),序號(hào),詳細(xì)鏈接,標(biāo)題,日期)



sublime查看info.json文件,如下,發(fā)現(xiàn)是無(wú)序的,無(wú)關(guān)鍵詞。


2)命令行:# python jobSearchAdv.py info.json,對(duì)info.json各標(biāo)題鏈接進(jìn)行關(guān)鍵詞提取,生成文件detail.sql。出現(xiàn)如下信息和生成文件。


sublime查看detail.sql文件:





[color=#f79646,strength=3)"]//***樣例****************************************************************************************************************************//

detail.sql這個(gè)文件就是最終結(jié)果了,列出了10個(gè)關(guān)鍵詞、標(biāo)題、時(shí)間等信息。
如下的一個(gè)小截圖!爸袊(guó)移動(dòng)杭州研發(fā)中心年薪超13萬(wàn),報(bào)名截止11月”,至少我看得懂它的關(guān)鍵詞:“工程師,開(kāi)發(fā),研發(fā),應(yīng)用,杭州,產(chǎn)品,Java,設(shè)計(jì)師,中國(guó)移動(dòng),經(jīng)理助理”。
但細(xì)看,在列出的10個(gè)關(guān)鍵詞中還是存在問(wèn)題的,比如下一條,“華訊網(wǎng)絡(luò)系統(tǒng)有限公司2015年校園招聘”中出現(xiàn)了“61548”,“專(zhuān)業(yè)”等無(wú)意義詞~






回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表