犀光科技I基於scrapy-redis和anyproxy抓取app內容.md

2021-01-20 AI風向標

摘要

本文主要介紹一下犀光科技, 抓取系統中的數據採集模塊中的app採集部分,是基於scrapy-redis和anyproxy來實現的.

這裡只介紹比較簡單的一種場景:只要二次下載就可以抓取想要的內容,一次是下載列表頁,另一次是下次詳情頁.

基本架構圖

基本流程

用anyproxy截獲要抓取app的基本信息:請求url;請求頭;請求包體(如果有), 將這三個信息組包,並發到app_proxy服務app_proxy服務將收到的信息緩存:以供注入模塊查詢注入模塊,向app_proxy獲取到:請求url;請求頭;請求包體 打包注入到scrapy-redis的master隊列中scrapy-redis 將從隊列中獲取的:請求url;請求頭;請求包體 原封不動的發出去,基本上就可以拿到想要的信息,將下載到得信息,發到 app_parse_svr服務去解析,獲取格式化內容;如果是slave模塊,則將格式化內容輸出就可以了下面詳細介紹圖中的5個模塊

截獲必要信息模塊

anyproxy安裝,這個網上很多就不介紹了,可以參考這個地址這個主要是用nodejs實現一個截獲信息,並能將信息發送到app_proxy服務啟動anyproxy服務時,加載上面寫到的nodejs文件就可以了這個模塊,可以做成自動點擊,這樣就可以解決時效性的問題app_proxy模塊

此服務主要有二個接口,如下:

上報接口(report_message):POST 方法, 接收anyproxy截獲的信息,並保存

