基于python3的百度網盤爬蟲

為了更熟練掌握面向對象泊脐,用面向對象編程寫了百度網盤的爬蟲,爬蟲部分都已完工烁峭,使用python3容客。自己在本機跑了快一個小時,目測效率還行约郁。如果要部署使用缩挑,需要自己補充入庫以及uk去重,因為老的網盤爬蟲(使用代理采集)還能工作鬓梅,就懶得去寫入庫和去重以及資源過濾部分了供置,等哪天老的爬蟲不能用了,再來把這個補充完整绽快。
更新:補充流程圖

Paste_Image.png
改進
  • uk去重簡單實現(xiàn):uk從隊列之中取出后芥丧,直接存入數(shù)據(jù)庫,已存在就跳過采集坊罢。
  • 資源入庫:把打印方法替換成數(shù)據(jù)庫插入就好续担。
  • 單機綁定不同本地ip多開或者綁定不同代理ip多開,雖然之前使用過socket bind本地ip多開其它爬蟲活孩,但是感覺還是使用代理ip更好物遇,本地多ip也可以使用nginx做代理服務器,這樣更通用一點憾儒。
  • 當前從某個用戶獲取fans_list之后询兴,程序會自動采集,加入數(shù)據(jù)庫之后起趾,可以考慮將多余的uk存入數(shù)據(jù)庫(uk爬取要比資源爬取快)蕉朵,之后直接從數(shù)據(jù)庫取未采集的uk列表初始化采集

當前采集到的數(shù)據(jù)直接輸出到了控制臺

Paste_Image.png

# -*- coding: utf-8 -*-
# Copyright (c) 2017 - walker <cail1844@gmail.com>

#  定義了用戶和資源類型
#  定義了FollowList和FansList類
# 分離了download url的過程,帶數(shù)據(jù)驗證
# 分離了主線程阳掐,實現(xiàn)資源調度
# loggging記錄日志始衅,存放當前目錄下
# 最簡數(shù)據(jù),僅保留構成wap分享鏈接的uk,shareid以及文件名
import requests
from queue import Queue
import time
import json
import re
import random
#import pymysql
import logging
from threading import Thread

logging.basicConfig(handlers=[logging.FileHandler('baiduyunwap.log','w','utf-8')],level=logging.WARNING)

class UKItem:
    'define UK class'
    def __init__(self,uk=None,fans=None,follow=None,pubshare=None):
        self.uk = uk
        self.fans = fans
        self.follow = follow
        self.pubshare = pubshare

    def existed(self):
        'check in mysql'
        self.history = False

    def put_uk(self,item,uk_queue):
        if 'fans_uk' in item.keys():
            self.uk = item['fans_uk']
        else:
            self.uk = item['follow_uk']
        self.fans = item['fans_count']
        self.follow = item['follow_count']
        self.pubshare = item['pubshare_count']
        uk_queue.put(self)

class BDRecord:
    'define Baidu Yun Record'
    def __init__(self,title=None,uk=None,shareid=None):
        self.title = title
        self.uk = uk
        self.shareid = shareid

    def put_file(self,item,file_queue):
        self.title = item['title']
        self.uk = item['uk']
        if item['feed_type'] == 'share':
            self.shareid = item['shareid']
            file_queue.put(self)

class FollowList:
    'get uk list from user follow list'
    pass
    def __init__(self, uk, uk_queue):
        self.uk = uk
        self.baseurl = "https://pan.baidu.com/pcloud/friend/getfollowlist?query_uk=%s&limit=24&start=%s&bdstoken=&channel=chunlei&clienttype=0&web=1"
        self.uk_queue = uk_queue

    def get_uk(self,start):
        url = self.baseurl % (self.uk,start)
        dic = Request(url).content_from_url()
        if dic and 'follow_list' in dic.keys():
            for item in dic['follow_list']:
                u = UKItem()
                u.put_uk(item,self.uk_queue)
        if dic and start == 0:
            return dic['total_count']
        else:
            return 0

    def page_uk(self,start=0):
        count = self.get_uk(start)
        while count > start + 24:
            time.sleep(2.1)
            start += 24
            self.get_uk(start)

