實驗報告【爬取Curlie網(wǎng)站信息】

一圃郊、實驗目標

使用scrapy框架采集Curlie網(wǎng)站下Kids_and_Teens的分類子目錄結(jié)構(gòu)以及此分類下所收集的所有站點的網(wǎng)站名靡狞、網(wǎng)站鏈接及網(wǎng)站簡介。

擬突破的重難點

  1. 破解網(wǎng)站的反爬蟲策略
  2. 跟蹤URL進行多層網(wǎng)頁鏈接的爬取(crawlSpider或者遞歸)
  3. 使用pandas進行數(shù)據(jù)清洗與處理

二谚中、實驗環(huán)境

  • 操作系統(tǒng):CentOS 7.4 64位
  • python環(huán)境:python2.7.5與python2.7.12兩版本共存
  • 采用的爬蟲框架:scrapy1.5.0

三、實驗方案設計

①分析目標網(wǎng)頁,制定爬取規(guī)則----》②編寫python代碼----》③不斷調(diào)試代碼宪塔,得到初步結(jié)果----》④數(shù)據(jù)清洗磁奖,生成最終的結(jié)果文件

四、實驗過程

1. 分析目標網(wǎng)頁某筐,制定爬取規(guī)則

首頁的子類解析

此頁面有14個子類比搭,進入Arts分類網(wǎng)頁。


ARTS

爬取流程如下圖南誊,即爬取多層網(wǎng)頁的結(jié)構(gòu)數(shù)據(jù)身诺。


數(shù)據(jù)爬取流程

2. 編寫python代碼

  • items.py
# -*- coding: utf-8 -*-

import scrapy
class KidsItem(scrapy.Item):
    cate_path = scrapy.Field()
    sites = scrapy.Field()

在編寫具體的爬蟲代碼時,本小組設計了兩種方案抄囚。
第一種方案是在當網(wǎng)頁

plan A:scrapy.Spider遞歸爬取網(wǎng)頁數(shù)據(jù)

  • kidsspiderA.py
# -*- coding: utf-8 -*-
# Please refer to the documentation for information on how to create and manage
# your spiders.
import scrapy
from kids.items import *

class Kids(scrapy.Spider):
  name="kidsspider"
  allowed_domains=["curlie.org"]
  start_urls=[
    'http://curlie.org/Kids_and_Teens/',
  ]

  def parse(self,response):
    item=KidsItem()
    item['cate_path']=response.url.strip('http://curlie.org')
    sites=response.xpath("http://section[@class='results sites']").extract()
    if sites:
      sitelist=list()
      for lp in response.xpath("http://div[@id='site-list-content']/div"):
        s={}
        s['site_url']=lp.xpath("div[@class='title-and-desc']/a/@href").extract_first()
        s['site_title']=lp.xpath("div[@class='title-and-desc']/a/div/text()").extract_first()
        s['site_desc']=lp.xpath("div[@class='title-and-desc']/div[@class='site-descr ']/text()").extract_first().strip()
        sitelist.append(s)
      item['sites']=sitelist
    yield item

    for kids in response.xpath("http://div[@id='subcategories-div']/section[@class='children']/div[@class='cat-list results leaf-nodes']/div"):
      link=kids.xpath("a/@href").extract()
      if link:
        link="http://curlie.org" + link[0]  #要爬取的下一個鏈接
        yield scrapy.Request(link, callback=self.parse)

plan B 通過Crawlspider爬取網(wǎng)頁

  • kidsSpiderB.py
import scrapy
from scrapy.spiders import CrawlSpider, Rule
from scrapy.linkextractors import LinkExtractor
from kids.items import *

class Kids(CrawlSpider):
    name = 'kidsSpider3'
    allowed_domains = ['curlie.org']
    start_urls = ['http://curlie.org/Kids_and_Teens/']

    rules = [
        Rule(LinkExtractor(
            restrict_css=('.cat-item')
        ), callback='parse_site', follow=True),
    ]

    def parse_site(self, response):
        item=KidsItem()
        item['cate_path']=response.url.strip('http://curlie.org/')

        sites=list()
        for div in response.css('.title-and-desc'):
            site={}
            site['site_title']=div.css('.site-title::text').extract_first()
            site['site_desc']= div.css('.site-descr::text').extract_first().strip()
            site['site_url']=div.css('a::attr(href)').extract_first()
            sites.append(site)

        item['sites']=sites
        yield item

3. 調(diào)試代碼霉赡,得到初步結(jié)果

經(jīng)過漫長的調(diào)試,最后我們的代碼終于能夠成功運行了幔托。

