爬蟲爬 JSON HTML 數據

最近這兩週在忙着給公司爬一點數據,更文的速度有一點降低,預計今天就爬完了,總結總結經驗。css

其實以前我司是有專門作爬蟲的,不用前端這邊出人幹活。後來那人離職了,有可能就沒有爬蟲這方面的需求了。忽然又有了一些,前端這邊出人作一下。老大說用 py 作,前期先調研一下。html

原理

爬蟲其實原理上很簡單,咱們==客戶端他們==服務端
客戶端發送請求 req,服務端返回響應 rsp。拿到響應以後解析數據,入庫,就完事了。前端

請求數據 req

通常來講請求分爲兩種,拉數據 get 比較多。
偶爾部分接口須要登陸,那就是多帶 cookie 或者 headers
其實還有一部分工做就是分析入參vue

  1. get
    參數拼接在 url
  2. post
    參數放在 body

響應數據 rsp

返回數據大致上是兩種python

  1. JSON
    通常來講,經過 抓包 或者說 network 工具。咱們找到了服務端的接口,那麼我直接訪問這個接口便可。
    本文第一個重點來了:切換到移動端再查一遍,每每有不同的收穫,通常來講 PCM 端的進度不了,有可能都不是一個項目組,因此實現方式就會有差異。
  2. html
    比較坑的一種方式,由於沒有找到 JSON 接口。無奈只能走解析 HTML 的路子。