{ "token": "xxxx", #唯一標識 (必填) "url": "xxxxx", #請求URL(必填) "req_headers": "xxxx", #請求頭部,urlencode編碼(必填) "req_body": "xxxx" #請求包體urlencode編碼(可不填)}

提供查詢接口(query): Get 方法

參數: token=xxx返回結構:{ 'errno': 0, 'err_msg': 'success', 'data'}

注入模塊

這個主要是定時將要抓取的app信息,根據token從app_proxy服務中獲取信息,並將其打包成json結構,並壓入scrapy-redis隊列中,供其抓取。json結構如下:

{ "url": "xxxx", #列表頁url (必填) "headers": {}, # key-value 鍵值對 (必填) "body": "xxxx", # (可不填) "meta": { "shell_name": "xxx", #腳本文件名 (必填) "fun_name": "xxxx", #腳本函數名 (必填) ... } # key-value 鍵值對, 主要用來傳遞一些信息}

scrapy-redis模塊

此模塊基於master和slave實現的, master負責下載列表頁;slave 負責下載詳情頁.

原有的scrapy-redis,redis隊列中,只能放入url,不支持json結構,所以要改造一下,在spider目錄下,添加一個基類,假設名類叫CommSpider,maser和slave都繼承此基類, CommSpider基本定義如下:

# -*- coding:utf-8 -*-from scrapy.http import Requestfrom scrapy_redis.utils import bytes_to_strfrom scrapy_redis.spiders import RedisSpiderclass CommSpider(RedisSpider): def make_request_from_data(self, data): url, headers, body, meta = self.parse_redis_data(bytes_to_str(data, self.redis_encoding)) if url == '': #非json結構,按原來的邏輯處理 return self.make_requests_from_url(dec_data) else: # 將data,通過meta信息傳遞,以供下載完成時使用, 假設其key是 REDIS_DATA_GUID if body != '': return Request(url, method='POST', headers=headers, body=body.encode('utf-8'), meta={REDIS_DATA_GUID: data}, dont_filter=True) else: return Request(url, method='GET', headers=headers, meta={REDIS_DATA_GUID: data}, dont_filter=True) defparse_redis_data(self, data): #解析出url, headers, body和meta xxxxx return url, headers, body, meta

此模塊,只負責將內容下載下來, 不做具體的解析工作,所有解析工作都交由app_parse_svr來處理,具體的輸出內容master和slave是不同的.

mastermaster負責下載列表頁,並將從app_parse_svr獲取得格式化好的內容,解析出各個詳情頁,打包成json結構,壓入slave隊列中,master類簡單定義如下(這裡只寫一個大概的過程,不能運行的):

# -*- coding:utf-8 -*-import base64import tracebackimport jsonfrom .comm_spider import CommSpiderfrom ..log_handler import LogHandlerfrom ..settings import INFO, WARNING, ERRORfrom ..settings import MASTER_NAME, MASTER_KEY, REDIS_DATA_GUIDclassMaster(CommSpider):def__init__(self, *kargs, **kwargs): super(Master, self).__init__(*kargs, *kwargs) self._log_handler = LogHandler() name = MASTER_NAME redis_key = MASTER_KEY defparse(self, response):try: #1 獲取redis中的信息, 注意要將其base64解碼,這裡就寫個名字表示一下就好了 redis_info = decode_base64( response.meta[REDIS_DATA_GUID] if REDIS_DATA_GUID in response.meta else'') #2 解析出shell_name和fun_name#3 將shell_name, fun_name 和 response.text 傳遞給 app_parse_svr,讓其解析,並返回。#4 解析返回的內容,並將期打包成json格式壓入slave的redis隊列中 (這個結構在app_parse_svr模塊裡介紹)except Exception: traceback.print_exc()

slave 負責下載詳情頁內容, 並將從app_parse_svr獲取得格式化好的數據,輸出就可以了, 例如,可以輸出到kafka,做後續處理, slave類簡單定義如下:

# -*- coding:utf-8 -*-import tracebackimport jsonimport timefrom .comm_spider import CommSpiderfrom ..log_handler import LogHandlerfrom ..settings import SLAVE_NAME, SLAVE_KEY,REDIS_DATA_GUIDclassSlave(CommSpider):def__init__(self, *kargs, **kwargs): super(Slave, self).__init__(*kargs, *kwargs) self._log_handler = LogHandler() name = SLAVE_NAME redis_key = SLAVE_KEY defparse(self, response):try: #1 獲取redis中的信息, 注意要將其base64解碼,這裡就寫個名字表示一下就好了 redis_info = decode_base64( response.meta[REDIS_DATA_GUID] if REDIS_DATA_GUID in response.meta else'') #2 解析出shell_name、fun_name和ext#3 將shell_name、fun_name、ext 和 response.text 傳遞給 app_parse_svr,讓其解析,並返回。#4 解出ext,這個是格式化好的數據,輸出即可except Exception: traceback.print_exc()

app_parse_svr 模塊

此服務主要負責解析內容,並打包成指定的格式返回

此服務主要功能,就是可動態加載指定的解析腳本(我是用python來實現的), 解析指定的內容,這樣在增加新app時,只需按下面的格式增加一個腳本來解析和打包內容,完成後放到指定的目錄下就好了,服務無須改動,方便擴展.

請求包結構

{ "shell_name":"xxx", //腳本名字: 例 jrtt.py (必填) "parse_function":"xxxx", //解析函數名字 (必填) "content":"xxxx", //base64 編碼 (必填) "ext":{ //擴展項:主要用來傳項腳本必要信息,給腳本使用 (可不填) }}

響應包結構

列表頁:{ "errno":0, "errmsg":"success", "detail":[ { "next_url": "xxxx", //下一個解析的url (必填)"next_fun": "xxxx", //下一個解析內容的腳本函數(必填)"news_title": "xxxx", (可不填)"new_tags": "xxxxx", (可不填)... }, ..... ]}詳情頁:{ "errno":0, "errmsg":"success", "detail":{ "next_url": "xxxx", //下一個解析的url "next_fun": "xxxx", //下一個解析內容的腳本函數"ext":{ } }}註:如果"next_url"和"next_fun"為空,則表時是最終的詳情頁結果,ext 就是news的json格式

結尾

到這裡,此文就接近尾聲了,簡單總結一下: 此抓取總共由5個模塊組成,它們各司其職,並且每個模塊功能儘可能簡單,方便擴展。後續增加新app抓取,基本上只需增加一個解析腳本放到app_parser_svr服務指定的目錄下就可以了,其它的不需改動.

相關焦點

  • Python爬蟲:Scrapy-redis分布式爬蟲講解
    Github地址:https://github.com/rmax/scrapy-redis安裝:pip install scrapy-redisscrapy_redis在scrapy的基礎上實現了更多,更強大的功能,具體體現在:
  • python + appium + 模擬器 搭建app自動點擊系統
    摘要本文主要介紹犀光科技app自動控制系統的搭建,利用python腳本驅動appium從而控制模擬器中app的行為。adb.exe文件刪掉該目錄的nox_adb.exe文件,再複製一份adb.exe並重命名為nox_adb.exe啟動夜神模擬器再該目錄打開控制臺,執行nox_adb.exe connect 127.0.0.1:62001,然後執行adb devices,看到如下信息就表示成功了(注意:這一步很重要)appium配置 安裝完成後啟動appium,host和port
  • scrapy中scrapy_redis分布式內置pipeline源碼及其工作原理
    scrapy_redis分布式實現了一套自己的組件,其中也提供了Redis數據存儲的數據管道,位於scrapy_redis.pipelines,這篇文章主要分析器源碼及其工作流程,源碼如下:from scrapy.utils.misc import load_objectfrom scrapy.utils.serialize import ScrapyJSONEncoderfrom
  • 記錄微信公眾號歷史文章採集(一、Anyproxy)
    安裝AnyproxyAnyProxy是一個基於NodeJS的,可供插件配置的HTTP/HTTPS代理伺服器。使用npm安裝命令npm install -g anyproxy,這也是安裝Anyproxy第一個坑。
  • 犀光科技與微鯉看看深度合作,共同助力短視頻商業化變現
    而在內容生產帶來巨大能量的同時,怎樣將其進行商業化,是所有媒體一直在探尋的問題。北京微鯉科技有限公司旗下平臺微鯉看看是一個旨在打造創新型內容社區的平臺,深受廣大用戶的喜愛,有著豐富的媒體流量資源,但是在面對這樣巨大的流量的同時,也讓微鯉科技陷入了沉思:這麼巨大的流量,如何才能突破流量變現的瓶頸,實現最大化的商業變現。
  • Scrapy爬蟲框架結構介紹(各部分組件功能,常用命令)
    所以我們只需要定製開發幾個模塊就可以輕鬆的實現一個爬蟲,用來抓取網頁上的各種內容。Scrapy爬蟲的優點很多:內建的css選擇器和xpath表達式。基於IPython交互shell,方便編寫爬蟲和debug。
  • 使用爬蟲框架Scrapy抓取網頁數據(一):概述
    在無法隨時隨地接觸網絡的情況下,有時靠的就是笨辦法:將一些小說網站上的內容一頁頁的粘貼複製下來。而那些動輒幾百章節的網絡小說,靠這樣的手工操作,確實讓人非常頭疼。那時候是多麼希望有一個工具能幫我自動完成這些吃力的手工活啊!!!好吧,言歸正傳,最近在研究怎麼使用爬蟲框架Scrapy。先說說想要學習Scrapy的初衷吧。
  • python 爬蟲框架Scrapy使用方法
    一、安裝篇python3在安裝scrapy時,需要twisted的支持,但安裝twisted會需要visual studio的支持,詳見本人的另一文章Python 3.5 安裝scrapy無法找到vcvarsall.bat解決方案.
  • Redis 集群之Redis+Codis方案
    codis和redis cluster的區別:redis cluster基於smart client和無中心的設計,client必須按key的哈希將請求直接發送到對應的節點。這意味著:使用官方cluster必須要等對應語言的redis driver對cluster支持的開發和不斷成熟;client不能直接像單機一樣使用pipeline來提高效率,想同時執行多個請求來提速必須在client端自行實現異步邏輯。
  • 技術篇-使用Charles抓取電腦、APP、小程序請求
    簡單介紹Charles官網地址:https://www.charlesproxy.com/Charles的官網是這樣介紹自己的:Charles是HTTP代理/ HTTP監視器/反向代理,使開發人員可以查看其計算機與Internet之間的所有HTTP和SSL
  • python爬蟲小白——scrapy的使用
    本文中的知識點:安裝scrapyscrapy的基礎教程scrapy使用代理安裝scrapy以下的演示是基於windows系統,windows與linux都可以用。安裝好後,確認scrapy是否安裝spiders目錄——爬蟲代碼放這裡items.py ——要抓取的欄位middleware——中間件pipelines——管道文件settings——設置文件先不用管這麼細,我們先跑起來。代碼樣例抓個百度首頁試試吧。進入spiders目錄裡,創建個baidu的爬蟲,並且限制抓取域名的範圍。
  • 如何用Python和Scrapy將Web轉化為數據
    在這種情況下,我們只剩下使用web抓取來提取數據的可能性。基本上,每個web頁面都以HTML格式從伺服器返回。這意味著我們實際的數據被很好地打包在HTML元素中。它使得檢索特定數據的整個過程非常簡單和直接。本教程將是您學習使用Python程式語言進行web抓取的最終指南。首先,我將向您介紹一些基本示例,以使您熟悉web抓取。
  • Scrapy爬蟲庫快速入門
    Scrapy是一款網絡爬蟲框架,官方文檔的描述如下:Scrapy是一個為了爬取網站數據,提取結構性數據而編寫的應用框架。 可以應用在包括數據挖掘,信息處理或存儲歷史數據等一系列的程序中。下載完後,將whl文件拷貝到Python安裝目錄下,然後cmd進入到你的Python安裝目錄,運行pip3 install lxml-3.4.4-cp35-none-win32.whl然後運行:pip3 install scrapy在cmd中輸入scrapy,如果輸出版本信息並沒有報錯,
  • python爬蟲29 | 使用scrapy爬取糗事百科
    是時候給你說說爬蟲框架了使用框架來爬取數據會節省我們更多時間很快就能抓取到我們想要抓取的內容scrapy幫你自動生成了項目文件在這裡面有一些配置文件和預定義的設置文件是不是很方便咧接下來我們再來解析關鍵數據比如我們只需要段子的作者和段子的內容
  • 用python爬蟲框架scrapy抓取王者榮耀官網所有英雄信息
    工具:pycharm、python3.6、requests庫、scrapy庫和selenium、 PhantomJS庫目標url獲取:http://pvp./herolist.shtml裡有所有英雄的列表,抓包,並寫入函數分析網頁,先寫items.py,主要內容如下:Pipelines.py內容(最終文件為json格式):記得在settings.py裡面將ITEM_PIPELINES打開,並設置ROBOTSTXT_OBEY False(不打開不能保存文件,設置robotstxt是跳過網站ROBOT協議)
  • Spring AOP 用註解封裝 redis 緩存
    pre> * 指示方法的哪些參數用來構造key,及其順序(編號由0開始) * * 示例 * keyArgs = {1,0,2},表示用方法的第二,第一,第三個參數,按順序來構造key * * 默認值的意思是方法的前 n 個參數來構造key,n 最大為10 * 這樣如果構造 key 的參數不多於 10 個且順序也和方法參數一致