class FansList():
    'get uk from user fanslist'
    def __init__(self, uk, uk_queue):
        self.uk = uk
        self.baseurl = "https://pan.baidu.com/pcloud/friend/getfanslist?query_uk=%s&limit=24&start=%s&channel=chunlei&clienttype=0&web=1"
        self.uk_queue = uk_queue

    def get_uk(self,start):
        url = self.baseurl % (self.uk,start)
        dic = Request(url).content_from_url()
        if dic and 'fans_list' in dic.keys():
            # print(dic['fans_list'])
            for item in dic['fans_list']:
                u = UKItem()
                u.put_uk(item,self.uk_queue)
        if dic and start == 0:
            return dic['total_count']
        else:
            return 0


    def page_uk(self,start=0):
        count = self.get_uk(start)
        while count > start + 24:
            time.sleep(2.1)
            start += 24
            self.get_uk(start)

class FileList:
    'get file from user pubshare list, from wap page'
    def __init__(self, uk, file_queue):
        self.uk = uk
        self.baseurl = "http://pan.baidu.com/wap/share/home?uk=%s&start=%s&adapt=pc&fr=ftw"
        self.file_queue = file_queue

    def get_file(self,start):
        url = self.baseurl % (self.uk, start)
        dic = Request(url).content_from_url()
        if dic and 'feedata' in dic.keys():
            for item in dic['feedata']['records']:
                f = BDRecord()
                f.put_file(item,self.file_queue)
        if dic and start == 0:
            # try:
            return dic['feedata']['total_count']
            # except:
            #     print('file dic',dic)
        else:
            # print('file dic',dic)
            return 0

    def page_file(self,start=0):
        count = self.get_file(start)
        while count > start + 20:
            start += 20
            time.sleep(2.1)
            self.get_file(start)

class Request:
    'download the html and json'
    def __init__(self,url):
        self.url = url
    uk_list_reg = re.compile(r'friend')
    file_reg = re.compile(r'wap')
    file_content_reg = re.compile(r'window\.yunData = (.*?)\;')
    file_fast_reg = re.compile(r'<title>頁面不存在</title>')
    uaList = [
    'Mozilla/5.0 (Linux; Android 4.0.3; M031 Build/IML74K) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Mobile Safari/535.19',
    'Mozilla/5.0 (Linux; U; Android 4.0; en-us; GT-I9300 Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30',
    'Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1',
    'Mozilla/5.0 (Linux; U; Android 4.1.1; zh-CN; M040 Build/JRO03H) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 UCBrowser/9.4.1.362 U3/0.8.0 Mobile Safari/533.1'
]
    ua = random.choice(uaList)
    ref = 'https://yun.baidu.com/share/home?uk=4726647#category/type=0'
    headers = {'User-Agent': ua,'Referer':ref}

    def content_from_url(self):
        try:
            r = requests.get(self.url,headers=self.headers,timeout=15)
            r.encoding = 'utf8'
        except Exception as e:
            logging.warning('[Request.content_from_url1] requests error {%s}' % e)
            return False
        try:
            if Request.uk_list_reg.search(self.url):
                data =  r.json()
                data = self.verify(data)
            elif Request.file_reg.search(self.url):
                html =  r.text
                html = self.verify(html)
                j = Request.file_content_reg.search(html).group(1)
                data = json.loads(j)
            else:
                data = r.text
        except Exception as e:
            logging.warning('[Request.content_from_url2] data error {%s} [%s] \n %s' %(e,self.url,r.text))
            data = False
        return data

    def verify(self,data):
        if Request.uk_list_reg.search(self.url) and ('error_msg' in data.keys() or data['errno'] != 0):
            print('sleep 36',self.url,time.localtime())
            logging.warning('[Request.verify] verify file data,get bad data,sleep 120s')
            logging.warning(self.url)
            logging.warning(data)
            time.sleep(120)
            data = False
        elif Request.file_reg.search(self.url) and Request.file_fast_reg.search(data):
            print('sleep 36',self.url,time.localtime())
            logging.warning('[Request.verify] verify file data,get bad data,sleep 36s')
            logging.warning(self.url)
            logging.warning(data)
            time.sleep(36)
            data = False
        else:
            data = data
        return data