晚上睡覺之前在創(chuàng)建的screen里面打開了爬蟲同廉,然后C-a d退出,將爬蟲程序置于后臺運行柑司。
第二天八點起床的時候打開電腦迫肖,登錄Xshell之后,輸入
screen -r,再次進入爬蟲界面攒驰,發(fā)現(xiàn)kidsSpider已經(jīng)finished了蟆湖。嘻嘻~~~

  • plan A 爬取結(jié)果


    plan A結(jié)束部分截圖

    可以看到爬取了7135條items

  • plan B爬取結(jié)果


    plan B結(jié)束界面截圖

    可以看到一共爬取了6705條item,request請求的最大深度居然有16層玻粪。
    兩種方案爬取的結(jié)果不太一樣隅津,應該是因為使用的代理IP池不同,訪問某些網(wǎng)頁的時候被重定向的情況有所不同劲室。
    用editplus打開爬取的數(shù)據(jù):


    plan B爬取的部分json數(shù)據(jù)

    使用JsonViwer查看具體的層級結(jié)構(gòu):
    JsonViwer查看爬取的數(shù)據(jù)的部分截圖

    經(jīng)過瀏覽發(fā)現(xiàn)伦仍,cate_path的順序是亂的,并且有一些重復的目錄很洋,需要進一步的數(shù)據(jù)清洗充蓝。

4. 數(shù)據(jù)清洗,得到最終結(jié)果

1)目標:去重喉磁、cate_path字段排序谓苟,導出cate_path字段。
2)工具: pandas庫
3)清洗過程

  • 安裝pandas庫


    安裝pandas
  • 編寫代碼
import pandas as pd
df =pd.read_json('/home/lly/kids/kids_and_teens.json') # 讀取json文件
print df.info()

#去重
df.duplicated("cate_path") #判斷是否有重復項
df=df.drop_duplicates("cate_path") #去掉重復項
print df.info() #查看去重是否成功

#排序
df=df.sort_values(by=['cate_path']) #按照cate_path進行排序
df['cate_path'].to_csv('category.csv') #輸入目錄結(jié)構(gòu)文件cate.csv

df.to_json('results.json')

4)清洗后的最終結(jié)果
一共去除了1022條重復數(shù)據(jù)协怒,如下圖:


去重結(jié)果

爬取的目錄結(jié)構(gòu)涝焙,詳見category.csv文件,部分截圖如下:


目錄結(jié)構(gòu)部分截圖

爬取的網(wǎng)站信息孕暇,詳見results.json文件仑撞,部分截圖如下:
results.json部分截圖

注:文件中的“0”赤兴、“1”、“2”....等是該site所在目錄的索引號隧哮。

五搀缠、調(diào)試過程

1.如何利用遞歸遍歷所有目錄

curlie.org此網(wǎng)站下每個目錄下都有很多層級子目錄,由于要求爬取所有子目錄及其目錄下的sites信息近迁。所以,需要用到遞歸的算法進行遍歷簸州。參考教程
存在一些目錄下并沒有sites鉴竭,因此對sites進行了if判斷。并且對sites進行整合岸浑,將一個目錄下的sites整合到一個list()中搏存。改進后的代碼見下圖:

遞歸.png

2.破解目標網(wǎng)站的反爬蟲機制

早就聽聞,爬蟲-反爬蟲-反反爬蟲....是爬蟲蜘蛛與網(wǎng)站運維人員之間的一場永無止境的斗爭矢洲。這一次璧眠,終于遇上了。
curlie的反爬蟲機制有封禁IP读虏、服務器端網(wǎng)頁重定向等责静,在我們的本次實驗中遇到的問題有:

  • TCP connection timed out: 110:
  • Connection was refused by other side: 111: Connection refused.
  • DEBUG: Redirecting (301)永久重定向
  • DEBUG: Redirecting (302)暫時重定向
  • .......

為了解決上述問題,本小組采取的解決辦法有:

  • 設置隨機user-agent盖桥,偽造user發(fā)送請求
  • 設置隨機IP代理
  • 設置下載延遲
  • 設置不遵循robots.txt協(xié)議
  • 禁用cookie

六灾螃、爬蟲策略的進一步探索

  • 實驗的不足之處:不知道是否已經(jīng)目標目錄下的所有的站點信息;網(wǎng)站的目錄結(jié)構(gòu)存成json或者xml的樹狀結(jié)構(gòu)更能體現(xiàn)目錄之間的層級關(guān)系揩徊。
    為了解決上述問題腰鬼,小組進行了爬蟲策略的進一步探索。

1.用crontab實現(xiàn)定時執(zhí)行scrapy任務

crontab命令常見于Unix和類Unix的操作系統(tǒng)之中塑荒,用于設置周期性被執(zhí)行的指令熄赡。下面是使用crontab進行定時循環(huán)執(zhí)行scrapy爬蟲的操作:

  • 安裝crontab
    yum install crontab

  • 編輯crontab服務文件
    crontab -e
    (其他參數(shù):-u 指定用戶下的crontab; -r 刪除齿税; -l 查看crontab工程目錄彼硫; -i 有提示的刪除)

  • 在crontab文件中添加命令以爬取name為ACW1的爬蟲
    * * * * * cd /home/hyj/kids && scrapy crawl ACW1 -o ACW1.json
    詳細寫法參見Linux下的crontab定時執(zhí)行任務命令詳解

