Scrapy學(xué)習(xí)筆記(二)提取數(shù)據(jù)

在上一節(jié)里面哗总,我定義了結(jié)構(gòu)化字段Item真屯,然而并沒有用到它脸候。
所以,為了能夠?qū)⒂杏玫男畔⒄淼絀tem中去绑蔫,我們需要了解一下提取頁面有效信息的辦法运沦。

  • 這里要用到一個(gè)小工具——Selectors(選擇器)

Selector是Scrapy內(nèi)置的功能配深,它支持使用XPathCSS Selector兩種表達(dá)式來對(duì)信息進(jìn)行搜索携添。
如果有同學(xué)用過正則表達(dá)式的話,對(duì)以上兩種語言應(yīng)該有些感性認(rèn)識(shí)了篓叶。不過比起正則烈掠,也許BeautifulSoup插件中的find Tag與Selector更加相似羞秤,它們都可以很方便地對(duì)提取出html中的標(biāo)簽。(其實(shí)寫這段我有點(diǎn)不確定的左敌,因?yàn)閾?jù)說XPath應(yīng)該是一門在 XML 文檔中查找信息的語言瘾蛋,XML和HTML之間的差異,我理解得不夠深刻矫限。)
這里附上XPath的教程:http://www.w3school.com.cn/xpath/index.asp

Step1:網(wǎng)頁源代碼分析

現(xiàn)在哺哼,我們就打開上一節(jié)中我們保存下來的tencent.txt,我從中選取了一小段我們比較感興趣的數(shù)據(jù)叼风。

<tr class="odd">
            <td class="l square"><a target="_blank" href="position_detail.php?id=42477&keywords=&tid=0&lid=0">SNG16-騰訊音樂多媒體AI研究員(深圳)</a></td>
        <td>技術(shù)類</td>
        <td>3</td>
        <td>深圳</td>
        <td>2018-07-14</td>
</tr>
<tr class="even">
        <td class="l square"><a target="_blank" href="position_detail.php?id=42471&keywords=&tid=0&lid=0">22989-專有云網(wǎng)絡(luò)運(yùn)維工程師(北京/上海/深圳)</a><span class="hot">&nbsp;</span></td>
        <td>技術(shù)類</td>
        <td>2</td>
        <td>深圳</td>
        <td>2018-07-14</td>
</tr>
<tr class="odd">
        <td class="l square"><a target="_blank" href="position_detail.php?id=42472&keywords=&tid=0&lid=0">22989-專有云數(shù)據(jù)庫運(yùn)維工程師(北京/上海/深圳)</a><span class="hot">&nbsp;</span></td>
        <td>技術(shù)類</td>
        <td>2</td>
        <td>深圳</td>
        <td>2018-07-14</td>
        </tr>

初看雜亂的信息中也是有不少規(guī)律的嘛取董。
看第一行中的odd和下面幾行中的even,再結(jié)合剛才看到的原網(wǎng)頁无宿,可以猜出這分別代表了表格中的奇數(shù)行和偶數(shù)行茵汰,他們的背景色不一樣的。

信息表格.jpg

經(jīng)過瀏覽器的渲染孽鸡,摘錄的這段呈現(xiàn)在我們眼中蹂午,就是表格的最后三行了。
現(xiàn)在回頭看一下上節(jié)筆記中定義的Item信息梭灿,就可以一一對(duì)應(yīng)上了画侣,以最后一條為例:

  • name = 22989-專有云數(shù)據(jù)庫運(yùn)維工程師(北京/上海/深圳)
  • detailLink = position_detail.php?id=42472&keywords=&tid=0&lid=0
  • catalog = 技術(shù)類
  • recruitNumber = 2
  • workLocation = 深圳
  • publishTime = 2018-07-14

固然我們可以手動(dòng)從中挑出想要的信息來,但最終的目的依然是讓程序幫我們完成一切堡妒,我們對(duì)html源代碼的關(guān)注配乱,是為了找出有用信息的特征。

  • 可以看出一對(duì)<tr>包括了一條招聘信息皮迟,而<td>括起了一條信息中的各個(gè)元素搬泥。