class Main(Thread):
    'multiple thread main func'
    uk_queue = Queue()
    fans_follow = Queue()
    follow_queue = Queue()
    pubshare_queue = Queue()
    file_queue =Queue()

    def __init__(self):
        Thread.__init__(self)
        print("start Main Thread")

    def run(self):
        print("start run func")
        Thread(target=self.parse_uk).start()
        Thread(target=self.parse_fans_follow).start()
        Thread(target=self.parse_file).start()
        Thread(target=self.show_info).start()

    def parse_uk(self):
        while True:
            uk = Main.uk_queue.get()
            if bool(uk.fans) and uk.fans >= 25:
                Main.fans_follow.put({'uk':uk.uk,'type':'fans'})
            if bool(uk.follow) and uk.follow >= 10:
                Main.fans_follow.put({'uk':uk.uk,'type':'follow'})
            if bool(uk.pubshare) and uk.pubshare >=10 :
                Main.pubshare_queue.put(uk.uk)

    def parse_fans_follow(self):
        while True:
            user = Main.fans_follow.get()
            if user['type'] == 'fans':
                FansList(user['uk'],Main.uk_queue).page_uk()
            else:
                FollowList(user['uk'],Main.uk_queue).page_uk()

    def parse_file(self):
        while True:
            uk = Main.pubshare_queue.get()
            pubshare = Main.pubshare_queue.get()
            FileList(uk,Main.file_queue).page_file()

    def show_info(self):
        while True:
            print('show info:', 'uk:%s  fans and follow:%s  pubshare:%s  file:%s' %(Main.uk_queue.qsize(),Main.fans_follow.qsize(),Main.pubshare_queue.qsize(),Main.file_queue.qsize()))
            logging.warning('uk:%s  fans and follow:%s  pubshare:%s  file:%s' %(Main.uk_queue.qsize(),Main.fans_follow.qsize(),Main.pubshare_queue.qsize(),Main.file_queue.qsize()))
            time.sleep(30)

if __name__ == '__main__':
    t = Main()
    FollowList('675131233',t.uk_queue).page_uk()
    t.start()
    t.join()
    while True:
        f = t.file_queue.get()
        print(f.title,f.uk,f.shareid)
    print('end')
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末缭保,一起剝皮案震驚了整個濱河市汛闸,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌艺骂,老刑警劉巖诸老,帶你破解...
    沈念sama閱讀 221,695評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異钳恕,居然都是意外死亡别伏,警方通過查閱死者的電腦和手機蹄衷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來厘肮,“玉大人愧口,你說我怎么就攤上這事±嗝” “怎么了耍属?”我有些...
    開封第一講書人閱讀 168,130評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長巩检。 經常有香客問我厚骗,道長,這世上最難降的妖魔是什么兢哭? 我笑而不...
    開封第一講書人閱讀 59,648評論 1 297
  • 正文 為了忘掉前任领舰,我火速辦了婚禮,結果婚禮上迟螺,老公的妹妹穿的比我還像新娘提揍。我一直安慰自己,他們只是感情好煮仇,可當我...
    茶點故事閱讀 68,655評論 6 397
  • 文/花漫 我一把揭開白布劳跃。 她就那樣靜靜地躺著,像睡著了一般浙垫。 火紅的嫁衣襯著肌膚如雪刨仑。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,268評論 1 309
  • 那天夹姥,我揣著相機與錄音杉武,去河邊找鬼。 笑死辙售,一個胖子當著我的面吹牛轻抱,可吹牛的內容都是我干的。 我是一名探鬼主播旦部,決...
    沈念sama閱讀 40,835評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼祈搜,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了士八?” 一聲冷哼從身側響起容燕,我...
    開封第一講書人閱讀 39,740評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎婚度,沒想到半個月后蘸秘,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 46,286評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,375評論 3 340
  • 正文 我和宋清朗相戀三年醋虏,在試婚紗的時候發(fā)現(xiàn)自己被綠了寻咒。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,505評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡颈嚼,死狀恐怖毛秘,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情粘舟,我是刑警寧澤,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布佩研,位于F島的核電站柑肴,受9級特大地震影響,放射性物質發(fā)生泄漏旬薯。R本人自食惡果不足惜晰骑,卻給世界環(huán)境...
    茶點故事閱讀 41,873評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望绊序。 院中可真熱鬧硕舆,春花似錦、人聲如沸骤公。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽阶捆。三九已至凌节,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間洒试,已是汗流浹背倍奢。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留垒棋,地道東北人卒煞。 一個月前我還...
    沈念sama閱讀 48,921評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像叼架,于是被迫代替她去往敵國和親畔裕。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,515評論 2 359

推薦閱讀更多精彩內容