上一篇文章實現的最簡單的爬蟲,抓取了某個連接下第一次加載的全部圖片連接。由於存在下拉刷新, 所以怎麼得到該頁面的所有答案是這篇文章須要去處理的事情。css
這裏選擇使用方案2,方案1後面遇到再討論。html
一:selenium的簡單使用。 這裏涉及selenium的安裝,Selenium with Python官方文檔講解的特別簡單。我使用的的chrome(能夠配置無頭屬性)。 注意:須要將下載的driver配置環境變量,以即可以訪問。python
if __name__ == '__main__':
options = webdriver.ChromeOptions()
options.add_argument('headless')
# driver = webdriver.Chrome(options=options)
driver = webdriver.Chrome()
driver.implicitly_wait(2)
driver.get("https://www.zhihu.com/question/22856657")
time.sleep(2)
resSoup = BeautifulSoup(driver.page_source, 'lxml')
items = resSoup.select("figure > span > div")
print(len(items))
for item in items:
print(item)
#driver.close()
複製代碼
在項目執行代碼能夠看到輸出:python zhihu/spiders/zhihu.py
git
data-src
屬性便可得圖片連接。 代碼解釋: 前三行用於啓動一個無頭的driver。若是須要查看加載的狀況,只用第四行代碼便可,執行完畢能夠查看瀏覽器打開的url, 以下。
接下來三行: 第一行啓動driver的隱式等待,簡單意思就是:2秒內網頁加載完畢就往下執行,不然就加載完2秒,繼續往下執行。 第二行用於打開連接,至關於手動在地址欄輸入連接。 第三行延時,等待網頁加載。 後面的內容前面有接觸。 若是輸出結果和個人相差不大,那麼繼續下一步。github
二:selenium執行js代碼,加載所有內容。web
if __name__ == '__main__':
options = webdriver.ChromeOptions()
options.add_argument('headless')
# driver = webdriver.Chrome(options=options)
driver = webdriver.Chrome()
driver.implicitly_wait(2)
driver.get("https://www.zhihu.com/question/22856657")
time.sleep(2)
count = 1
css_selector = "#root > div > main > div > div.Question-main > div.Question-mainColumn > div > div.Card > button"
css_selector2 = "#root > div > main > div > div.Question-main > div.Question-mainColumn > div > div.CollapsedAnswers-bar"
while len(driver.find_elements_by_css_selector(css_selector)) == 0 and \
len(driver.find_elements_by_css_selector(css_selector2)) == 0:
print("count:" + str(count))
js = "var q=document.documentElement.scrollTop=" + str(count * 200000)
count += 1
driver.execute_script(js)
time.sleep(0.5)
resSoup = BeautifulSoup(driver.page_source, 'lxml')
items = resSoup.select("figure > span > div")
print(len(items))
for item in items:
print(item)
複製代碼
用一個循環去執行js代碼,簡單意思是滑動到距離頁面頂部x的距離。通過測試,200000/頁是比較好的選擇。chrome
至此,能夠抓取某個連接下的全部圖片。瀏覽器
三: selenium與spider middlewares的結合。 上面一切順利以後, 接下來去使雙方結合。 關於scrapy 的下載中間鍵(DOWNLOADER_MIDDLEWARES): 簡單來講,該中間鍵就是調用process_request, 將獲取url的request通過處理,返回request,response,None三值之一。 返回 request:繼續執行後面的process_request方法(包括中間鍵) response:不知行後面的process_request方法,以此response結果直接返回,執行zhihu/spiders/zhihu.py 的回調方法。 具體請看官方文檔: https://docs.scrapy.org/en/latest/topics/downloader-middleware.html (還有spider middlewares, 本次未用到) bash
話很少說,開始寫代碼: 在middlewares.py中定義本身的中間鍵:服務器
class PhantomJSMiddleware(object):
def __init__(self):
options = webdriver.ChromeOptions()
options.add_argument('headless')
self.driver = webdriver.Chrome()
self.driver.implicitly_wait(1)
def process_request(self, request, spider):
print(request.url)
driver = self.nextPage(request)
return HtmlResponse(url=request.url, body=driver.page_source, encoding="utf-8")
# 翻頁操做
def nextPage(self, request):
self.driver.get(request.url)
time.sleep(2)
count = 1
css_selector = "#root > div > main > div > div.Question-main > div.Question-mainColumn > div > div.Card > button"
css_selector2 = "#root > div > main > div > div.Question-main > div.Question-mainColumn > div > div.CollapsedAnswers-bar"
# css_selector = "div > a > img"
# print(len(self.driver.find_elements_by_css_selector(css_selector)))
while len(self.driver.find_elements_by_css_selector(css_selector)) == 0 and len(
self.driver.find_elements_by_css_selector(css_selector2)) == 0:
print("count:" + str(count))
js = "var q=document.documentElement.scrollTop=" + str(count * 200000)
count += 1
self.driver.execute_script(js)
time.sleep(0.5)
print(count)
time.sleep(2)
return self.driver
@classmethod
# 信號的使用
def from_crawler(cls, crawler):
print("from_crawler")
# This method is used by Scrapy to create your spiders.
s = cls()
crawler.signals.connect(s.spider_opened, signal=signals.spider_closed)
return s
def spider_opened(self, spider):
print("spider close")
self.driver.close()
複製代碼
稍做解釋: __init__
函數作初始化工做, nextPage
函數根據獲得的request作翻頁操做。 **process_request
**函數是中間鍵的必要函數, 啓動中間鍵以後,yield生成器中的request都會通過該函數,而後返回結果(必定要在此函數執行return)。
後面是spiders信號的使用實例, 用於在spiders執行結束的時候作處理工做,好比關閉driver等操做。
setttings.py:配置對下載中間鍵的使用。
DOWNLOADER_MIDDLEWARES = {
'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': None,
'zhihu.middlewares.PhantomJSMiddleware': 100,
}
複製代碼
以上配置完畢,便可執行爬蟲。 命令行執行 scrapy crawl zhihu
啓動爬蟲,注意看日誌,有以下輸出。
下拉刷新根據網速決定,因此count值會有不一樣。 能夠看到這裏抓取到了660張圖片連接(容許個別偏差)。
至此,對於使用scrapy結合selnium抓取動態網頁已經不是問題。
對於某些須要登陸的連接,打開url以後會直接去到登陸頁。下一篇文章介紹怎麼使用selenium 去登陸,保存cookies, 帶着cookies去請求(多是萬能的登陸方法,對於圖片驗證, 手機驗證碼也可能適用)。
微信:youquwen1226 github:https://github.com/yunshuipiao 歡迎來信一塊兒探討。