抖音短視頻爬取實戰

需求

爬取用戶的抖音號、粉絲數、關注數、點贊數html

目的:

某公司作生鮮電商平臺,這個公司平臺想在流量平臺上投放廣告,發現抖音這個大平臺,python

抖音擁有不錯的用戶流量,經過數據分析預測在抖音投放公司廣告,看他是否會對公司利益帶來收益,這樣就要分析抖音數據,抖音的用戶畫像,判斷用戶羣體與公司的匹配度。android

那麼分析暱稱,粉絲書,關注書,和公司有什麼關係,經過分析能夠知道誰的粉絲忽然就增多了,誰的點贊數增多,那麼這個時候就能夠和廣告合做,拍廣告或者作營銷宣傳,或者根據點贊趨勢,能夠知道用戶喜歡的視頻,,這樣就能夠想辦法把公司產品融入到用戶喜歡的視頻中,公關公司根據數據,找到網紅黑馬,進行營銷包裝。web

 

 

三 粉絲數據接口

使用fiddler抓包數據庫

  https://aweme.snssdk.com/aweme/v1/user/follower/list/?user_id=105178085411&max_time=1556944953&count=20&offset=0&source_type=1&address_book_access=1&gps_access=1&retry_type=no_retry&iid=70850033498&device_id=67587886667&ac=wifi&channel=tengxun_new&aid=1128&app_name=aweme&version_code=600&version_name=6.0.0&device_platform=android&ssmix=a&device_type=SM-G955F&device_brand=samsung&language=zh&os_api=22&os_version=5.1.1&uuid=354730011196544&openudid=1c45444f5846a419&manifest_version_code=600&resolution=720*1280&dpi=240&update_version_code=6002&_rticket=1556944951543&mcc_mnc=46007&ts=1556944953&as=a115515c29b3bc480d4611&cp=1c3bc6579cd1ca83e1%5DcKg&mas=01f0b2caf2e5cf4c82c18f011cc8e22af58c8c6c2c260c1c2cc646

 

 

 

mitmproxy中間人代理

  發現請求頭中的加密數據太多,咱們換成了mitmproxy中間人代理的方式抓取數據包,並保存咱們須要的數據。json

 

粉絲請求urlbootstrap

https://aweme.snssdk.com/aweme/v1/user/follower/list/

 

 

編寫mitproxy處理響應體數據,代碼以下api

  def response(flow):
      if 'aweme/v1/user/follower/list/' in flow.request.url:
          with open('user.txt','w') as f:
              f.write(flow.response.text)

 

 

啓動 mitmdump服務器

 mitmdump -s decode_douyin_fans.py -p 8889

 

 

手機端或者模擬器端,設置好代理,啓動抖音刷粉絲頁面,生成txt文件,驗證,獲取的數據爲粉絲列表響應數據。app

 

 

數據清洗過程

 

 

入庫

mitmdump response攔截代碼

  import json
  from handle_db import mongo_info
  ​
  ​
  def response(flow):
      if 'aweme/v1/user/follower/list/' in flow.request.url:
          for user in json.loads(flow.response.text)['followers']:
              douyin_info={}
              douyin_info['share_id']=user['uid']
              douyin_info['douyin_id']=user['short_id']
              douyin_info['nickname']=user['nickname']
              mongo_info.save_task(douyin_info)
              # print(douyin_info)

 

 

handle_db.py數據庫操做代碼

 import pymongo
  ​
  class Connect_mongo(object):
      def __init__(self):
          #鏈接數據庫,若是沒有數據,則建立數據庫
          self.client=pymongo.MongoClient(host='106.12.108.236',port=27017)
          self.db=self.client['douyindb']
  ​
  ​
  ​
      def save_task(self,task):
          '保存粉絲信息'
          db_collection=self.db['douyin']
          #找到就更新,沒找到就新增
          db_collection.update({'share_id':task['share_id']},task,True)
  ​
      def handle_get_task(self):
          #獲取到數據,並刪除數據庫中的文檔
          return self.db['douyin'].find_one_and_delete({})
  ​
  ​
  mongo_info=Connect_mongo()

 

 

