在進行爬蟲的時候,有時候我們在網頁中看到的數據是一個樣子的,但是抓取到的數據卻是另外一個樣子的。這是爲什麼呢?這個時候啊很可能我們抓取的是動態網頁。動態網頁的代碼雖然沒有改變,但是顯示的內容卻是可以隨着時間、環境或者數據庫操作的結果二發生改變的。動態網頁一般使用被稱爲 AJAX 的快速動態創建網頁技術。通過在後臺與服務器進行少量數據交換,AJAX可以使網頁實現異步更新。那麼這種網頁該如何進行抓取呢?我們可以考慮使用如下兩種方法。
1. 分析頁面請求,查找真實請求的URL
既然 AJAX 技術是在後臺與服務器交換數據,只要有數據發送過來,就肯定有發送到服務器的請求,只需找出它加載出頁面的真實請求,然後構造併發送請求即可。
2. 使用Selenium模擬瀏覽器行爲
Selenium是一個自動化測試工具,被廣泛的用來做爬蟲,在爬蟲中主要使用Selenium解決動態網頁的加載和渲染功能。Selenium 可以用代碼模擬操作瀏覽器,模擬人的操作。可以使用 Selenium,配合 headless 的瀏覽器(如:phantomjs、headless Chrome)來加載和渲染網頁,然後提取需要的信息。
案例
1. 鏈家經紀人頁面分析
我們來對移動端的 鏈家經紀人頁面 進行分析,相比於 PC 端,移動端的網頁更爲簡單、簡潔。所以如果一個網頁有移動端的話,我們優先選擇移動端網頁進行爬取。打開網頁拉動滾動條,將其拉到底,添加一些數據進來,我們發現 NetWork 裏出現了很多的請求信息,這些請求大部分都是以 jpg 結束的圖片請求,但是我們仔細觀察,就能發現一項比較特殊的請求,如下:
我們繼續滑動滾動條,又會發現類似的請求,我們將該請求鏈接複製出來,單獨打開,發現它是不同經紀人的請求頁面。我們對該鏈接進行分析,發現後面有一項 offset 的值一直在改變,而且每次以 15 增加,會請求到新的 15 條數據。因此你,我們只需要更改 offset 的值即可請求不同的頁面。至此,我們已經發現了該網站 URL 的構造規律了,下面就可以編寫代碼進行爬取了。
# -*- coding: utf-8 -*-
# # @Author: lemon
# # @Date: 2019-09-19 18:18
# # @Last Modified by: lemon
# # @Last Modified time: 2019-09-19 18:42
# # @function: 爬取鏈家經紀人數據
import requests
import time
from lxml import etree
import pandas as pd
# 存儲 DataFrame 中用到的數據
data = {
'姓名': [],
'職位': [],
'評分': []
}
def spider(list_url):
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'
}
response = requests.get(list_url, headers=headers)
time.sleep(5)
sel = etree.HTML(response.text)
# 先爬取每一位經紀人的整體代碼段
agent_list = sel.xpath('//li[@class="pictext flexbox box_center_v lazyload_ulog"]')
for agent in agent_list:
agent_name = agent.xpath('div/div[2]/div[1]/span[1]/a/text()')[0].strip() # 姓名
agent_level = agent.xpath('div/div[2]/div[1]/span[2]/text()')[0].strip() # 職位
agent_score = agent.xpath('div/div[2]/div[1]/span[3]/span[1]/text()')[0].strip() # 評分
print(agent_name, agent_level, agent_score)
data['姓名'].append(agent_name)
data['職位'].append(agent_level)
data['評分'].append(agent_score)
def write_data(data):
frame = pd.DataFrame(data)
frame.to_excel('鏈家經紀人數據.xlsx')
if __name__ == '__main__':
for i in range(10):
# 根據加載的時候 offset 的變化規律, 構造不同頁面的 URL
url = 'https://m.lianjia.com/cs/jingjiren/?page_size=15&_t=1&offset=' + str(i * 15)
print(f'正在爬取 page {i + 1}...')
spider(url)
write_data(data)
這是我們最終爬取到的經紀人數據:
2. Selenium 請求百度
由於 Selenium 不是 Python 的標準庫,因此我們首先需要安裝 Selenium 庫。
pip install selenium
Selenium 需要使用 chromedriver 來驅動 Chrome 瀏覽器,我們需要下載與操作系統對應的版本,可參考 ChromeDriver與Chrome版本對應參照表及ChromeDriver下載鏈接 進行下載安裝。
Selenium 在使用 chromedriver 時,既可以把 chromedriver添加到系統的環境變量中,也可以直接在代碼中指明 chromedriver 所在的目錄。
下面我們使用 Selenium 訪問百度首頁
# -*- coding: utf-8 -*-
# # @Author: lemon
# # @Date: 2019-09-19 19:00
# # @Last Modified by: lemon
# # @Last Modified time: 2019-09-19 19:10
# # @function: Selenium 打開百度
# %%1 從 selenium 中引入 webdriver
from selenium import webdriver
driver = webdriver.Chrome('E:\ChromeDriver\chromedriver.exe') # 初始化 webdriver
driver.get('https://www.baidu.com/') # 使用 webdriver 打開百度首頁
search_box = driver.find_element_by_xpath('//*[@id="kw"]') # 使用 xpath 找到搜索框
search_box.send_keys('python') # 在搜索框中搜索關鍵字
submit = driver.find_element_by_xpath('//*[@id="su"]') # 使用 xpath 找到搜索按鈕
submit.click() # 點擊搜索按鈕進行搜索
可觀察到如下效果:我們的 Chrome 瀏覽器正在收到自動測試軟件的控制
後續的文章我們爲大家示例:如何使用 Selenium 爬取新浪微博的網站,進一步加強大家對於 Selenium 的使用。