多彩投网站动态爬取[python+selenium]
生活随笔
收集整理的這篇文章主要介紹了
多彩投网站动态爬取[python+selenium]
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
目標網站
遇到的坑
這個網站為了反爬蟲,使用了很多策略,而這些策略都會是爬蟲中可能遇到的坑。
目的: 目的是爬取這個網頁中的這個狀態的項目(projectStatus=6)(估計是表示結束了的意思)
坑1
- 坑: 上面的圖示網頁,無法直接獲得具體的項目的網頁鏈接: 頁面的地址是被動態加載的。也就是說沒辦法直接獲取到每個項目的具體鏈接。
- 解決方式: 這個是被我后面用一個方法(selenium)一起解決了,但其實不是一定要用selenium的。但是如果是只有這一個問題的話,我們其實一方面可以通過后臺來看network相關的請求,另一方面看js的過程。
坑2
- 坑: 在每一個項目頁面中,加載到具體的具體信息頁面中。采用的是js自動替換頁面的技術。同樣是這個原因,讓我更想使用selenium來實現爬取了
- 解決方式: selenium動態模擬
坑3
- 坑:在具體的數據頁面中數據的變換。 比如說到稍微到后面的一點點的頁面的情況的哈,會發現網頁的數據內容變了。
- 比如說,有些是:最高可投,有些是每人限投。其實本質上是一個意思。
- "標的公司", "項目公司"也是一樣的道理
- "標的估值", "項目公司估值"
- 然后一開始的數據表示的話,中間是用:(中文輸入法的:),但是,在后面有些網頁就會是: (英文輸入法的冒號加上空格作為分隔符)
- 解決辦法: 全都是用中文的來進行字符串替代。
坑4
- 坑:一開始的數據都是用每行用<p>來表示的,但是后來發現,會隨機在某兩種數據直接,使用<br>(換行符來分隔)。這樣,如果采用一般的直接獲取p標簽的話,就會出現bug。導致會在某些地方一直沒捕捉到數據。
- 解決辦法: 就是下面的代碼段。要先獲取具體的html代碼然后根據html的結構進行分析。隱含的坑!!(find_…之類的話,如果是不存在的話,就會報錯。但是之前說了這個是隨機的…所以只能是使用try來實現)
坑5
- 坑:網頁結構發生了變化。 以前的數據似乎跟稍微近一些的數據不太一樣。比如說關于我們想要的數據的所在的定位span。以前是第一個,但是后面的時候會遇到有些是在第二個上,所以就會出現一直爬不到信息的情況。
- 解決辦法: 這里的解決辦法其實還不夠完善,但是至少夠用了。就是使用最后一個。我發現,之前的只有一個span的情況,那還是一樣,但是有兩個span的時候,數據一般是在后面的span中。所以我就直接使用了[-1]這樣的方式來進行索引。
坑6
- 坑:每次都要手動登錄。非常麻煩,因為這里有需要有驗證碼,而且,驗證碼還是需要先手動先滑動一個東西之后,才會發到手機上的。而且,發到之后,每個手機號,每天只能發5次。這個非常坑。
- 解決方法: 使用pickle來存儲cookies。然后每次只用調用一次,以后的,就需要先訪問登錄網頁,然后加載cookies就好了。根據我的實驗,每一份cookies可以使用一天,然后,對面的這個網站,就會刷新這個cookies。
具體的代碼片段:
- refresh 表示是否刷新cookies
坑7
- 坑:有些是有項目的價值,有些是有項目公司的價值,有些是兩者都有 這個我驚呆了。
- 解決方法: 我就想到用字典來存儲,如果有就添加進去,否則就添加一個NULL。
坑8
- 坑:這個網頁有些神奇(或許是服務器質量不是很好),有些時候網頁加載數據的速度很慢。(加載的延時很高)。有時候,爬取到了具體的數據,但是卻沒爬到對應的公司名字。這個沒辦法了。
- 解決辦法: 我就設置,如果當公司名字為空的話,就重新加載。然后最多重新加載一定的次數。
類似的有切換網頁的時候也會出現失敗,但是刷新一下也就好了。這個我就限制了,到了一定次數就直接終止整個程序。因為,我有天晚上爬取,但是半夜的時候斷網了… 發現一直在爬取空數據。所以就有了這樣的設計。
同時,我也增加了等待機制。 類似于下面的這種。
elemnt = WebDriverWait(browser, 10).until(EC.presence_of_element_located((By.XPATH, '//*[@id="__layout"]/div/div[2]/div/div[3]/ul/li[%d]/div/div/div[1]/div[2]/h3' % (index_i + 1))))同樣是因為那次停電,我之前爬取到不少有用的數據,但是沒保存,所以我加入了一個中途定次數記錄的代碼。來保持中間的數據,為避免突然發生的問題。
坑9
- 到很久遠的數據時候,會發現沒有數據了,全都是圖片來表示數據
- 這是我一個沒解決的問題: 在圖片內… 我大概就爬了300多條稍微干凈的數據了,我想應該夠用了吧。
- 在圖片內嵌入數據,這個只能做圖片文字提取的技術了。。
代碼如何使用
- pageCount 第幾頁(是最開始的圖片所示)
- index_i在第幾頁的第幾個(從0開始計數)
用這個可以做分段爬取(有時候遇到問題了,對于某些部分可以用這個來設置重新開始)
-
refresh = False 為True的時候,需要手動登錄。然后,等待出現刷新完成之后就說明已經保存好cookies了。然后以后再啟動的時候,就設置為False。這樣就不需要再登錄了。
-
configure 這個部分的代碼,一般人都需要注釋掉。我有這個代碼,主要是因為我的chrome是我用源碼替換掉的。所以沒寫入到系統中。然后就手動寫執行文件所在的地址好了。一般人是不需要這段代碼的。記得注釋掉!!!
-
下載好需要的庫~
之后直接運行就好了。用時蠻久的。
完全的代碼
from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC import time import pickle import pandas as pd##################### USERNAME = "寫自己的手機號碼" # 填寫好賬號 密碼 下面的url根據要求替換掉 URL = "https://www.duocaitou.com/project?projectStatus=6&pageNum=%d" pageCount = 1 tempURL = URL % pageCount LOGIN_URL = "https://www.duocaitou.com/login?redirect=%2Fproject" refresh = False##################### # configure options = webdriver.ChromeOptions() options.binary_location = r"D:\Software\Chrome\Application\chrome.exe" browser = webdriver.Chrome(chrome_options=options)keys = ['項目公司', '項目公司估值', '項目估值', '籌集規模', '籌集模式', '起投金額', '每人限投', '投資期限'] globalData = {} for k in keys:globalData[k] = []if refresh:browser.get(LOGIN_URL)# 登錄time.sleep(2)input = browser.find_element_by_xpath('//input[@placeholder="請輸入手機號"]')input.send_keys(USERNAME)time.sleep(40)pickle.dump(browser.get_cookies(), open("cookies.pkl", "wb"))print('finish refresh')browser.get(tempURL) # 加載網頁time.sleep(2) else:browser.get(LOGIN_URL) # 加載網頁cookies = pickle.load(open("cookies.pkl", "rb"))for cookie in cookies:browser.add_cookie(cookie)browser.get(tempURL) # 加載網頁time.sleep(2)print(tempURL) save = 0 times = 0index_i = 0 continuetime = 0try:while True:try:elemnt = WebDriverWait(browser, 10).until(EC.presence_of_element_located((By.XPATH, '//*[@id="__layout"]/div/div[2]/div/div[3]/ul/li[%d]/div/div/div[1]/div[2]/h3' % (index_i + 1))))li_list = browser.find_element_by_xpath('//*[@id="__layout"]/div/div[2]/div/div[3]/ul/li[%d]/div/div/div[1]/div[2]/h3' % (index_i + 1)).click()elemnt = WebDriverWait(browser, 10).until(EC.presence_of_element_located((By.XPATH, '//*[@id="__layout"]/div/div[2]/div/div[1]/div[1]/div[2]/div[1]/div/div/div/div/div[3]')))browser.find_element_by_xpath('//*[@id="__layout"]/div/div[2]/div/div[1]/div[1]/div[2]/div[1]/div/div/div/div/div[3]').click()elemnt = WebDriverWait(browser, 10).until(EC.presence_of_element_located((By.XPATH, '//*[@id="__layout"]/div/div[2]/div/div[1]/div[1]/div[2]/div[2]/div[2]/div/span')))datas = browser.find_elements_by_xpath('//*[@id="__layout"]/div/div[2]/div/div[1]/div[1]/div[2]/div[2]/div[2]/div/span')if "籌集模式" in datas[0].text:datas = datas[0]else:datas = datas[-1]elemnt = WebDriverWait(datas, 10).until(EC.presence_of_element_located((By.TAG_NAME, 'p')))time.sleep(5 + continuetime)datas = datas.find_elements_by_tag_name('p')[0:40]except Exception as e:browser.get(tempURL) # 加載網頁print('refresh', tempURL, 'index is', index_i)time.sleep(5)continuetime += 1if continuetime >= 10:breakcontinuedatas = [d for d in datas if len(d.text.strip()) > 4 and (':' in d.text or ':' in d.text)][:8]tempDatas = []for d in datas:try:td = d.find_element_by_tag_name('span').get_attribute("innerHTML")if '<br>' in td:tds = td.split('<br>')for tdi in tds:tempDatas.append(tdi.replace('\n', '').replace(' ', ' ').replace(': ', ':').replace(':', ":").strip())else:tempDatas.append(d.text.strip().replace('\n', '').replace(': ', ':').replace(':', ":"))except Exception as e:tempDatas.append(d.text.strip().replace('\n', '').replace(': ', ':').replace(':', ":"))datas = tempDatastry:tempdict = {}for d in datas:if ':' not in d:continuea = d[:d.index(':')]b = d[d.index(':') + 1:]if a == '最高可投':a = '每人限投'a = a.replace("標的公司", "項目公司").replace("標的估值", "項目公司估值")if a in tempdict:if '籌集規模:' in b:b = b.split('籌集規模:')tempdict['項目公司估值'] = b[0]tempdict['籌集規模'] = b[1]else:tempdict['項目公司估值'] = belif a == '籌集模式' and '每人限投:' in b:b = b.split('每人限投:')tempdict[a] = b[0]tempdict['每人限投'] = b[1]elif a == '項目公司' and '籌集規模:' in b:b = b.split('籌集規模:')tempdict['項目公司估值'] = b[0]tempdict['籌集規模'] = b[1]else:tempdict[a] = bif len(tempdict) == 0 or '項目公司' not in tempdict:continuetime += 1if continuetime < 3:browser.get(tempURL) # 加載網頁time.sleep(2)continueelse:continuetime = 0for key in globalData.keys():if key in tempdict:globalData[key].append(tempdict[key])elif key == '標的公司':globalData['項目公司'].append(tempdict[key])elif key == '標的公司估值':globalData['項目公司估值'].append(tempdict[key])else:globalData[key].append('NULL')print(key, ': ', globalData[key][-1], end=' , ')print()times += 1if times % 50 == 49:pd.DataFrame(globalData).to_excel('data_%d.xlsx' % save, columns=keys)save += 1times = 0except Exception as e:print(e.args)for i, d in enumerate(datas):print(i, d)breakif index_i == 8:index_i = 0pageCount += 1if pageCount >= 67:breaktempURL = URL % pageCountprint(tempURL)browser.get(tempURL) # 加載網頁time.sleep(2)else:browser.get(tempURL) # 加載網頁time.sleep(2)index_i += 1continuetime = 0 finally:pd.DataFrame(globalData).to_excel('data.xlsx', columns=keys)總結
以上是生活随笔為你收集整理的多彩投网站动态爬取[python+selenium]的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: RNN代码解释pytorch
- 下一篇: VS C++调用python进行画图ma