appium實現抖音app自動滑動實現粉絲數據包的處理

1 測試是否連通,代碼以下

  from appium import webdriver
  #等待元素加載
  from selenium.webdriver.support.ui import WebDriverWait
  ​
  #定義設備參數
  cap={
      "platformName": "Android",
      "platformVersion": "5.1.1",
      "deviceName": "127.0.0.1:62025",
      "appPackage": "com.ss.android.ugc.aweme",
      "appActivity": "com.ss.android.ugc.aweme.main.MainActivity",
      "noReset": True,
      'unicodekeyboard':True, #使用unicode輸入法
      'resetkeyboard':True, #還原輸入法
  }
  ​
  driver =webdriver.Remote('http://localhost:4723/wd/hub',cap)

 

 

2 連通後使用uiautomator viewer,獲取空間的id,xpath...表達式

註釋事項:抓取截屏數據的時候,必須等待數據加載完畢,或者把視頻暫停,不然報錯

此過程使用了appium和uiautomator viewer交替定位元素.

 

 

最終appium代碼,以下

  import time
  ​
  from appium import webdriver
  #等待元素加載
  from selenium.webdriver.support.ui import WebDriverWait
  ​
  #定義設備參數
  cap={
      "platformName": "Android",
      "platformVersion": "6.0.1",
      "deviceName": "758ca8ba",
      "appPackage": "com.ss.android.ugc.aweme",
      "appActivity": "com.ss.android.ugc.aweme.main.MainActivity",
      "noReset": True,
      'unicodekeyboard':True, #使用unicode輸入法
      'resetkeyboard':True, #還原輸入法
  }
  ​
  driver =webdriver.Remote('http://localhost:4723/wd/hub',cap)
  ​
  def get_size():
      #獲取設備屏幕大小
      x=driver.get_window_size()['width']
      y=driver.get_window_size()['height']
      return x,y
  ​
  #點擊搜索框
  try:
      if WebDriverWait(driver, 10).until(lambda x: x.find_element_by_id("com.ss.android.ugc.aweme:id/aqz")):
          driver.find_element_by_id("com.ss.android.ugc.aweme:id/aqz").click()
  except:
      pass#定位搜索框
  try:
      if WebDriverWait(driver, 10).until(lambda x: x.find_element_by_xpath(
              "//android.widget.EditText[@resource-id='com.ss.android.ugc.aweme:id/agq']")):
          driver.find_element_by_xpath(
              "//android.widget.EditText[@resource-id='com.ss.android.ugc.aweme:id/agq']").send_keys('191433445')
  except:
      pass#點擊搜索
  if WebDriverWait(driver,10).until(lambda x:x.find_element_by_xpath("//android.widget.TextView[@resource-id='com.ss.android.ugc.aweme:id/agt']")):
      driver.find_element_by_xpath("//android.widget.TextView[@resource-id='com.ss.android.ugc.aweme:id/agt']").click()
  ​
  #點擊用戶,進入我的主頁
  if WebDriverWait(driver,10).until(lambda x:x.find_element_by_xpath("/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout[2]/android.widget.RelativeLayout/android.widget.FrameLayout/android.widget.RelativeLayout/android.support.v4.view.ViewPager/android.widget.LinearLayout/android.widget.FrameLayout/android.view.ViewGroup/android.support.v7.widget.RecyclerView/android.widget.LinearLayout[1]/android.widget.LinearLayout[1]/android.support.v7.widget.RecyclerView/android.widget.RelativeLayout/android.widget.FrameLayout/android.widget.ImageView[2]")):
      el4 = driver.find_element_by_xpath("/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.FrameLayout[2]/android.widget.RelativeLayout/android.widget.FrameLayout/android.widget.RelativeLayout/android.support.v4.view.ViewPager/android.widget.LinearLayout/android.widget.FrameLayout/android.view.ViewGroup/android.support.v7.widget.RecyclerView/android.widget.LinearLayout[1]/android.widget.LinearLayout[1]/android.support.v7.widget.RecyclerView/android.widget.RelativeLayout/android.widget.FrameLayout/android.widget.ImageView[2]")
      el4.click()
  ​
  # 點擊粉絲
  if WebDriverWait(driver,10).until(lambda x:x.find_element_by_xpath("//android.widget.TextView[@text='粉絲']")):
      driver.find_element_by_xpath("//android.widget.TextView[@text='粉絲']").click()
  ​
  # 等待頁面刷新
  time.sleep(3)
  ​
  #開始滑動
  l =get_size()
  x1=int(l[0]*0.5)
  y1=int(l[1]*0.9)
  y2=int(l[1]*0.25)
  ​
  while True:
      if '沒有更多了' in driver.page_source:
          break
      else:
          #初始位置x1,y1   結束位置爲:x1,y2
          driver.swipe(x1,y1,x1,y2)
          time.sleep(0.2)
  ​

 

 