以上指令可以實現(xiàn)每分鐘執(zhí)行一次爬蟲。但是在爬蟲比較多時凌箕,可以采用shell腳本集中管理乌助。
若爬蟲運行時間較長,又想錯開目標網(wǎng)站的訪問高峰時間段陌知,可結(jié)合scrapy jobs進行暫停爬取他托,之后再恢復運行,接著上一次的斷點繼續(xù)爬取數(shù)據(jù)仆葡。

  • 遇到的一些問題
    如果直接在crontab -e中輸入* * * * * scrapy crawl xxx赏参,定時任務是不會生效的志笼,因為我們不知道crontab執(zhí)行時,其所處的目錄把篓,很有可能就沒有scrapy命令和crawl命令纫溃。因此,改用指令:* * * * * cd /home/hyj/kids && scrapy crawl ACW1就可以正常的執(zhí)行定時任務了韧掩。

  • 查看crontab歷史執(zhí)行情況
    默認情況下,crontab中執(zhí)行的日志寫在/var/log下紊浩。可通過以下指令在root權(quán)限下訪問:
    tail –f /var/log/cron

    crontab日志

2.爬取curlie全站的策略

  • 分析網(wǎng)站首頁疗锐,改寫爬蟲代碼


    curlie首頁

可以看到首頁上的打開分類目錄的下一層鏈接都在名為"top cat"的標簽里面坊谁,之后每一個大類的網(wǎng)站結(jié)構(gòu)都跟kids_and_teens的結(jié)構(gòu)一樣。因此滑臊,只要在crawlSpider的rules對象中將網(wǎng)站url的匹配規(guī)則改寫一下就可以了口芍。代碼改動部分有一下兩處:


全站爬蟲代碼改動部分
  • 爬蟲的執(zhí)行
    在首頁上可以看到curlie收錄的站點約370萬個,分別位于約100萬個目錄下雇卷。


    站點總數(shù)

    在沒有網(wǎng)站的反爬蟲限制鬓椭,用一臺服務器執(zhí)行爬蟲指令,遵循crawl_delay=1的協(xié)議关划,一切順利的話小染,大約17天能爬下來所有的站點數(shù)據(jù)。

3.分布式爬蟲spider-redis

為了滿足在較短時間內(nèi)爬取大量數(shù)據(jù)的需求贮折,分布式的爬蟲應運而生氧映,在爬取curlie全站的時候也可以采用分布式的爬蟲。要搭建分布式爬蟲需要多臺服務器:

  • 一臺中心服務器master:不執(zhí)行具體的爬蟲任務脱货,只負責request任務分配岛都、將數(shù)據(jù)存入redis數(shù)據(jù)庫、判斷url是否重復等工作
  • 多臺爬蟲執(zhí)行服務器Slaver:負責執(zhí)行爬蟲程序振峻,運行過程中提交新的Request給中心服務器

Slaver從中心服務器拿任務(Request臼疫、url)進行數(shù)據(jù)抓取,在抓取數(shù)據(jù)的同時扣孟,產(chǎn)生新任務的Request便提交給 Master 處理烫堤;

Master端只有一個Redis數(shù)據(jù)庫,負責將未處理的Request去重和任務分配凤价,將處理后的Request加入待爬隊列鸽斟,并且存儲爬取的數(shù)據(jù)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末利诺,一起剝皮案震驚了整個濱河市富蓄,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌慢逾,老刑警劉巖立倍,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件灭红,死亡現(xiàn)場離奇詭異,居然都是意外死亡口注,警方通過查閱死者的電腦和手機变擒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來寝志,“玉大人娇斑,你說我怎么就攤上這事〔牟浚” “怎么了毫缆?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長败富。 經(jīng)常有香客問我,道長摩窃,這世上最難降的妖魔是什么兽叮? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮猾愿,結(jié)果婚禮上鹦聪,老公的妹妹穿的比我還像新娘。我一直安慰自己蒂秘,他們只是感情好泽本,可當我...
    茶點故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著姻僧,像睡著了一般规丽。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上撇贺,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天赌莺,我揣著相機與錄音,去河邊找鬼松嘶。 笑死艘狭,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的翠订。 我是一名探鬼主播巢音,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼尽超!你這毒婦竟也來了官撼?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤似谁,失蹤者是張志新(化名)和其女友劉穎歧寺,沒想到半個月后燥狰,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡斜筐,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年龙致,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片顷链。...
    茶點故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡目代,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出嗤练,到底是詐尸還是另有隱情榛了,我是刑警寧澤,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布煞抬,位于F島的核電站霜大,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏革答。R本人自食惡果不足惜战坤,卻給世界環(huán)境...
    茶點故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望残拐。 院中可真熱鬧途茫,春花似錦、人聲如沸溪食。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽错沃。三九已至栅组,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間枢析,已是汗流浹背笑窜。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留登疗,地道東北人排截。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像辐益,于是被迫代替她去往敵國和親断傲。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,037評論 2 355

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