一些数据,必须登录后才能爬取,解决方案有两种:

  • 直接用爬虫程序向登录站点提交用户名、密码、验证码等参数,登录成功后记录 Cookie
  • 使用真正的浏览器来模拟登录,然后记录登录后的 Cookie

第一种方法,编程起来比较麻烦,第二种方法比较简单。在使用 Scrapy 开发爬虫程序时,经常会整合 Selenium 来启动浏览器登录

安装 Selenium

pip install selenium

下载浏览器驱动

下载地址:https://selenium-python.readthedocs.io/installation.html#drivers

例如我这里会下载 chrome 的驱动,chromedriver

简单测试

新建一个文件夹 selenium,将刚下载的 chromedriver 驱动放进去。新建一个 selenium_test.py 文件,

from selenium import webdriver
import time

# 通过executable_path指定浏览器驱动的路径
browser = webdriver.Chrome(executable_path="./chromedriver")

# 等待3秒,用于等待浏览器启动完成
time.sleep(3)

# 浏览指定网页
browser.get("https://itfun.tv/")

# 暂停5秒
time.sleep(5)

运行一下,可以看到 chrome 被启动了,并访问了指定的页面。

Scrapy 整合 Selenium

现在建立项目,正式开发。

$ scrapy startproject LoginSpider
cd LoginSpider
scrapy genspider itfun "itfun.tv"

配置

将下载好的 chromedriver 放在项目根目录中

settings.py

USER_AGENT = 'Chrome/75.0.3770.142'
ROBOTSTXT_OBEY = True

爬虫开发

spiders/itfun.py

# -*- coding: utf-8 -*-
import scrapy
from selenium import webdriver
import time


class ItfunSpider(scrapy.Spider):
    name = 'itfun'
    allowed_domains = ['itfun.tv']
    start_urls = ['http://itfun.tv/']

    def __init__(self):
        # 定义保存登录成功之后的cookie的变量
        self.cookies = []

    # 定义发送请求的请求头
    headers = {
        "Referer": "https://itfun.tv/",
        'User-Agent': "Chrome/75.0.3770.142"
    }

    def get_cookies(self):
        # 使用Selenium模拟浏览器登录并获取cookies
        browser = webdriver.Chrome(executable_path="./chromedriver")

        # 等待3秒,用于等待浏览器启动完成,否则可能报错
        time.sleep(3)
        browser.get("https://itfun.tv/")

        # 登录框
        login = browser.find_element_by_xpath('//a[@id="btn_login_modal"]')
        login.click()
        time.sleep(3)

        # 获取输入用户名的 input
        email = browser.find_element_by_xpath('//input[@id="user_login_email"]')
        # 输入用户名
        email.send_keys('xxxxx@gmail.com')

        # 获取输入密码的 input
        password = browser.find_element_by_xpath('//input[@id="user_login_password"]')
        # 输入密码
        password.send_keys('yyyyyy')

        # 获取提交按钮
        commit = browser.find_element_by_xpath('//button[@id="btn_login_submit"]')
        # 单击提交按钮
        commit.click()

        # 暂停5秒,等待浏览器登录完成
        time.sleep(5)

        # 登录成功后获取cookie
        print('=====================', browser.get_cookies())
        self.cookies = browser.get_cookies()

    # start_requests方法会在parse方法之前执行,此方法可用于处理登录逻辑。
    def start_requests(self):
        self.get_cookies()

        # 抓取登录后的用户首页
        return [scrapy.Request('https://itfun.tv/users',
                               headers=self.headers,
                               cookies=self.cookies,
                               callback=self.parse)]

    # 解析登录后的页面
    def parse(self, response):
        print('=====================')
        print("解析登录后的用户页:", response.text)

运行

$ scrapy crawl itfun

后续

爬取到登录后页面,接下来想存成 json 也好,存入数据库也好,就看你个人需求了。请参考前几节的内容自行完成。