電腦開wifi給手機用,使用mitmdump開代理,有點坑,ip找這裏,我用的是網線!!!

 

 

代碼執行順序

1 啓動弄mitmproxy

  mitmdump -p 8889 -s decode_douyin_fans.py

 

2 啓動appnium程序,把粉絲信息入庫

  python handle_appium_douyin.py

 

3 執行採集分享id對應用戶的詳細信息,併入庫

  python handle_share_web.py

 

多任務端

 

 

注意事項

查找模擬器對應端口,找到對應的設備.

 

 

沒有粉絲處理

 

返回,清空,從新輸入

 

 

封裝兼容不一樣設備函數

 

 

啓動多進程

 

 

 

假裝爬蟲

 

 

抖音視頻下載

網頁源碼中找到加密js

 

 

請求參數分析 max_cursor

網頁中加的dytk

 

 

解密signature找尋流程

網頁張找到js加密文件,全局搜索(點擊右側三個點,或者ctrl +f)

 

 

繼續找

 

 

 

 

一層一層的找,找到全部的流程

 

找完以後,開始構建html文件和js文件

html 頭部文件

 

 

html尾部文件(複製調用的js函數到腳部文件)

 

 

使用文件合併的方法,生成html文件

 

 

每次打開生成的html 自動生成signature 祕鑰

 

 

js 破解思路:

  使用開發者工具,全局搜索加密字段所在的文件,理清楚加密過程,即執行流程,本身構建html文件,模擬加密執行函數,無需本身寫,只須要拷貝js代碼.

 

項目總結

我的數據 --TTF 字體混淆

 

 

fontedit解析字體,找到映射關係表

 

 

映射表,正則替換

 

 

粉絲數據抓取

appium模擬滑動+mitmdump解析數據

 

使用了uiautomator viewer和appium結合進行元素定位,進行元素的操做,使用mitmdump中間人攻擊技術,在請求分數數據的時候,把響應數據進行解析,入庫.

 

視頻抓取階段

編寫破解文件

 

 

注意:

1 ttf字體數據對應關係,若是關係更改了,爬蟲就須要作響應的更改.

2 通常一個名人最多獲取5000條粉絲數據

3 移動設備設置代理抓包後,若是沒法聯網或沒法解析https數據時候,須要安裝xpose框架+justtrustme組件進行屏蔽證書強校驗.

4 在設置多設備、多進程數據抓取時候,須要設置appium服務器端的bootstrap端口,以及客戶端的udid字段.

5 視頻數據抓取,須要破解signature字段,並使用html文件,解析js,

拼接html文件,逆退出加密過程.

6 數據抓取須要加上代理,假裝爬蟲.

7 最好使用真實的移動設備.
相關文章
相關標籤/搜索