那是不是如果按順序提取出(tr[1],tr[2],……)再索引到(td[1]伏尼,td[2]忿檩,……)就可以對(duì)應(yīng)上我們想要的信息了呢?
沒錯(cuò)爆阶,不過在XPath里有更簡(jiǎn)單形式的語法能夠幫我們找到他們燥透。

Step2:XPath語法

表達(dá)式 描述
nodename 選取nodename節(jié)點(diǎn)的所有子節(jié)點(diǎn)。
. 選取當(dāng)前節(jié)點(diǎn)辨图。
.. 選取當(dāng)前節(jié)點(diǎn)的父節(jié)點(diǎn)班套。
@ 選取屬性。
[ ] 根據(jù)中括號(hào)的內(nèi)容作篩選
* 通配符:選擇所有元素節(jié)點(diǎn)

還有一個(gè)表達(dá)式符號(hào)我想單獨(dú)拿出來說故河,就是/吱韭,大家知道/在系統(tǒng)里用作文件夾層次的分隔,同樣地鱼的,/應(yīng)該配合以上表達(dá)式食用理盆。單獨(dú)的/表示根節(jié)點(diǎn)位置痘煤。

除了表達(dá)式,XPath還有一類構(gòu)成要素:運(yùn)算符猿规。運(yùn)算符可以連接表達(dá)式衷快,以更方便地完成任務(wù)。我列出了感覺會(huì)常用的坎拐,想了解更多可以查看這個(gè)鏈接:http://www.w3school.com.cn/xpath/xpath_operators.asp

運(yùn)算符 描述 實(shí)例 返回值
| 計(jì)算兩個(gè)節(jié)點(diǎn)集 //book | //cd 返回所有擁有 book 和 cd 元素的節(jié)點(diǎn)集
>= 大于或等于 price>=9.80 如果 price 是 9.90烦磁,則返回 true养匈。如果 price 是 9.70哼勇,則返回 false。
or price=9.80 or price=9.70 如果 price 是 9.80呕乎,則返回 true积担。如果 price 是 9.50,則返回 false猬仁。
and price>9.00 and price<9.90 如果 price 是 9.80帝璧,則返回 true。如果 price 是 8.50湿刽,則返回 false的烁。
<tr class="odd">
            <td class="l square"><a target="_blank" href="position_detail.php?id=42477&keywords=&tid=0&lid=0">SNG16-騰訊音樂多媒體AI研究員(深圳)</a></td>
        <td>技術(shù)類</td>
        <td>3</td>
        <td>深圳</td>
        <td>2018-07-14</td>
</tr>

表格中信息的特征很好辨認(rèn),奇數(shù)行的內(nèi)容一定具有屬性 "odd"诈闺,我們可以編寫表達(dá)式把奇數(shù)行的找出來:

'//*[@class="odd"]'
  • 表達(dá)式的解釋
    剛才提到/可以表示根結(jié)點(diǎn)渴庆,那么//又是什么意思呢,它表示從當(dāng)前節(jié)點(diǎn)開始遞歸下降雅镊,此路徑運(yùn)算符出現(xiàn)在模式開頭時(shí)襟雷,表示應(yīng)從根節(jié)點(diǎn)遞歸下降。
    所以代碼的意思就是:從根節(jié)點(diǎn)開始尋找所有符合要求的節(jié)點(diǎn)仁烹,要求是該行屬性為奇數(shù)行耸弄。
    可是一般來說我們關(guān)注的對(duì)象可不僅僅是奇數(shù)行,還有偶數(shù)行呢卓缰。所以啊用上面提到的節(jié)點(diǎn)集符號(hào)|修改一下表達(dá)式就可以了:
//*[@class="even"] | //*[@class="odd"]

這樣计呈,我們就找到了一條招聘信息的節(jié)點(diǎn),為了能夠分別保存職位名稱征唬、類型捌显、工作地點(diǎn)等信息,我們需要對(duì)上一步找到的節(jié)點(diǎn)做進(jìn)一步處理:

