天天看點

再見爬蟲,全靠這個爬蟲工具!

最近國内一位開發者在 GitHub 上開源了個集衆多資料源于一身的爬蟲工具箱——InfoSpider,一不小心就火了!!!

再見爬蟲,全靠這個爬蟲工具!

有多火呢?開源沒幾天就登上GitHub周榜第四,标星1.3K,累計分支 172 個。同時作者已經開源了所有的項目代碼及使用文檔,并且在B站上還有使用視訊講解。

項目代碼: 

https://github.com/kangvcar/InfoSpider 

項目使用文檔:

https://infospider.vercel.app 

項目視訊示範:

https://www.bilibili.com/video/BV14f4y1R7oF/

在這樣一個資訊爆炸的時代,每個人都有很多個賬号,賬号一多就會出現這麼一個情況:個人資料分散在各種各樣的公司之間,就會形成資料孤島,多元資料無法融合,這個項目可以幫你将多元資料進行融合并對個人資料進行分析,這樣你就可以更直覺、深入了解自己的資訊。

InfoSpider 是一個集衆多資料源于一身的爬蟲工具箱,旨在安全快捷的幫助使用者拿回自己的資料,工具代碼開源,流程透明。并提供資料分析功能,基于使用者資料生成圖表檔案,使得使用者更直覺、深入了解自己的資訊。 

再見爬蟲,全靠這個爬蟲工具!

目前支援資料源包括GitHub、QQ郵箱、網易郵箱、阿裡郵箱、新浪郵箱、Hotmail郵箱、Outlook郵箱、京東、淘寶、支付寶、中國移動、中國聯通、中國電信、知乎、哔哩哔哩、網易雲音樂、QQ好友、QQ群、生成朋友圈相冊、浏覽器浏覽曆史、12306、部落格園、CSDN部落格、開源中國部落格、簡書。

根據建立者介紹,InfoSpider 具有以下特性:

  • 安全可靠:本項目為開源項目,代碼簡潔,所有源碼可見,本地運作,安全可靠。
  • 使用簡單:提供 GUI 界面,隻需點選所需擷取的資料源并根據提示操作即可。
  • 結構清晰:本項目的所有資料源互相獨立,可移植性高,所有爬蟲腳本在項目的 Spiders 檔案下。
  • 資料源豐富:本項目目前支援多達24+個資料源,持續更新。
  • 資料格式統一:爬取的所有資料都将存儲為json格式,友善後期資料分析。
  • 個人資料豐富:本項目将盡可能多地為你爬取個人資料,後期資料處理可根據需要删減。
  • 資料分析:本項目提供個人資料的可視化分析,目前僅部分支援。

InfoSpider使用起來也非常簡單,你隻需要安裝python3和Chrome浏覽器,運作 python3 main.py,在打開的視窗點選資料源按鈕, 根據提示選擇資料儲存路徑,接着輸入賬号密碼,就會自動爬取資料,根據下載下傳的目錄就可以檢視爬下來的資料。

當然如果你想自己去練習和學習爬蟲,作者也開源了所有的爬取代碼,非常适合實戰。

再見爬蟲,全靠這個爬蟲工具!

舉個例子,比如爬取taobao的:

import json
import random
import time
import sys
import os
import requests
import numpy as np
import math
from lxml import etree
from pyquery import PyQuery as pq
from selenium import webdriver
from selenium.webdriver import ChromeOptions
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver import ChromeOptions, ActionChains
from tkinter.filedialog import askdirectory
from tqdm import trange


def ease_out_quad(x):
    return 1 - (1 - x) * (1 - x)

def ease_out_quart(x):
    return 1 - pow(1 - x, 4)

def ease_out_expo(x):
    if x == 1:
        return 1
    else:
        return 1 - pow(2, -10 * x)

def get_tracks(distance, seconds, ease_func):
    tracks = [0]
    offsets = [0]
    for t in np.arange(0.0, seconds, 0.1):
        ease = globals()[ease_func]
        offset = round(ease(t / seconds) * distance)
        tracks.append(offset - offsets[-1])
        offsets.append(offset)
    return offsets, tracks

def drag_and_drop(browser, offset=26.5):
    knob = browser.find_element_by_id('nc_1_n1z')
    offsets, tracks = get_tracks(offset, 12, 'ease_out_expo')
    ActionChains(browser).click_and_hold(knob).perform()
    for x in tracks:
        ActionChains(browser).move_by_offset(x, 0).perform()
    ActionChains(browser).pause(0.5).release().perform()