調研

  1. Node
    以前給後臺搭架子的時候使用過,主要功能點以下:mysql

    1. 自動登陸,(拿headers、cookie
    2. 存儲本地,每次請求帶上 token
    3. 啓動代理服務
  2. py 老大說要用這個東西。諮詢了一下其餘朋友,說可使用下面的工具。sql

    1. requests + beautifulSoup
      使用起來其實就是 requests 發請求, beautifulSoup 解析 HTML。比較原始。
    2. scrapy
      一個爬蟲的框架。我在這裏學的 www.scrapyd.cn。實現上比較完整,能夠設置請求間隔,隨機 ua 等功能。
  3. 前端實現
    我一個鐵頭娃,怎麼能輕言放棄?身爲一個前端er,仍是這些 api 讓我更加親切數據庫

    1. XHR
      發請求利器,打開對方頁面,cookie 啥的都自帶。無敵就是這麼寂寞
      其實還能夠找到對方請求發起的位置,打個斷點,把對方內部的代碼綁定到全局,這樣一些內部邏輯什麼的也都沒問題。
      並且還 JSON HTML 通吃。
    2. iframe
      針對 HTML 類型的處理。同域的狀況下,也無敵好嗎?json

      1. HTML 獲取 DOM 節點?
      2. 甚至能夠取 window 上的對象。vue SSR 你感受到了威脅嗎?
  4. 網上其餘服務商提供的接口(真香啊)。有免費的有收費的,通常免費的限量。網頁爬蟲

    1. 好比抖音熱度?
    2. 好比各種音樂的歌單和做品?
    3. IP 查詢
    4. 天氣查詢

好了上面說了那麼多,建議老大限制,我選擇了 scrapy

scrapy

scrapy 是一個網頁爬蟲框架,神馬叫作爬蟲,若是沒據說過,那就:內事不知問度娘,外事不決問谷歌,百度或谷歌一下吧!……(這裏的省略號表明 scrapy 很牛逼,基本神馬都能爬,包括你喜歡的蒼老師……這裏就不翻譯了)

看到這個騷的飛起的介紹了嗎?沒錯,我就是在上面學的。scrapy 中文站。接下來我就介紹一下我認爲對於新手比較關注的東西

scrapy HTML

scrapy 處理器中的 response 標識你拿到的 rsp 上面自帶了一些方法,通常來講須要關注的只有兩個

css 選擇器

quote.css('span.text::text').extract_first() 中的 'span.text::text'眼熟嗎?
沒錯,就是咱們經常使用的選擇器。經過這個 api,咱們能夠把咱們想要的數據,限時在一個很小的範圍,而後拿字符串便可。
啥?你說你不會 css 選擇器?前端培訓-初級階段(5 - 8)-CSS選擇器(基本、層級、屬性、僞類、僞狀態)

  1. extract() 函數提取列表
  2. extract_first() 表明提取第一個元素。基本等價於 extract()[0]
  3. ::text 選擇其中的文字
  4. ::attr(href) 提取屬性

xpath

quote.xpath('span/small/text()').extract_first()
文檔,這個我不會,我也沒看

scrapy JSON

import json 使用這個類庫解析如:json.loads(response.body.decode('utf-8'))

scrapy 請求方式

get

import urllib 能夠用來給中文字符 encode

yield scrapy.FormRequest(
    url, 
    method = 'GET', 
    headers = self.headers, 
    formdata={}, 
    callback = self.parse_list, 
    dont_filter = True, 
    meta = {
        'offset': 0,
    })

post

數據放入 formdata 傳遞便可。

yield scrapy.FormRequest(
    url, 
    method = 'POST', 
    headers = self.headers, 
    formdata={}, 
    callback = self.parse_list, 
    dont_filter = True, 
    meta = {
        'offset': 0,
    })

給回調模塊帶參數

meta = {
        'offset': 0,
    }

以下方式接收

disstid = response.meta['offset']

外部傳參方式

scrapy crawl argsSpider -a tag=愛情
內部是使用以下命令能夠接收到。

def start_requests(self):
        url = 'http://lab.scrapyd.cn/'
        tag = getattr(self, 'tag', None)  # 獲取tag值,也就是爬取時傳過來的參數

scrapy mysql

大數據那邊說爬回來的數據要入庫。

  1. scrapyMysql/scrapyMysql/items.py 編寫對應入庫字段。

    import scrapy
    
    class ScrapymysqlItem(scrapy.Item):
        # define the fields for your item here like:
        # name = scrapy.Field()
        tag = scrapy.Field()  # 標籤字段
        cont = scrapy.Field()  # 名言內容
        pass
  2. scrapyMysql/scrapyMysql/spiders/inputMysql.py 寫爬蟲處理操做時,入庫

    item = ScrapymysqlItem()  # 實例化item類
        for v in mingyan:  # 循環獲取每一條名言裏面的:名言內容、做者、標籤
            item['cont'] = v.css('.text::text').extract_first()  # 提取名言
            tags = v.css('.tags .tag::text').extract()  # 提取標籤
            item['tag'] = ','.join(tags)  # 數組轉換爲字符串
            yield item  # 把取到的數據提交給pipline處理
  3. 編寫MySQL存儲插件:MySQLPipeline.py

    import pymysql.cursors
    class MySQLPipeline(object):
        def __init__(self):
            # 鏈接數據庫
            self.connect = pymysql.connect(
                host='127.0.0.1',  # 數據庫地址
                port=3306,  # 數據庫端口
                db='scrapyMysql',  # 數據庫名
                user='root',  # 數據庫用戶名
                passwd='root',  # 數據庫密碼
                charset='utf8',  # 編碼方式
                use_unicode=True)
            # 經過cursor執行增刪查改
            self.cursor = self.connect.cursor()
    
        def process_item(self, item, spider):
            self.cursor.execute(
                """insert into mingyan(tag, cont)
                value (%s, %s)""",  # 純屬python操做mysql知識,不熟悉請惡補
                (item['tag'],  # item裏面定義的字段和表字段對應
                 item['cont'],))
            # 提交sql語句
            self.connect.commit()
            return item  # 必須實現返回
  4. settings啓動MySQLPipline組件

    ITEM_PIPELINES = {
       'scrapyMysql.MySQLPipline.MySQLPipeline': 300,
    }

總結一下

到如今,咱們已經完成了全部基礎知識的積累。遇到不會咱們去裏看?
總結一下須要注意點的

  1. 切換 PC 和 M 端,尋找可行的方案
  2. 注意節制(部分容易限量)
  3. python 編碼問題(真的好煩)
  4. 網上提供的那個 mysql 庫和個人不合,我換了一個MySQLdb
  5. 第三方的接口是真香

微信公衆號

clipboard.png

相關文章
相關標籤/搜索