'./td[1]/a/text()'#當(dāng)前節(jié)點(diǎn)中鳍鸵,第1個(gè)td節(jié)點(diǎn)里苇瓣,a節(jié)點(diǎn)內(nèi)的文字:name
'./td[1]/a/@href'#當(dāng)前節(jié)點(diǎn)中,第1個(gè)td節(jié)點(diǎn)里偿乖,a節(jié)點(diǎn)內(nèi)击罪,herf屬性的內(nèi)容:detailLink
'./td[2]/text()'#當(dāng)前節(jié)點(diǎn)中哲嘲,第2個(gè)td節(jié)點(diǎn)里,a節(jié)點(diǎn)內(nèi)的文字:catalog
'./td[3]/text()'#當(dāng)前節(jié)點(diǎn)中媳禁,第3個(gè)td節(jié)點(diǎn)里眠副,a節(jié)點(diǎn)內(nèi)的文字:recruitNumber
'./td[4]/text()'#當(dāng)前節(jié)點(diǎn)中,第4個(gè)td節(jié)點(diǎn)里竣稽,a節(jié)點(diǎn)內(nèi)的文字:workLocation
'./td[5]/text()'#當(dāng)前節(jié)點(diǎn)中囱怕,第5個(gè)td節(jié)點(diǎn)里,a節(jié)點(diǎn)內(nèi)的文字:publishTime

一一對(duì)應(yīng)的關(guān)系找到了毫别,恭喜我們娃弓,終于理解XPath的初級(jí)用法了。接下來要把命令交給爬蟲執(zhí)行岛宦,就需要把它放在tencent.py的parse函數(shù)中蔓涧。

Step3:編寫爬取代碼

打開tencent.py眉孩,在開頭添加上我們對(duì)items.py里定義好的結(jié)構(gòu)化字段的引用苹熏,然后修改整個(gè)文檔的代碼如下:

import scrapy
from tutorial.items import RecruitItem

class RecruitSpider(scrapy.Spider):
    name = "tencent"
    allowed_domains = ["hr.tencent.com"]
    start_urls = [
        "http://hr.tencent.com/position.php?&start=0#a"
    ]

    def parse(self, response):
        for sel in response.xpath('//*[@class="even"] | //*[@class="odd"]'):
            name = sel.xpath('./td[1]/a/text()').extract()[0]
            detailLink = sel.xpath('./td[1]/a/@href').extract()[0]
            catalog = sel.xpath('./td[2]/text()').extract()[0]
            recruitNumber = sel.xpath('./td[3]/text()').extract()[0]
            workLocation = sel.xpath('./td[4]/text()').extract()[0]
            publishTime = sel.xpath('./td[5]/text()').extract()[0]

            item = RecruitItem()
            item['name'] = name.encode('utf-8')
            item['detailLink'] = detailLink.encode('utf-8')
            item['catalog'] = catalog.encode('utf-8')
            item['recruitNumber'] = recruitNumber.encode('utf-8')
            item['workLocation'] = workLocation.encode('utf-8')
            item['publishTime'] = publishTime.encode('utf-8')

            yield item

代碼執(zhí)行部分結(jié)構(gòu)有3層:

  1. for sel in response.xpath('//*[@class="even"] | //*[@class="odd"]'):
    首先找出頁面中所有符合表格奇行和偶行特征的節(jié)點(diǎn)翩蘸,然后用sel這個(gè)臨時(shí)變量去遍歷他們;
  2. name = sel.xpath('./td[1]/a/text()').extract()[0]
    用XPath表達(dá)式去尋找sel中符合要求的元素变汪,分別存入臨時(shí)的字段里侠坎。
    至于為什么語法是這樣的,可以參考:
    xpath().extract()和xpath().extract()[0] 的區(qū)別裙盾? - 知乎用戶的回答 - 知乎
    https://www.zhihu.com/question/63370553/answer/247633004
  3. item['name'] = name.encode('utf-8')
    將臨時(shí)字段里的內(nèi)容轉(zhuǎn)碼成UTF-8再存入item的各字段中实胸。yield類似于C語言的return。

至此代碼部分就編寫完成啦~

Step4:爬取信息

來來闷煤,再度回到\tutorial文件夾下童芹,運(yùn)行終端,輸入:

scrapy crawl tencent -o items.json