def gen_session(cookie):
    session = requests.session()
    cookie_dict = {}
    list = cookie.split(';')
    for i in list:
        try:
            cookie_dict[i.split('=')[0]] = i.split('=')[1]
        except IndexError:
            cookie_dict[''] = i
    requests.utils.add_dict_to_cookiejar(session.cookies, cookie_dict)
    return session

class TaobaoSpider(object):
    def __init__(self, cookies_list):
        self.path = askdirectory(title='選擇資訊儲存檔案夾')
        if str(self.path) == "":
            sys.exit(1)
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36',
        }
        option = ChromeOptions()
        option.add_experimental_option('excludeSwitches', ['enable-automation'])
        option.add_experimental_option("prefs", {"profile.managed_default_content_settings.images": 2})  # 不加載圖檔,加快通路速度
        option.add_argument('--headless')
        self.driver = webdriver.Chrome(options=option)
        self.driver.get('https://i.taobao.com/my_taobao.htm')
        for i in cookies_list:
            self.driver.add_cookie(cookie_dict=i)
        self.driver.get('https://i.taobao.com/my_taobao.htm')
        self.wait = WebDriverWait(self.driver, 20)  # 逾時時長為10s

    # 模拟向下滑動浏覽
    def swipe_down(self, second):
        for i in range(int(second / 0.1)):
            # 根據i的值,模拟上下滑動
            if (i % 2 == 0):
                js = "var q=document.documentElement.scrollTop=" + str(300 + 400 * i)
            else:
                js = "var q=document.documentElement.scrollTop=" + str(200 * i)
            self.driver.execute_script(js)
            time.sleep(0.1)

        js = "var q=document.documentElement.scrollTop=100000"
        self.driver.execute_script(js)
        time.sleep(0.1)

    # 爬取淘寶 我已買到的寶貝商品資料, pn 定義爬取多少頁資料
    def crawl_good_buy_data(self, pn=3):

        # 對我已買到的寶貝商品資料進行爬蟲
        self.driver.get("https://buyertrade.taobao.com/trade/itemlist/list_bought_items.htm")

        # 周遊所有頁數
        
        for page in trange(1, pn):
            data_list = []

            # 等待該頁面全部已買到的寶貝商品資料加載完畢
            good_total = self.wait.until(
                EC.presence_of_element_located((By.CSS_SELECTOR, '#tp-bought-root > div.js-order-container')))

            # 擷取本頁面源代碼
            html = self.driver.page_source

            # pq子產品解析網頁源代碼
            doc = pq(html)

            # # 存儲該頁已經買到的寶貝資料
            good_items = doc('#tp-bought-root .js-order-container').items()

            # 周遊該頁的所有寶貝
            for item in good_items:
                # 商品購買時間、訂單号
                good_time_and_id = item.find('.bought-wrapper-mod__head-info-cell___29cDO').text().replace('\n', "").replace('\r', "")
                # 商家名稱
                # good_merchant = item.find('.seller-mod__container___1w0Cx').text().replace('\n', "").replace('\r', "")
                good_merchant = item.find('.bought-wrapper-mod__seller-container___3dAK3').text().replace('\n', "").replace('\r', "")
                # 商品名稱
                # good_name = item.find('.sol-mod__no-br___1PwLO').text().replace('\n', "").replace('\r', "")
                good_name = item.find('.sol-mod__no-br___3Ev-2').text().replace('\n', "").replace('\r', "")
                # 商品價格  
                good_price = item.find('.price-mod__price___cYafX').text().replace('\n', "").replace('\r', "")
                # 隻列出商品購買時間、訂單号、商家名稱、商品名稱
                # 其餘的請自己實踐擷取
                data_list.append(good_time_and_id)
                data_list.append(good_merchant)
                data_list.append(good_name)
                data_list.append(good_price)
                #print(good_time_and_id, good_merchant, good_name)
                #file_path = os.path.join(os.path.dirname(__file__) + '/user_orders.json')
                # file_path = "../Spiders/taobao/user_orders.json"
                json_str = json.dumps(data_list)
                with open(self.path + os.sep + 'user_orders.json', 'a') as f:
                    f.write(json_str)

            # print('\n\n')

            # 大部分人被檢測為機器人就是因為進一步模拟人工操作
            # 模拟人工向下浏覽商品,即進行模拟下滑操作,防止被識别出是機器人
            # 随機滑動延時時間
            swipe_time = random.randint(1, 3)
            self.swipe_down(swipe_time)

            # 等待下一頁按鈕 出現
            good_total = self.wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '.pagination-next')))
            good_total.click()
            time.sleep(2)
            # while 1:
            #     time.sleep(0.2)
            #     try:
            #         good_total = self.driver.find_element_by_xpath('//li[@title="下一頁"]')
            #         break
            #     except:
            #         continue
            # # 點選下一頁按鈕
            # while 1:
            #     time.sleep(2)
            #     try:
            #         good_total.click()
            #         break
            #     except Exception:
            #         pass

    # 收藏寶貝 傳入爬幾頁 預設三頁  https://shoucang.taobao.com/nodejs/item_collect_chunk.htm?ifAllTag=0&tab=0&tagId=&categoryCount=0&type=0&tagName=&categoryName=&needNav=false&startRow=60
    def get_choucang_item(self, page=3):
        url = 'https://shoucang.taobao.com/nodejs/item_collect_chunk.htm?ifAllTag=0&tab=0&tagId=&categoryCount=0&type=0&tagName=&categoryName=&needNav=false&startRow={}'
        pn = 0
        json_list = []
        for i in trange(page):
            self.driver.get(url.format(pn))
            pn += 30
            html_str = self.driver.page_source
            if html_str == '':
                break
            if '登入' in html_str:
                raise Exception('登入')
            obj_list = etree.HTML(html_str).xpath('//li')
            for obj in obj_list:
                item = {}
                item['title'] = ''.join([i.strip() for i in obj.xpath('./div[@class="img-item-title"]//text()')])
                item['url'] = ''.join([i.strip() for i in obj.xpath('./div[@class="img-item-title"]/a/@href')])
                item['price'] = ''.join([i.strip() for i in obj.xpath('./div[@class="price-container"]//text()')])
                if item['price'] == '':
                    item['price'] = '失效'
                json_list.append(item)
        # file_path = os.path.join(os.path.dirname(__file__) + '/shoucang_item.json')
        json_str = json.dumps(json_list)
        with open(self.path + os.sep + 'shoucang_item.json', 'w') as f:
            f.write(json_str)

    # 浏覽足迹 傳入爬幾頁 預設三頁  https://shoucang.taobao.com/nodejs/item_collect_chunk.htm?ifAllTag=0&tab=0&tagId=&categoryCount=0&type=0&tagName=&categoryName=&needNav=false&startRow=60
    def get_footmark_item(self, page=3):
        url = 'https://www.taobao.com/markets/footmark/tbfoot'
        self.driver.get(url)
        pn = 0
        item_num = 0
        json_list = []
        for i in trange(page):
            html_str = self.driver.page_source
            obj_list = etree.HTML(html_str).xpath('//div[@class="item-list J_redsList"]/div')[item_num:]
            for obj in obj_list:
                item_num += 1
                item = {}
                item['date'] = ''.join([i.strip() for i in obj.xpath('./@data-date')])
                item['url'] = ''.join([i.strip() for i in obj.xpath('./a/@href')])
                item['name'] = ''.join([i.strip() for i in obj.xpath('.//div[@class="title"]//text()')])
                item['price'] = ''.join([i.strip() for i in obj.xpath('.//div[@class="price-box"]//text()')])
                json_list.append(item)
            self.driver.execute_script('window.scrollTo(0,1000000)')
        # file_path = os.path.join(os.path.dirname(__file__) + '/footmark_item.json')
        json_str = json.dumps(json_list)
        with open(self.path + os.sep + 'footmark_item.json', 'w') as f:
            f.write(json_str)

    # 位址
    def get_addr(self):
        url = 'https://member1.taobao.com/member/fresh/deliver_address.htm'
        self.driver.get(url)
        html_str = self.driver.page_source
        obj_list = etree.HTML(html_str).xpath('//tbody[@class="next-table-body"]/tr')
        data_list = []
        for obj in obj_list:
            item = {}
            item['name'] = obj.xpath('.//td[1]//text()')
            item['area'] = obj.xpath('.//td[2]//text()')
            item['detail_area'] = obj.xpath('.//td[3]//text()')
            item['youbian'] = obj.xpath('.//td[4]//text()')
            item['mobile'] = obj.xpath('.//td[5]//text()')
            data_list.append(item)
        # file_path = os.path.join(os.path.dirname(__file__) + '/addr.json')
        json_str = json.dumps(data_list)
        with open(self.path + os.sep + 'address.json', 'w') as f:
            f.write(json_str)


if __name__ == '__main__':
    # pass
    cookie_list = json.loads(open('taobao_cookies.json', 'r').read())
    t = TaobaoSpider(cookie_list)
    t.get_orders()
    # t.crawl_good_buy_data()
    # t.get_addr()
    # t.get_choucang_item()
    # t.get_footmark_item()
           
再見爬蟲,全靠這個爬蟲工具!

更多Python相關技能,不要錯過!