這些都是原來在微博上的文章,慢慢搬到這里吧
(一)安裝和測試
學(xué)習(xí)網(wǎng)絡(luò)爬蟲也是進(jìn)行自然語言處理的前期準(zhǔn)備工作虑润,爬蟲是獲取大量語料的利器?瓢对,自從學(xué)會(huì)使用網(wǎng)絡(luò)爬蟲之后跛锌,幫人爬了些網(wǎng)頁數(shù)據(jù)贱呐,感覺自己胸前的紅領(lǐng)巾又更鮮艷了一些
最開始用的是BeautifulSoup爬取靜態(tài)網(wǎng)頁丧诺,效果已經(jīng)很讓我驚艷了
后來遇到動(dòng)態(tài)網(wǎng)站,又用了下Selenium奄薇,調(diào)用firefox爬取動(dòng)態(tài)數(shù)據(jù),也是成就感滿滿
然而聽說爬蟲框架Scrapy更高效(B格更高)抗愁,于是決定今天開始學(xué)習(xí)一下
首先聽說windows系統(tǒng)下Scrapy安裝非常的復(fù)雜馁蒂,我已經(jīng)準(zhǔn)備好又折騰一整天,不過有了Anaconda平臺(tái)蜘腌,這些都不是事沫屡,一行代碼搞定:
conda intall scrapy
然后是測試:
創(chuàng)建項(xiàng)目 scrapy startproject test
進(jìn)入項(xiàng)目目錄 cd test
生成爬蟲 scrapy genspider baidu www.baidu.com
爬取百度 scrapy crawl baidu
成功,撒花慶祝撮珠!
(二)——熟悉Xpath
開始Xpath之前先補(bǔ)充一下剛剛踩的一個(gè)小小坑
準(zhǔn)備寫這篇筆記之前打算在筆記本上也裝上scrapy沮脖,結(jié)果用conda install安裝好慢好慢好慢,一度以為是家里網(wǎng)絡(luò)問題芯急,查了下才發(fā)現(xiàn)添加下國內(nèi)鏡像源就可以了勺届,輸入以下代碼即可:
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
conda config --set show_channel_urls yes
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge/
conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/msys2/
好了,開始Xpath娶耍,Xpath就是用來在XML文檔中查找目標(biāo)元素的語言免姿,HTML和XML一樣,也是洋蔥一樣的一層一層包裹的結(jié)構(gòu)榕酒,所以可以用Xpath很方便地在HTML文檔中找到我們想要的元素
Xpath長這樣:
//*[@id="t1"]/tbody/tr/td/table/tbody/tr/td/table[1]/tbody/tr[2]/td[2]/table[1]/tbody/tr[2]/td[3]/b
就是一層一層地找下來胚膊,找到目標(biāo)元素
很多瀏覽器都可以很方便地查看網(wǎng)頁中某元素的Xpath,右鍵單擊要查看的目標(biāo)想鹰,選擇“查看元素”紊婉,在顯示的元素源代碼中右鍵選擇“復(fù)制Xpath”,上面一段長長的Xpath就是這么來的
不過實(shí)際使用中不建議直接用上面這樣的Xpath辑舷,因?yàn)檫@個(gè)路徑太長喻犁,還有很多按數(shù)字順序選擇的元素,萬一網(wǎng)頁結(jié)構(gòu)稍有變化(比如彈出個(gè)廣告框)惩妇,這個(gè)結(jié)果就謬之千里了
比較穩(wěn)妥的做法是用id來選擇
嗯株汉,Xpath的語法有很多很多,參加教程吧http://www.w3school.com.cn/xpath/xpath_syntax.asp
接下來就是在scrapy中嘗試一下Xpath的威力
在Anaconda端口輸入scrapy shell www.目標(biāo)網(wǎng)頁.com?
居然又報(bào)錯(cuò)8柩辍(真是一臺(tái)電腦一個(gè)環(huán)境乔妈,各種報(bào)錯(cuò)層出不窮啊)
錯(cuò)誤信息:DLL load failed: 操作系統(tǒng)無法運(yùn)行1%
解決方法:pip install -I cryptography
好啦氓皱,網(wǎng)頁讀取正常啦路召,接下來就用
response.xpath(' ').extract()各種嘗試吧
最后ctrl+d退出
收工睡覺勃刨!
(三)——?jiǎng)?chuàng)建項(xiàng)目
下面要正式開始創(chuàng)建項(xiàng)目了,其實(shí)在第一篇筆記的安裝測試中股淡,就已經(jīng)創(chuàng)建了一個(gè)項(xiàng)目
這次我?計(jì)劃從一些期刊中爬取標(biāo)題身隐、摘要、關(guān)鍵詞等內(nèi)容唯灵,所以我創(chuàng)建了一個(gè)名為articles的項(xiàng)目:
anaconda端口中cd到準(zhǔn)備存儲(chǔ)項(xiàng)目的文件夾贾铝,輸入scrapy startproject articles?
發(fā)現(xiàn)文件夾中多了一個(gè)名為articles的文件夾,點(diǎn)開?是這樣的:
創(chuàng)建articles項(xiàng)目文件夾
?只用一行代碼埠帕,項(xiàng)目就搭好了垢揩,接下來就要往文件夾里面一點(diǎn)一點(diǎn)填東西
這下理解了為什么scrapy叫爬蟲框架,就是人家搭好了架子敛瓷,按照模板填東西就好
(1)定義Item
打開文件夾中的items.py文件叁巨,按照給出的示例(name = scrapy.Field()),定義我準(zhǔn)備爬取的字段呐籽,包括中英文標(biāo)題锋勺、關(guān)鍵詞、摘要等
定義字段列表
?
(2)編寫爬蟲
scrapy提供了不同的爬蟲模板狡蝶,用scrapy genspider -l查看庶橱,有basic、crawl牢酵、csvfeed悬包、xmlfeed四種
先用basic模板試試,輸入scrapy genspider basic web
spiders文件夾中多了一個(gè)basic.py文件
打開編輯一下
basic模板
?start_urls = [' ']里面填入要爬取的文章網(wǎng)頁
def parse(self, response):里面填入網(wǎng)頁中要獲取的字段內(nèi)容馍乙,這里Xpath就大派用場了
用Xpath獲取網(wǎng)頁中的目標(biāo)元素
?(3)運(yùn)行爬蟲
Anaconda端口輸入scrapy crawl basic
編輯好的basic.py爬蟲就開始運(yùn)行了布近,控制臺(tái)輸出了我要的標(biāo)題、關(guān)鍵詞丝格、摘要等內(nèi)容
運(yùn)行爬蟲 控制臺(tái)輸出日志
?換一個(gè)文章網(wǎng)頁也可以
scrapy parse --spider=basic http://另一篇文章的網(wǎng)站.com
(4)填充Item
目前為止撑瞧,第一步定義的Item似乎還沒有發(fā)揮作用,爬取的目標(biāo)元素直接在控制臺(tái)中輸出了显蝌,看起來亂的很
不急预伺,這就把結(jié)果導(dǎo)入到之前定義的Item中
還是編輯basic.py
首先導(dǎo)入編寫的ArcticlesItem:from articles.items import ArticlesItem
定義一個(gè)item實(shí)例:item=ArticlesItem()
給item的字段賦值,如:item['title_CN']=response.xpath('//h3[@class="abs-tit"][1]/text()').extract()
最后不要忘記 return item
定義item并給其字段賦值
?然后端口再運(yùn)行:scrapy crawl basic -o items.xml
結(jié)果直接導(dǎo)出到xml文件(json曼尊、jl酬诀、csv文件都可以,這里我選了xml)
結(jié)果導(dǎo)出到xml文件
?
好了骆撇,大功告成瞒御,一個(gè)最最基礎(chǔ)的爬蟲就搭起來了,后面再接著完善
(四)——清洗Item
上一篇筆記里已經(jīng)成功爬出了需要的字段神郊,但是結(jié)果還不是很理想肴裙,比如還有一些惱人的逗號(hào)趾唱、不必要的分段等等
我以前的解決方式是導(dǎo)出來之后,另外用re模塊進(jìn)行文本處理
但是scrapy框架里面蜻懦,這一步工作也為我們考慮到了甜癞,這就是ItemLoader,相當(dāng)于一個(gè)中轉(zhuǎn)站宛乃,爬下來的數(shù)據(jù)先不著急放到Item里面悠咱,而是在ItemLoader中先清洗一下,然后再導(dǎo)出到Item中
ItemLoader的具體用法見官方文檔:
https://doc.scrapy.org/en/latest/topics/loaders.html
還有一篇中文的博客文章也不錯(cuò):
https://blog.csdn.net/zwq912318834/article/details/79530828
用ItemLoader可以自己構(gòu)建處理器(Processor)烤惊,將爬取的原始數(shù)據(jù)經(jīng)過處理器處理后再導(dǎo)出到Item中乔煞。不過我目前只需要用到內(nèi)置的一些處理器,一個(gè)是Join()柒室,將獲取的多個(gè)段落連接成一個(gè);
還有一個(gè)是MapCompose()逗宜,()里面可以放入多個(gè)函數(shù)雄右,數(shù)據(jù)由第一個(gè)函數(shù)處理完后,傳遞給第二個(gè)函數(shù)纺讲,以此類推擂仍。我只用了一個(gè)函數(shù),MapCompose(lambda i:i.replace(',',''))熬甚,將多余的‘逢渔,’去掉。
好了乡括,現(xiàn)在接著來修改basic.py文件:
首先導(dǎo)入需要的對(duì)象肃廓、函數(shù):
from scrapy.loader import ItemLoader
from scrapy.loader.processors import MapCompose,Join
然后將parse函數(shù)修改如下
使用ItemLoader清洗Item
?導(dǎo)出結(jié)果如圖,比之前舒服多了:
導(dǎo)出結(jié)果
(五)——爬取多個(gè)url
之前的筆記一直只是在拿一個(gè)網(wǎng)頁做試驗(yàn)诲泌,?但實(shí)際上我們需要對(duì)整個(gè)網(wǎng)站進(jìn)行爬取
還是要對(duì)basic.py進(jìn)行修改
最直接的方法就是在start_urls的列表里面添加網(wǎng)頁地址
start_urls = ['url1','url2','url3']
很明顯這不是一個(gè)理智的做法
還有一種方法是如果已經(jīng)有了一個(gè)待爬取網(wǎng)頁的列表盲赊,把它存在txt文檔中,一行為一個(gè)網(wǎng)址敷扫,然后讀取這個(gè)txt文件
start_urls = [i.strip() for i in open('list.txt').readlines()]
這個(gè)方法看著B格也不是很高哀蘑,不過有時(shí)候能應(yīng)急,我在不會(huì)爬取動(dòng)態(tài)網(wǎng)站的時(shí)候就用了這個(gè)方法葵第,把網(wǎng)址索引頁的表格整個(gè)復(fù)制粘貼到excel中绘迁,就這樣弄到了整個(gè)網(wǎng)站的url列表(雖然B格不高,但是夠快夠輕松白涿堋)
現(xiàn)在看看scrapy用的方法吧
先導(dǎo)入需要的函數(shù) from scrapy.http import Request
起點(diǎn)設(shè)置成第一期的網(wǎng)頁start_urls = ['/*the first volume*/']
把原先的parse()函數(shù)更改為parse_item()
再寫一個(gè)新的parse()函數(shù)缀台,這個(gè)函數(shù)一方面調(diào)取下一期的url(next_selector),接著進(jìn)行解析栅受;另一方面調(diào)取本期文章的url(item_selector)将硝,填充item
遍歷整個(gè)網(wǎng)站的parse函數(shù)
?最后端口運(yùn)行scrapy crawl basic -o items.xml
喝幾口茶恭朗,ok,全部爬完啦依疼,一個(gè)10M的xml文件呈現(xiàn)在面前
好吧痰腮,真實(shí)場景是我又遇到了坑
1.Request()中必須加上dont_filter=True,否則什么都爬不到律罢,原因不明(目標(biāo)url和allowed_domains也并不沖突啊膀值。。误辑。沧踏。。巾钉。)
2.原本是用urlparse來解析抽取的相對(duì)路徑翘狱,總是報(bào)錯(cuò),最后只好用了個(gè)字符串替換解決了(還是原因不明)
3.scrapy還提供了一種B格更高的類LinkExtractor砰苍,上面的7行代碼可以用2行解決潦匈,嘗試了一下午,沒有成功
目前就先到這里吧赚导,接下來還準(zhǔn)備再爬一些期刊茬缩,多多準(zhǔn)備語料
scrapy還有更多更強(qiáng)大的功能,留著有空再慢慢研究