即在當(dāng)前目錄下生成了items.json鲤拿。
JSON語言能夠方便地被讀取假褪,我理解為輕量的數(shù)據(jù)庫。
我是第一次處理json格式的語言近顷,所以在用NPP記事本打開文檔的時(shí)候生音,望著格式一團(tuán)糟的json頭暈了。不過為了降低學(xué)習(xí)成本窒升,暫時(shí)還沒有開數(shù)據(jù)庫的坑缀遍。那就找一個(gè)能夠方便地把UTF-8代碼顯示成漢字的工具吧。
我是選擇了NPP的插件JSON Viewer饱须,可以對(duì)JSON可視化排版域醇,也能把UTF-8翻譯成漢字,大概是這樣的:


JSON Viewer處理的效果

嗯……就是這樣。
但是這個(gè)界面……求一款顏值高的本地工具譬挚,謝謝锅铅。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市减宣,隨后出現(xiàn)的幾起案子盐须,更是在濱河造成了極大的恐慌,老刑警劉巖漆腌,帶你破解...
    沈念sama閱讀 221,635評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件贼邓,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡闷尿,警方通過查閱死者的電腦和手機(jī)塑径,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來悠砚,“玉大人晓勇,你說我怎么就攤上這事」嗑桑” “怎么了?”我有些...
    開封第一講書人閱讀 168,083評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵绰筛,是天一觀的道長(zhǎng)枢泰。 經(jīng)常有香客問我,道長(zhǎng)铝噩,這世上最難降的妖魔是什么衡蚂? 我笑而不...
    開封第一講書人閱讀 59,640評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮骏庸,結(jié)果婚禮上毛甲,老公的妹妹穿的比我還像新娘。我一直安慰自己具被,他們只是感情好玻募,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,640評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著一姿,像睡著了一般七咧。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上叮叹,一...
    開封第一講書人閱讀 52,262評(píng)論 1 308
  • 那天艾栋,我揣著相機(jī)與錄音,去河邊找鬼蛉顽。 笑死蝗砾,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播悼粮,決...
    沈念sama閱讀 40,833評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼拇泣,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了矮锈?” 一聲冷哼從身側(cè)響起霉翔,我...
    開封第一講書人閱讀 39,736評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎苞笨,沒想到半個(gè)月后债朵,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,280評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡瀑凝,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,369評(píng)論 3 340
  • 正文 我和宋清朗相戀三年序芦,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片粤咪。...
    茶點(diǎn)故事閱讀 40,503評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡谚中,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出寥枝,到底是詐尸還是另有隱情宪塔,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評(píng)論 5 350
  • 正文 年R本政府宣布囊拜,位于F島的核電站某筐,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏冠跷。R本人自食惡果不足惜南誊,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,870評(píng)論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蜜托。 院中可真熱鬧抄囚,春花似錦、人聲如沸橄务。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽仪糖。三九已至柑司,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間锅劝,已是汗流浹背攒驰。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評(píng)論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留故爵,地道東北人玻粪。 一個(gè)月前我還...
    沈念sama閱讀 48,909評(píng)論 3 376
  • 正文 我出身青樓隅津,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國和親劲室。 傳聞我的和親對(duì)象是個(gè)殘疾皇子伦仍,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,512評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • 關(guān)于Mongodb的全面總結(jié) MongoDB的內(nèi)部構(gòu)造《MongoDB The Definitive Guide》...
    中v中閱讀 31,947評(píng)論 2 89
  • scrapy學(xué)習(xí)筆記(有示例版) 我的博客 scrapy學(xué)習(xí)筆記1.使用scrapy1.1創(chuàng)建工程1.2創(chuàng)建爬蟲模...
    陳思煜閱讀 12,713評(píng)論 4 46
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)很洋,斷路器充蓝,智...
    卡卡羅2017閱讀 134,699評(píng)論 18 139
  • 大圣的麻麻閱讀 152評(píng)論 0 0
  • 那篇暗戀那些事的推文,精彩的地方還是在評(píng)論喉磁。 “為了偶遇你繞遍校園”谓苟。我會(huì)為了偶遇一些想看見的人故意下課出去逛逛或...
    去社閱讀 312評(píng)論 2 0