我正在尝试使用Scrapy提交动态生成的用户登录表单,然后在与成功登录相对应的页面上解析HTML。
我想知道如何使用Scrapy或Scrapy和Selenium的组合来做到这一点。 Selenium可以在DOM上找到元素,但我想知道在获取完整的HTML后是否可以“控制回”Scrapy,以便允许它执行表单提交并保存必要的cookie ,会话数据等,以便刮取页面。
基本上,我认为Selenium是必要的唯一原因是因为我需要在Scrapy查找<form>
元素之前从Javascript呈现页面。有没有替代方案呢?
谢谢!
编辑:此问题类似于this one,但遗憾的是,已接受的答案涉及请求库而非Selenium或Scrapy。虽然在某些情况下可能会出现这种情况(watch this to learn more),正如alecxe指出的那样,如果“页面的某些部分[例如表单]通过API调用加载并在帮助中插入页面,则可能需要Selenium在浏览器中执行的javascript代码“。
答案 0 :(得分:4)
Scrapy
实际上并不适合使用coursera 网站,因为它非常异步。页面的一部分通过API调用加载,并在浏览器中执行javascript代码的帮助下插入页面。 Scrapy
不是浏览器,无法处理它。
这提出了重点 - 为什么不使用公开的Coursera API?
除了记录的内容之外,您还可以在浏览器开发人员工具中看到其他端点 - 您需要通过身份验证才能使用它们。例如,如果您已登录,则可以看到您已经采取的课程列表:
呼叫memberships.v1
端点。
为了举例,让我们开始selenium
,登录并使用get_cookies()
抓取Cookie。然后,让我们生成一个Request
到memberships.v1
端点,以获取已归档课程的列表,提供我们从selenium
获得的Cookie:
import json
import scrapy
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
LOGIN = 'email'
PASSWORD = 'password'
class CourseraSpider(scrapy.Spider):
name = "courseraSpider"
allowed_domains = ["coursera.org"]
def start_requests(self):
self.driver = webdriver.Chrome()
self.driver.maximize_window()
self.driver.get('https://www.coursera.org/login')
form = WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.XPATH, "//div[@data-js='login-body']//div[@data-js='facebook-button-divider']/following-sibling::form")))
email = WebDriverWait(form, 10).until(EC.visibility_of_element_located((By.ID, 'user-modal-email')))
email.send_keys(LOGIN)
password = form.find_element_by_name('password')
password.send_keys(PASSWORD)
login = form.find_element_by_xpath('//button[. = "Log In"]')
login.click()
WebDriverWait(self.driver, 20).until(EC.visibility_of_element_located((By.XPATH, "//h2[. = 'My Courses']")))
self.driver.get('https://www.coursera.org/')
cookies = self.driver.get_cookies()
self.driver.close()
courses_url = 'https://www.coursera.org/api/memberships.v1'
params = {
'fields': 'courseId,enrolledTimestamp,grade,id,lastAccessedTimestamp,role,v1SessionId,vc,vcMembershipId,courses.v1(display,partnerIds,photoUrl,specializations,startDate,v1Details),partners.v1(homeLink,name),v1Details.v1(sessionIds),v1Sessions.v1(active,dbEndDate,durationString,hasSigTrack,startDay,startMonth,startYear),specializations.v1(logo,name,partnerIds,shortName)&includes=courseId,vcMembershipId,courses.v1(partnerIds,specializations,v1Details),v1Details.v1(sessionIds),specializations.v1(partnerIds)',
'q': 'me',
'showHidden': 'false',
'filter': 'archived'
}
params = '&'.join(key + '=' + value for key, value in params.iteritems())
yield scrapy.Request(courses_url + '?' + params, cookies=cookies)
def parse(self, response):
data = json.loads(response.body)
for course in data['linked']['courses.v1']:
print course['name']
对我来说,它会打印出来:
Algorithms, Part I
Computing for Data Analysis
Pattern-Oriented Software Architectures for Concurrent and Networked Software
Computer Networks
这证明我们可以从Scrapy
提供selenium
Cookie并成功从&#34;中提取数据仅限登录用户&#34;页。
此外,请确保您不违反Terms of Use中的规则,具体为:
此外,作为访问网站的条件,您同意不这样做 ......(c)使用任何大容量,自动或电子方式进入 网站(包括但不限于机器人,蜘蛛,脚本或 网络抓取工具);