1. 程式人生 > >Scrapy網路爬蟲系列教程(二)| 提取網頁上的內容

Scrapy網路爬蟲系列教程(二)| 提取網頁上的內容

今天我們新建第一個爬蟲程式,爬取[伯樂線上]網站上一個網頁的內容。

建立專案

[按照上一篇文章所講的,你已經建好一個虛擬環境並安裝好了 scrapy]
首先,開啟控制檯,進入虛擬環境,輸入 scrapy startproject jobbole 新建一個名字為 jobbole 的專案。
輸入 tree/F jobbole 檢視檔案下的目錄結構。

│  scrapy.cfg
│
└─jobbole
    │  items.py
    │  middlewares.py
    │  pipelines.py
    │  settings.py
    │  __init__.py
│ ├─spiders │ │ __init__.py │ │ │ └─__pycache__ └─__pycache__

PyCharm 開啟該資料夾,並在 spider 資料夾下新建一個 Python File 檔案,取名為 jobbole_spider

在編寫程式之前,我們先分析一下所要抓取的網頁,登入伯樂線上網站,隨便開啟一篇文章:http://python.jobbole.com/89004/
我們要提取這個網頁的標題,釋出時間,標籤,評論數,點贊數等等。

提取資料

學習如何使用 Scrapy 提取資料的最好方法是嘗試使用 Scrapy shell

的選擇器。
在控制檯輸入 scrapy shell "http://python.jobbole.com/89004/"
會看到:

2018-02-11 14:10:26 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://python.jobbole.com/89004/> (referer: None)
[s] Available Scrapy objects:
[s]   scrapy     scrapy module (contains scrapy.Request, scrapy.Selector, etc)
[s]   crawler    <scrapy.crawler.Crawler object at 0x0000016D64CD9A90
> [s] item {} [s] request <GET http://python.jobbole.com/89004/> [s] response <200 http://python.jobbole.com/89004/> [s] settings <scrapy.settings.Settings object at 0x0000016D64CD9B70> [s] spider <DefaultSpider 'default' at 0x16d64f822b0> [s] Useful shortcuts: [s] fetch(url[, redirect=True]) Fetch URL and update local objects (by default, redirects are followed) [s] fetch(req) Fetch a scrapy.Request and update local objects [s] shelp() Shell help (print this help) [s] view(response) View response in a browser >>>

下面用響應物件使用 CSS 選擇元素:
提取標題,輸入:response.css(".type-post h1::text").extract_first()

>>> response.css(".type-post h1::text").extract_first()
'15 分鐘用 ML 破解一個驗證碼系統'

提取建立時間,輸入:response.css(".entry-meta-hide-on-mobile::text").extract_first().strip()[:-2]

>>> response.css(".entry-meta-hide-on-mobile::text").extract_first()
'\r\n\r\n            2018/01/29 ·  '
>>> response.css(".entry-meta-hide-on-mobile::text").extract_first().strip()
'2018/01/29 ·'
>>> response.css(".entry-meta-hide-on-mobile::text").extract_first().strip()[:-2]
'2018/01/29'

提取標籤,輸入:response.css(".entry-meta a::text").extract()

>>> response.css(".entry-meta a::text").extract()
['實踐專案', ' 1 評論 ', 'OpenCV', 'tensorflow', '機器學習']

提取點贊數,輸入:response.css(".vote-post-up h10::text").extract_first()

>>> response.css(".vote-post-up h10::text").extract_first()
'5'

提取收藏數,輸入:response.css(".bookmark-btn::text").extract_first()

>>> response.css(".bookmark-btn::text").extract_first()
' 12 收藏'

提取評論數,輸入response.css(".hide-on-480::text").extract()[-1]


>>> response.css(".hide-on-480::text").extract()[-1]
' 1 評論'

這裡需要說明的是,呼叫.extract()返回的是一個列表,而當你想返回列表中的第一個值,可以呼叫extract_first()

除了使用extract()extract_first()方法之外,還可以使用re()正則表示式進行提取頁面資訊。比如,對於收藏數和評論數,我們僅僅是想提取數字而已,所以得把上面抓取到的內容進行正則匹配。

        fav_nums = response.css(".bookmark-btn::text").extract_first()
        match_re = re.match(".*?(\d+).*", fav_nums)
        if match_re:
            fav_nums = match_re.group(1)

        comment_nums = response.css(".hide-on-480::text").extract()[-1]
        match_re = re.match(".*?(\d+).*", comment_nums)
        if match_re:
            comment_nums = match_re.group(1)

當我們提取標籤的時,發現其中['實踐專案', ' 1 評論 ', 'OpenCV', 'tensorflow', '機器學習']還有1 評論,這並不是我們希望看到的,所以我們得用正則匹配把無用的資訊剔除掉。

        tag_list = response.css(".entry-meta a::text").extract()
        tag_list = [element for element in tag_list if not element.strip().endswith("評論")]
        tags = ",".join(tag_list)

到此為止,我們的程式程式碼就已經分析完成了。
主要程式碼:

import scrapy
import re

class jobboleSpider(scrapy.Spider):

    name = "jobbole_spider"

    start_urls = ['http://python.jobbole.com/89004/']


    def parse(self, response):
        fav_nums = response.css(".bookmark-btn::text").extract_first()
        match_re = re.match(".*?(\d+).*", fav_nums)
        if match_re:
            fav_nums = match_re.group(1)

        comment_nums = response.css(".hide-on-480::text").extract()[-1]
        match_re = re.match(".*?(\d+).*", comment_nums)
        if match_re:
            comment_nums = match_re.group(1)

        tag_list = response.css(".entry-meta a::text").extract()
        tag_list = [element for element in tag_list if not element.strip().endswith("評論")]
        tags = ",".join(tag_list)

        for quote in response.css(".grid-8"):
            yield{
                'title': quote.css(".type-post h1::text").extract_first(),
                'create_data': quote.css(".entry-meta-hide-on-mobile::text").extract_first().strip()[:-2],
                'tags': tags,
                'praise_nums': quote.css(".vote-post-up h10::text").extract_first(),
                'fav_nums': fav_nums,
                'comment_nums': comment_nums,
            }

另外,要想在PyCharm上執行此程式,還需要新建一個main.py函式

import os
import sys
from scrapy.cmdline import execute

sys.path.append(os.path.dirname(os.path.abspath(__file__)))
execute(["scrapy", "crawl", "jobbole_spider"])

執行main.py函式,得到執行結果。

2018-02-11 15:31:57 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://python.jobbole.com/robots.txt> (referer: None)
2018-02-11 15:31:57 [scrapy.core.engine] DEBUG: Crawled (200) <GET http://python.jobbole.com/89004/> (referer: None)
2018-02-11 15:31:58 [scrapy.core.scraper] DEBUG: Scraped from <200 http://python.jobbole.com/89004/>
{'title': '15 分鐘用 ML 破解一個驗證碼系統', 'create_data': '2018/01/29', 'tags': '實踐專案,OpenCV,tensorflow,機器學習', 'praise_nums': '5', 'fav_nums': '13', 'comment_nums': '1'}
2018-02-11 15:31:58 [scrapy.core.engine] INFO: Closing spider (finished)

感興趣的朋友可以自己抓取網頁上的正文內容。
歡迎關注我的個人公眾號。