scrapy

  • Scrapy是用純python實(shí)現(xiàn)一個為了爬取網(wǎng)站數(shù)據(jù)齿坷、提取結(jié)構(gòu)性數(shù)據(jù)而編寫的應(yīng)用框架,用途非常廣泛

  • Scrapy架構(gòu)圖(綠線是數(shù)據(jù)流向):

    image
  • Scrapy Engine(引擎): 負(fù)責(zé)Spider、ItemPipeline剥悟、Downloader黔漂、Scheduler中間的通訊,信號民效、數(shù)據(jù)傳遞等憔维。

  • Scheduler(調(diào)度器): 它負(fù)責(zé)接受引擎發(fā)送過來的Request請求,并按照一定的方式進(jìn)行整理排列畏邢,入隊(duì)业扒,當(dāng)引擎需要時,交還給引擎舒萎。

  • Downloader(下載器):負(fù)責(zé)下載Scrapy Engine(引擎)發(fā)送的所有Requests請求程储,并將其獲取到的Responses交還給Scrapy Engine(引擎),由引擎交給Spider來處理

  • Spider(爬蟲):它負(fù)責(zé)處理所有Responses,從中分析提取數(shù)據(jù)臂寝,獲取Item字段需要的數(shù)據(jù)虱肄,并將需要跟進(jìn)的URL提交給引擎,再次進(jìn)入Scheduler(調(diào)度器)交煞,

  • Item Pipeline(管道):它負(fù)責(zé)處理Spider中獲取到的Item咏窿,并進(jìn)行進(jìn)行后期處理(詳細(xì)分析、過濾素征、存儲等)的地方.

  • Downloader Middlewares(下載中間件):你可以當(dāng)作是一個可以自定義擴(kuò)展下載功能的組件集嵌。

  • Spider Middlewares(Spider中間件):你可以理解為是一個可以自定擴(kuò)展和操作引擎和Spider中間通信的功能組件(比如進(jìn)入Spider的Responses;和從Spider出去的Requests)

一萝挤、新建項(xiàng)目(scrapy startproject)

  • 創(chuàng)建爬蟲項(xiàng)目

scrapy startproject 項(xiàng)目名稱 (有些用戶需要前面加上python -m)

  • 新建爬蟲文件

scrapy genspider 爬蟲文件 域名

  • item 定義結(jié)構(gòu)化數(shù)據(jù)字段,用來保存爬取到的數(shù)據(jù)根欧,有點(diǎn)像Python中的dict怜珍,但是提供了一些額外的保護(hù)減少錯誤。
item文件
class JobboleItem(scrapy.Item):
    # define the fields for your item here like:
    #標(biāo)題
    title = scrapy.Field()
    #創(chuàng)建時間
    create_date = scrapy.Field()
    #文章地址
    url = scrapy.Field()
    #id
    url_object_id = scrapy.Field()
    #文章圖片
    front_image_url = scrapy.Field()
    #文章圖片地址
    front_image_path = scrapy.Field()
    # 點(diǎn)贊數(shù)
    praise_nums = scrapy.Field()
    #收藏?cái)?shù)
    bookmark_nums = scrapy.Field()

二凤粗、制作爬蟲

# -*- coding: utf-8 -*-
import scrapy
class JobboleSpider(scrapy.Spider):

    name = '爬蟲文件'
    allowed_domains = ['網(wǎng)站域名']
    start_urls = ['https://xxx.xxxx.com/xxxx-x/']
def parse(self, response):
    pass

  • name = " " :這個爬蟲的識別名稱酥泛,必須是唯一的,在不同的爬蟲必須定義不同的名字嫌拣。

  • allow_domains = [] 是搜索的域名范圍柔袁,也就是爬蟲的約束區(qū)域,規(guī)定爬蟲只爬取這個域名下的網(wǎng)頁异逐,不存在的URL會被忽略捶索。

  • start_urls = () :爬取的URL元祖/列表。爬蟲從這里開始抓取數(shù)據(jù)灰瞻,所以腥例,第一次下載的數(shù)據(jù)將會從這些urls開始。其他子URL將會從這些起始URL中繼承性生成酝润。

  • parse(self, response) :解析的方法燎竖,每個初始URL完成下載后將被調(diào)用,調(diào)用的時候傳入從每一個URL傳回的Response對象來作為唯一參數(shù)

三要销、在parse方法中做數(shù)據(jù)的提取

from jobboleproject.items import JobboleprojectItem
    1.獲取圖片和文章詳情的鏈接
def parse(self, response):
    # css選擇器獲取當(dāng)前列表頁面的所有的節(jié)點(diǎn)
    post_nodes = response.css("#archive .floated-thumb .post-thumb a")

    # 如果不是完整的域名 需要拼接完整 response.url + post_url
    # 獲取到的URL可能不是一個域名构回,也可能是具體的文章需要使用parse函數(shù)from urllib import parse
    for post_node in post_nodes:
    image_url = post_node.css("img::attr(src)").extract_first("")
    post_url = post_node.css("::attr(href)").extract_first("")
    full_url = response.urljoin(post_url)
    #meta參數(shù)對應(yīng)的是一個字典,用來傳遞數(shù)據(jù)
    yield scrapy.Request(url=full_url, meta={"front_image_url": image_url},
callback=self.parse_detail)

