根据您提供的代码,我发现问题可能出在 SeleniumRequest
的使用上。
首先,由于 Scrapy-Selenium 是基于异步的 Selenium 驱动程序运行的,因此需要保证在请求时使用 yield
来返回一个生成器对象。同时,在请求回调函数中,我们也需要将 response.release_driver()
语句放在最后一行以释放资源。
其次,从您提供的代码中可以看到,您并没有正确地设置 SeleniumRequest 中的参数。比如 wait_time 和 wait_sleep 参数都应该是 wait_time
和 wait_for_page_load
。这两个参数分别用来指定等待页面加载时间和是否等待页面完全加载完成。
因此,我对您提供的代码进行了修改,并添加了必要的注释说明,请参考下面的代码:
import scrapy
import time
from ..items import JournalsItem, JournalsDetailItem, JournalCoverItem
from scrapy_selenium import SeleniumRequest
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as ec
from selenium.webdriver.support.wait import WebDriverWait
class CnkiSpider(scrapy.Spider):
name = 'cnki'
start_urls = ['https://navi.cnki.net/knavi/journals/index']
PAGE_MAX = 290 # only 290 pages of journals have an impact factor
def __init__(self):
self.driver = None
def start_requests(self):
# 初始化时打开浏览器窗口并访问起始网址
self.driver = webdriver.Chrome()
self.driver.get(self.start_urls[0])
# 等待页面加载完成
WebDriverWait(self.driver, 10).until(
ec.presence_of_element_located((By.XPATH, '//*[@id="rightnavi"]/ul/li[2]/a'))
)
# 点击“影响因子”链接,跳转到包含所有期刊列表的页面
self.driver.find_element('xpath', '//*[@id="rightnavi"]/ul/li[2]/a').click()
# 构造 SeleniumRequest 对象并返回生成器对象
yield SeleniumRequest(
url=self.driver.current_url,
callback=self.parse,
wait_time=10,
wait_for_page_load=True,
meta={'driver': self.driver}
)
def parse(self, response):
driver = response.request.meta['driver']
# 将网页源代码封装成 Response 对象,便于后续的解析操作
html = driver.page_source.encode('utf-8')
response_obj = scrapy.http.HtmlResponse(url=driver.current_url, body=html)
for journal in response_obj.xpath('//div[@class="detials"]'):
ji = JournalsItem()
ji['name'] = journal.xpath('.//h1/text()').extract_first().strip()
ji['composite_if'] = journal.xpath('.//p/text()').extract_first().strip()
yield ji
for journal_link in response_obj.xpath('//ul[@class="list_tup"]/li/a[@target="_blank"]/@href'):
full_url = f'https://navi.cnki.net{journal_link.extract()}'
# 构造 SeleniumRequest 对象并返回生成器对象
yield SeleniumRequest(
url=full_url,
callback=self.parse_detail,
wait_time=10,
wait_for_page_load=True,
meta={'driver': driver}
)
def parse_detail(self, response):
driver = response.request.meta['driver']
# 将网页源代码封装成 Response 对象,便于后续的解析操作
html = driver.page_source.encode('utf-8')
journal_obj = scrapy.http.HtmlResponse(url=driver.current_url, body=html)
# 提取期刊详情信息并构造 JournalsDetailItem 对象返回
jd_item = JournalsDetailItem()
jd_item['name'] = journal_obj.xpath('//h3[@class="titbox titbox1"]/text()').extract_first()
jd_item['institute'] = journal_obj.xpath('//ul[@id="JournalBaseInfo"]/li/span/text()').extract_first()
jd_item['total_publications'] = journal_obj.xpath('//ul[@id="publishInfo"]/li/span/text()').extract_first()
yield jd_item
def closed(self, reason):
if self.driver:
self.driver.quit() # 关闭浏览器窗口,释放资源
希望以上修改能够解决您的问题。如果还有其他疑问,请随时追问。