快上車,scrapy爬蟲飆車找福利(二)

上一篇文章實現(xiàn)的最簡單的爬蟲,抓取了某個鏈接下第一次加載的所有圖片鏈接。因為存在下拉刷新, 因此怎么獲得該頁面的全部答案是這篇文章需要去處理的事情。

方案:

  1. 抓包,看下拉刷新向服務器發(fā)送什么請求,模擬去發(fā)送請求(結構化數(shù)據(jù)適用)
  2. selenium執(zhí)行js的滑動到底部,判斷是否滑動到底部,以此循環(huán)。

具體實施;

這里選擇使用方案2,方案1后面遇到再討論。

一:selenium的簡單使用。
這里涉及selenium的安裝,Selenium with Python官方文檔講解的特別簡單。我使用的的chrome(可以配置無頭屬性)。
注意:需要將下載的driver配置環(huán)境變量,以便可以訪問。

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()

在項目執(zhí)行代碼可以看到輸出:python zhihu/spiders/zhihu.py

image.png

可以看到共抓到198張圖片,對去data-src屬性即可得圖片鏈接。
代碼解釋:
前三行用于啟動一個無頭的driver。如果需要查看加載的情況,只用第四行代碼即可,執(zhí)行完畢可以查看瀏覽器打開的url, 如下。
image.png

接下來三行:
第一行啟動driver的隱式等待,簡單意思就是:2秒內(nèi)網(wǎng)頁加載完畢就往下執(zhí)行,否則就加載完2秒,繼續(xù)往下執(zhí)行。
第二行用于打開鏈接,相當于手動在地址欄輸入鏈接。
第三行延時,等待網(wǎng)頁加載。
后面的內(nèi)容前面有接觸。
如果輸出結果和我的相差不大,那么繼續(xù)下一步。

二:selenium執(zhí)行js代碼,加載全部內(nèi)容。

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)
image.png

結果輸出:共計抓取翻頁13次,抓取662個圖片鏈接。
中間部分新增的代碼, count用于記錄翻頁次數(shù)。
css_selector和css_selector2用于判斷某個元素是否存在,決定是否滑動到底部,如下。


image.png

用一個循環(huán)去執(zhí)行js代碼,簡單意思是滑動到距離頁面頂部x的距離。經(jīng)過測試,200000/頁是比較好的選擇。

至此,可以抓取某個鏈接下的所有圖片。

三: selenium與spider middlewares的結合。
上面一切順利之后, 接下來去使雙方結合。
關于scrapy 的下載中間鍵(DOWNLOADER_MIDDLEWARES):
簡單來說,該中間鍵就是調(diào)用process_request, 將獲取url的request經(jīng)過處理,返回request,response,None三值之一。
返回 request:繼續(xù)執(zhí)行后面的process_request方法(包括中間鍵)
response:不知行后面的process_request方法,以此response結果直接返回,執(zhí)行zhihu/spiders/zhihu.py 的回調(diào)方法。
具體請看官方文檔: https://docs.scrapy.org/en/latest/topics/downloader-middleware.html
(還有spider middlewares, 本次未用到)

image.png

話不多說,開始寫代碼:
在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__函數(shù)做初始化工作,
nextPage函數(shù)根據(jù)得到的request做翻頁操作。
process_request函數(shù)是中間鍵的必要函數(shù), 啟動中間鍵之后,yield生成器中的request都會經(jīng)過該函數(shù),然后返回結果(一定要在此函數(shù)執(zhí)行return)。

后面是spiders信號的使用實例, 用于在spiders執(zhí)行結束的時候做處理工作,比如關閉driver等操作。

setttings.py:配置對下載中間鍵的使用。

DOWNLOADER_MIDDLEWARES = {
    'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': None,
    'zhihu.middlewares.PhantomJSMiddleware': 100,
}

以上配置完畢,即可執(zhí)行爬蟲。
命令行執(zhí)行 scrapy crawl zhihu啟動爬蟲,注意看日志,有如下輸出。

image.png

下拉刷新根據(jù)網(wǎng)速決定,所以count值會有不同。
可以看到這里抓取到了660張圖片鏈接(允許個別誤差)。

至此,對于使用scrapy結合selnium抓取動態(tài)網(wǎng)頁已經(jīng)不是問題。

對于某些需要登錄的鏈接,打開url之后會直接去到登錄頁。下一篇文章介紹怎么使用selenium 去登錄,保存cookies, 帶著cookies去請求(可能是萬能的登錄方法,對于圖片驗證, 手機驗證碼也可能適用)。

微信:youquwen1226
github:https://github.com/yunshuipiao
歡迎來信一起探討。

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • 以前也有寫過爬蟲,抓過網(wǎng)易云歌單和豆瓣讀書的數(shù)據(jù),當時有兩個問題解決的不夠好, 自動化和登錄。最近花時間用scra...
    swensun閱讀 5,487評論 0 2
  • scrapy學習筆記(有示例版) 我的博客 scrapy學習筆記1.使用scrapy1.1創(chuàng)建工程1.2創(chuàng)建爬蟲模...
    陳思煜閱讀 13,087評論 4 46
  • Scrapy,Python開發(fā)的一個快速,高層次的屏幕抓取和web抓取框架,用于抓取web站點并從頁面中提取結構化...
    Evtion閱讀 6,193評論 12 18
  • Python版本管理:pyenv和pyenv-virtualenvScrapy爬蟲入門教程一 安裝和基本使用Scr...
    inke閱讀 63,530評論 6 99
  • 如果在填志愿那時,我知道即將一個人遠赴1360.38公里去,真的還會有現(xiàn)在的故事嗎。 “想出去走走” “嗯,一起”...
    良人小妮子閱讀 232評論 0 1

友情鏈接更多精彩內(nèi)容