2.然后將我們得到的數(shù)據(jù)封裝到一個 JobboleItem 對象中蕉陋,可以保存每個文章的屬性:
def parse_detail(self,response):
    # print(response)
    # 使用xpath語法或者css語法提取網(wǎng)頁的相關(guān)信息
    # extract() 串行化并將匹配到的節(jié)點(diǎn)返回一個unicode字符串列表

    item = JobboleprojectItem()
    #標(biāo)題
    item['title'] = response.xpath('//div[@class="entry-header"]/h1/text()').extract_frist("")

    #發(fā)布日期
    item['create_date'] = response.xpath("http://p[@class='entry-meta-hide-on-mobile']/text()").extract_first("").strip().replace("·","").strip()
    #文章地址詳情地址
    item['url'] = response.url
    # http://blog.jobbole.com/113949/

    #文章的id
    item['url_object_id'] = re.match(".*?(\d+).*", url).group(1)

    # 文章圖片
    item['front_image_url'] = response.meta.get("front_image_url","")

    # 點(diǎn)贊數(shù)
    item['praise_nums'] = response.xpath("http://span[contains(@class,'vote-post-up')]/h10/text()").extract_first("")

    # 收藏?cái)?shù)
    bookmark_nums = response.xpath("http://span[contains(@class,'bookmark-btn')]/text()").extract_first("")
match_bookmark_nums = re.match(".*?(\d+).*",bookmark_nums)
    if match_bookmark_nums:
        item['bookmark_nums'] = int(match_bookmark_nums.group(1))
    else:
        item['bookmark_nums'] = 0

    # 評論數(shù)
    comment_nums = response.xpath("http://a[@href='#article-comment']/span/text()").extract_first("")
    match_comment_nums = re.match(".*?(\d+).*",comment_nums)
    if match_comment_nums:
        item['comment_nums'] = int(match_comment_nums.group(1))
    else:
        item['comment_nums'] = 0

    # 文章內(nèi)容
    item['content'] = response.xpath("http://div[@class='entry']").extract_first("")

    # 過濾評論標(biāo)簽
    tag_list = response.xpath("http://p[@class='entry-meta-hide-on-mobile']//a/text()").extract()
    tag_list = [element for element in tag_list if not element.strip().endswith("評論")]
    # 標(biāo)簽
    item['tags'] = ",".join(tag_list)

    print(item)

    # return返回?cái)?shù)據(jù)捐凭,不經(jīng)過pipelines
    # return item

    # yield將獲取的數(shù)據(jù)交給pipelines
    # yield item

簡單地講一下:
yield 的作用就是把一個函數(shù)變成一個 generator(生成器),帶有 yield 的函數(shù)不再是一個普通函數(shù)凳鬓,Python 解釋器會將其視為一個 generator茁肠。

四、編寫Item Pipeline

import something

class SomethingPipeline(object):
    def __init__(self):
        # 可選實(shí)現(xiàn)缩举,做參數(shù)初始化等
        # doing something
    def process_item(self, item, spider):
        # item (Item 對象) – 被爬取的item
        # spider (Spider 對象) – 爬取該item的spider
        # 這個方法必須實(shí)現(xiàn)垦梆,每個item pipeline組件都需要調(diào)用該方法,
        # 這個方法必須返回一個 Item 對象仅孩,被丟棄的item將不會被之后的pipeline組件所處理托猩。
        return item

    def open_spider(self, spider):
        # spider (Spider 對象) – 被開啟的spider
        # 可選實(shí)現(xiàn),當(dāng)spider被開啟時辽慕,這個方法被調(diào)用京腥。

    def close_spider(self, spider):
        # spider (Spider 對象) – 被關(guān)閉的spider
        # 可選實(shí)現(xiàn),當(dāng)spider被關(guān)閉時溅蛉,這個方法被調(diào)用

管道作用:
  • 驗(yàn)證爬取的數(shù)據(jù)(檢查item包含某些字段公浪,比如說name字段)

  • 查重(并丟棄)

  • 將爬取結(jié)果保存到文件或者數(shù)據(jù)庫中

五他宛、重新啟動爬蟲

scrapy crawl jobbole

六、Settings.py 設(shè)置文件參數(shù)介紹

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末欠气,一起剝皮案震驚了整個濱河市厅各,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌预柒,老刑警劉巖队塘,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異宜鸯,居然都是意外死亡憔古,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進(jìn)店門顾翼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來投放,“玉大人奈泪,你說我怎么就攤上這事适贸。” “怎么了涝桅?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵拜姿,是天一觀的道長。 經(jīng)常有香客問我冯遂,道長蕊肥,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任蛤肌,我火速辦了婚禮壁却,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘裸准。我一直安慰自己展东,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布炒俱。 她就那樣靜靜地躺著盐肃,像睡著了一般。 火紅的嫁衣襯著肌膚如雪权悟。 梳的紋絲不亂的頭發(fā)上砸王,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天,我揣著相機(jī)與錄音峦阁,去河邊找鬼谦铃。 笑死,一個胖子當(dāng)著我的面吹牛榔昔,可吹牛的內(nèi)容都是我干的驹闰。 我是一名探鬼主播凿跳,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼疮方!你這毒婦竟也來了控嗜?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤骡显,失蹤者是張志新(化名)和其女友劉穎疆栏,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體惫谤,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡壁顶,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了溜歪。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片若专。...
    茶點(diǎn)故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖蝴猪,靈堂內(nèi)的尸體忽然破棺而出调衰,到底是詐尸還是另有隱情,我是刑警寧澤自阱,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布嚎莉,位于F島的核電站,受9級特大地震影響沛豌,放射性物質(zhì)發(fā)生泄漏趋箩。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一加派、第九天 我趴在偏房一處隱蔽的房頂上張望叫确。 院中可真熱鬧,春花似錦芍锦、人聲如沸竹勉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽饶米。三九已至,卻和暖如春车胡,著一層夾襖步出監(jiān)牢的瞬間檬输,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工匈棘, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留丧慈,地道東北人。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像逃默,于是被迫代替她去往敵國和親鹃愤。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評論 2 354

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