爬取用戶的抖音號、粉絲數、關注數、點贊數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中間人代理的方式抓取數據包,並保存咱們須要的數據。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()
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
網頁張找到js加密文件,全局搜索(點擊右側三個點,或者ctrl +f)
繼續找
一層一層的找,找到全部的流程
html 頭部文件
html尾部文件(複製調用的js函數到腳部文件)
使用文件合併的方法,生成html文件
每次打開生成的html 自動生成signature 祕鑰
使用開發者工具,全局搜索加密字段所在的文件,理清楚加密過程,即執行流程,本身構建html文件,模擬加密執行函數,無需本身寫,只須要拷貝js代碼.
fontedit解析字體,找到映射關係表
映射表,正則替換
使用了uiautomator viewer和appium結合進行元素定位,進行元素的操做,使用mitmdump中間人攻擊技術,在請求分數數據的時候,把響應數據進行解析,入庫.
編寫破解文件
注意:
1 ttf字體數據對應關係,若是關係更改了,爬蟲就須要作響應的更改. 2 通常一個名人最多獲取5000條粉絲數據 3 移動設備設置代理抓包後,若是沒法聯網或沒法解析https數據時候,須要安裝xpose框架+justtrustme組件進行屏蔽證書強校驗. 4 在設置多設備、多進程數據抓取時候,須要設置appium服務器端的bootstrap端口,以及客戶端的udid字段. 5 視頻數據抓取,須要破解signature字段,並使用html文件,解析js, 拼接html文件,逆退出加密過程. 6 數據抓取須要加上代理,假裝爬蟲. 7 最好使用真實的移動設備.