1
\$\begingroup\$

This is a follow-up to my question over here.

Having worked through most of the issues highlighted by @Reinderien in his detailed answer, I somehow got the code to work...

Some quick observations:

  1. elements.py and the SearchTextElement class from page.py seem to be obsolete to me, after revising the submit_search() function. But I still feel that given the fact that this design approach is suggested by the author(s) of the Selenium Manual, there ought to be some merit in it. One thing I had in mind when adopting their approach was to make use of the BasePageElement class (this is the "class of descriptors" described in my title) to do all the "getting" and "setting" of data on a webpage instance. The "getting" can be done via a static variable that represents an instance of SearchTextElement, as demonstrated in the manual. The downside to this is: the locator for the search text field would not be part of locators.py, but secretly tucked away in an obscure class whose sole purpose is to declare that variable. I still haven't figured out how BasePageElement can be invoked to do the "getting" work.
  2. I tried putting driver.get(CNKI.URL) in MainPage's __init__ function (it has since been commented out) but the code did not run well. I got caught in a "Catch-22"-like situation whereby initiation of both MainPage and SearchResult require driver as an argument. Which means I cannot do:
class MainPage(BasePage):
    """Home page action methods come here. I.e. Python.org"""

    def __init__(self, driver, SRC):
        super().__init__(driver, SRC)
        self.driver = driver()
        self.SRC = SRC
        self.driver.get(SRC.URL)

Because even though the browser and webpage get launched smoothly over here, back in test.py, driver still has to be defined so that it can be plugged into MainPage and SearchResults respectively:

driver = webdriver.Chrome # I use inert driver over here to avoid launching another empty browser.
cnki_search = MainPage(driver, CNKI) # driver gets passed to `MainPage.__init__` and activated.

result = SearchResults(driver, CNKI) # inert driver gets passed to `SearchResults` and spoils the soup.

I tried making use of class inheritance to solve the problem by defining driver and SRC as class variables (as opposed to instance) in BasePage so that SearchResults can somehow inherit that activated driver instance from its parent class, but so long as SearchResults needs to be instantiated in test.py, the active driver would be overwritten by the inert.

Any advice pertaining the above issues and/or other suggestions to improve the code would be greatly appreciated.


The Code:

test.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from selenium import webdriver
from selenium.webdriver.chrome.webdriver import WebDriver
from locators import CNKI
from page import BasePage, MainPage, SearchResults

def cnki_search():

    driver = webdriver.Chrome()
    driver.get(CNKI.URL)

    cnki_search = MainPage(driver, CNKI)
    cnki_search.submit_search('人性論')
    # cnki_search.search_keyword = '人性論'
    # cnki_search.select_dropdown_item('篇名')
    # cnki_search.click_search_button()

    cnki_search.switch_to_frame()
    cnki_search.max_content()

    result = SearchResults(driver, CNKI)
    titles_grp = result.get_structured_elements('titles')

    # cnki_search.next_page()

cnki_search()

page.py

# -*- coding: utf-8 -*-
from element import BasePageElement
from selenium import webdriver
from selenium.common.exceptions import TimeoutException, WebDriverException
from selenium.common.exceptions import StaleElementReferenceException
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver.support.ui import WebDriverWait


class SearchTextElement(BasePageElement):
    """This class gets the search text from the specified locator"""

    #The locator for search box where search string is entered
    locator = None


class BasePage:
    """Base class to initialize the base page that will be called from all
    pages"""

    def __init__(self, driver, SRC):
        BasePage.driver = driver
        BasePage.SRC = SRC


class MainPage(BasePage):
    """Home page action methods come here. I.e. Python.org"""

    # SRC = None
    # search_keyword = SearchTextElement()

    def __init__(self, driver, SRC):
        super().__init__(driver, SRC)
        self.driver = driver
        self.SRC = SRC
        # self.driver.get(SRC.URL)
    
    def submit_search(self, keyword):
        driver = self.driver
        wait = WebDriverWait(driver, 50)

        search = wait.until(EC.presence_of_element_located
            (self.SRC.INPUT['SEARCH_FIELD']))
        search.send_keys(keyword)
        search.submit()
    
    # THIS ONE MAKES USE OF SearchTextElement; the above doesn't.
    #
    # def submit_search(self, keyword):
    #     """Submits keyword and triggers the search"""
    #     SearchTextElement.locator = self.SRC.INPUT['SEARCH_FIELD']
    #     self.search_keyword = keyword

    def select_dropdown_item(self, item):
        driver = self.driver
        by, val = self.SRC.INPUT['SEARCH_ATTR']
        driver.find_element(by, val + "/option[text()='" + item + "']").click()

    def click_search_button(self):
        driver = self.driver
        element = driver.find_element(*self.SRC.INPUT['SEARCH_BUTTON'])
        element.click()
        
    def switch_to_frame(self):
        """Use this function to get access to hidden elements. """
        driver = self.driver
        wait = WebDriverWait(driver, 100)

        wait.until(
            lambda driver: 
            driver.find_element_by_xpath('//iframe[@name="iframeResult"]'))

        driver.switch_to.default_content()
        driver.switch_to.frame('iframeResult')


    def max_content(self):
        """Maximize the number of items on display in the search results."""
        driver = self.driver
        max_content = driver.find_element(*self.SRC.INPUT['MAX_CONTENT'])
        max_content.click()
    
    
    def stop_loading_page_when_element_is_present(self, locator):
        driver = self.driver
        ignored_exceptions = (NoSuchElementException, StaleElementReferenceException)
        wait = WebDriverWait(driver, 30, ignored_exceptions=ignored_exceptions)
    
        wait.until(
            EC.presence_of_element_located(locator))
        driver.execute_script("window.stop();")


    def next_page(self):
        driver = self.driver

        self.stop_loading_page_when_element_is_present(self.SRC.INPUT['NEXT_PAGE'])
        driver.execute_script("window.stop();")
    
        try:
            driver.find_element(*self.SRC.INPUT['NEXT_PAGE']).click()
            print("Navigating to Next Page")
        except (TimeoutException, WebDriverException):
            print("Last page reached")
        
  
        
class SearchResults(BasePage):
    """Search results page action methods come here"""

    def __init__(self, driver, SRC):
        super().__init__(driver, SRC)
        self.driver = driver
        self.SRC = SRC

    def wait_for_page_to_load(self):
        driver = self.driver
        wait = WebDriverWait(driver, 100)
        wait.until(
            EC.presence_of_element_located(*self.SRC.INPUT['MAIN_BODY']))
    
    def get_single_element(self, name):
        """Returns a single value as target data."""
        driver = self.driver
        target_data = driver.find_element(*self.SRC.OUTPUT[str(name.upper())])

        return target_data
    
    def number_of_items_found(self):
        """Return the number of items found on a single page."""
        driver = self.driver
        target_data = driver.find_elements(*self.SRC.OUTPUT['INDEX'])
        
        return len(target_data)
    

    def get_elements(self, name):
        """Returns simple list of values in specific data field in a table."""
        driver = self.driver
        target_data = driver.find_elements(*self.SRC.OUTPUT[str(name.upper())])
        
        for item in target_data:
            yield item.text
        


    def get_structured_elements(self, name):
        """For target data that is nested and structured,
        such as a table with multiple values in a single cell."""
        driver = self.driver

        i = 2 # keep track of 'i' to retain the document structure.
        number_of_items = self.number_of_items_found()
        elements = [None] * number_of_items

        # Manage split-xpaths for iteration.
        front_half, back_half = self.SRC.OUTPUT['SPLIT_XPATHS'][str(name.upper())]

        while i - 2 < number_of_items:
            
            target_data = driver.find_elements_by_xpath(front_half + str(i) + back_half)

            for item in target_data:
                print(item.text, i - 1)
                if elements[i - 2] == None:
                    elements[i - 2] = item.text
                elif isinstance(elements[i - 2], list):
                    elements[i - 2].append(item.text)
                else:
                    elements[i - 2] = [elements[i - 2]]
                    elements[i - 2].append(item.text)
            i += 1
    
        return elements
    

    def simple_get_structured_elements(self):
        """Simple structured elements code with fixed xpath.
        FOR DEBUGGING."""
        driver = self.driver

        i = 2 # keep track of 'i' to retain the document structure.
        number_of_items = self.number_of_items_found()
        elements = [None] * number_of_items
        
        while i - 2 < number_of_items:
            target_data = driver.find_elements_by_xpath
            ('//*[@id="Form1"]/table/tbody/tr[2]/td/table/tbody/tr['
                 + str(i) + ']/td[2]/a')

            for item in target_data:
                print(item.text, i-1)
                if elements[i - 2] == None:
                    elements[i - 2] = item.text
                elif isinstance(elements[i - 2], list):
                    elements[i - 2].append(item.text)
                else:
                    elements[i - 2] = [elements[i - 2]]
                    elements[i - 2].append(item.text)
            i += 1

        return elements

locators.py

# -*- coding: utf-8 -*-
from selenium.webdriver.common.by import By

# All locators specific to a certian web domain goes here, organized into classes.

class CNKI:
    URL = 'http://big5.oversea.cnki.net/kns55/'

    INPUT = {
        "MAIN_BODY": (By.XPATH, '//GridTableContent/tbody'),
        "SEARCH_FIELD": (By.NAME, 'txt_1_value1'), 
        "SEARCH_ATTR": (By.XPATH, '//select[@name = txt_1_sel]'), # dropdown list xpath.
        "SEARCH_BUTTON": (By.ID, 'btnSearch'),
        "NEXT_PAGE": (By.LINK_TEXT, "下頁"),
        "MAX_CONTENT": (By.CSS_SELECTOR, '#id_grid_display_num > a:nth-child(3)'), 
    }

    OUTPUT = {
        # Xpaths split at row number to be iterated, "i".
        "SPLIT_XPATHS": {
            "TITLES": ('//*[@id="Form1"]/table/tbody/tr[2]/td/table/tbody/tr[', ']/td[2]/a'),
            "AUTHORS": ('//*[@id="Form1"]/table/tbody/tr[2]/td/table/tbody/tr[', ']/td[3]/a')
    },
        "JOURNALS": (By.XPATH,'//*[@id="Form1"]/table/tbody/tr[2]/td/table/tbody/tr/td[4]/a'),
        "YEAR_ISSUE": (By.XPATH,'//*[@id="Form1"]/table/tbody/tr[2]/td/table/tbody/tr/td[5]/a'),
        "DOWNLOAD_PATHS": (By.XPATH,'//*[@id="Form1"]/table/tbody/tr[2]/td/table/tbody/tr/td[1]/table/tbody/tr/td/a[1]'), 
        "INDEX": (By.XPATH, '//*[@id="Form1"]/table/tbody/tr[2]/td/table/tbody/tr/td[1]/table/tbody/tr/td/a[2]')
    }

    # //*[@id="Form1"]/table/tbody/tr[2]/td/table/tbody/tr[2]/td[1]/table/tbody/tr/td/a[2]
    # //*[@id="Form1"]/table/tbody/tr[2]/td/table/tbody/tr[3]/td[1]/table/tbody/tr/td/a[2]

element.py

# -*- coding: utf-8 -*-
from selenium.webdriver.support.ui import WebDriverWait


class BasePageElement:
    """Base page class that is initialized on every page object class."""
    
    def __set__(self, obj, value):
        """Sets the text to the value supplied"""
        driver = obj.driver
        
        text_field = WebDriverWait(driver, 100).until(
            lambda driver: driver.find_element(*self.locator))
        text_field.clear()
        text_field.send_keys(value)
        text_field.submit()

    def __get__(self, obj, owner):
        """Gets the text of the specified object"""
        driver = obj.driver
        
        WebDriverWait(driver, 100).until(
            lambda driver: driver.find_element(*self.locator))
        element = driver.find_element(*self.locator)
        return element.get_attribute("value")
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

Long story short, you've captured the wrong things in classes. You've put too much effort into centralizing your locators, which - first of all - shouldn't be centralized, and - second of all - are written in a fragile, over-expressed XPath style. You seem to be under the impression that every single level of the DOM needs to be written out in the expression and every index made explicit, when this is not so.

The one class you really should have made that you haven't is a result set class to represent one row. Don't go to the trouble of having your API ask for one particular field to parse out (and certainly not specified via string); just parse them all. It's no extra network traffic thus barely any extra time.

Also consider discarding some images and extraneous requests via proxy.py. This part works, though I haven't measured the speedup.

Suggested

from contextlib import contextmanager
from dataclasses import dataclass
from datetime import date
from pathlib import Path
from typing import Iterable, Optional, ContextManager
from urllib.parse import unquote

# pip install proxy.py
import proxy
from proxy.http.exception import HttpRequestRejected
from proxy.http.parser import HttpParser
from proxy.http.proxy import HttpProxyBasePlugin
from selenium.common.exceptions import (
    NoSuchElementException,
    StaleElementReferenceException,
    TimeoutException,
    WebDriverException,
)
from selenium.webdriver import Firefox, FirefoxOptions, FirefoxProfile
from selenium.webdriver.common.by import By
from selenium.webdriver.common.proxy import ProxyType
from selenium.webdriver.remote.webdriver import WebDriver
from selenium.webdriver.remote.webelement import WebElement
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait


@dataclass
class Result:
    title: str        # Mozi's Theory of Human Nature and Politics
    title_link: str   # http://big5.oversea.cnki.net/kns55/detail/detail.aspx?recid=&FileName=ZDXB202006009&DbName=CJFDLAST2021&DbCode=CJFD
    html_link: Optional[str]  # http%3a%2f%2fkns.cnki.net%2fKXReader%2fDetail%3fdbcode%3dCJFD%26filename%3dZDXB202006009
    author: str       # Xie Qiyang
    source: str       # Vocational University News
    source_link: str  # http://big5.oversea.cnki.net/kns55/Navi/ScdbBridge.aspx?DBCode=CJFD&BaseID=ZDXB&UnitCode=&NaviLink=%e8%81%8c%e5%a4%a7%e5%ad%a6%e6%8a%a5
    published: date   # 2020-12-28
    database: str     # Periodical

    @classmethod
    def from_row(cls, row: WebElement) -> 'Result':
        number, title, author, source, published, database = row.find_elements_by_xpath('td')

        title_links = title.find_elements_by_tag_name('a')
        if len(title_links) > 1:
            # 'http://big5.oversea.cnki.net/kns55/ReadRedirectPage.aspx?flag=html&domain=http%3a%2f%2fkns.cnki.net%2fKXReader%2fDetail%3fdbcode%3dCJFD%26filename%3dZDXB202006009'
            html_link = unquote(
                title_links[1]
                .get_attribute('href')
                .split('domain=', 1)[1]
            )
        else:
            html_link = None

        published_date = date.fromisoformat(
            published.text.split(maxsplit=1)[0]
        )

        return cls(
            title=title_links[0].text,
            title_link=title_links[0].get_attribute('href'),
            html_link=html_link,
            author=author.text,
            source=source.text,
            source_link=source.get_attribute('href'),
            published=published_date,
            database=database.text,
        )

    def __str__(self):
        return (
            f'題名      {self.title}'
            f'\n作者     {self.author}'
            f'\n來源     {self.source}'
            f'\n發表時間  {self.published}'
            f'\n來源數據庫 {self.database}'
        )


class MainPage:
    def __init__(self, driver: WebDriver):
        self.driver = driver

    def submit_search(self, keyword: str) -> None:
        wait = WebDriverWait(self.driver, 50)
        search = wait.until(
            EC.presence_of_element_located((By.NAME, 'txt_1_value1'))
        )
        search.send_keys(keyword)
        search.submit()

    def switch_to_frame(self) -> None:
        wait = WebDriverWait(self.driver, 100)
        wait.until(
            EC.presence_of_element_located((By.XPATH, '//iframe[@name="iframeResult"]'))
        )
        self.driver.switch_to.default_content()
        self.driver.switch_to.frame('iframeResult')

        wait.until(
            EC.presence_of_element_located((By.XPATH, '//table[@class="GridTableContent"]'))
        )

    def max_content(self) -> None:
        """Maximize the number of items on display in the search results."""
        max_content = self.driver.find_element(
            By.CSS_SELECTOR, '#id_grid_display_num > a:nth-child(3)',
        )
        max_content.click()

    def get_element_and_stop_page(self, *locator) -> WebElement:
        ignored_exceptions = (NoSuchElementException, StaleElementReferenceException)
        wait = WebDriverWait(self.driver, 30, ignored_exceptions=ignored_exceptions)
        elm = wait.until(EC.presence_of_element_located(locator))
        self.driver.execute_script("window.stop();")
        return elm

    def next_page(self) -> None:
        link = self.get_element_and_stop_page(By.LINK_TEXT, "下頁")

        try:
            link.click()
            print("Navigating to Next Page")
        except (TimeoutException, WebDriverException):
            print("Last page reached")


class SearchResults:
    def __init__(self, driver: WebDriver):
        self.driver = driver

    def get_structured_elements(self) -> Iterable[Result]:
        rows = self.driver.find_elements_by_xpath(
            '//table[@class="GridTableContent"]//tr[position() > 1]'
        )

        for row in rows:
            yield Result.from_row(row)


class ContentFilterPlugin(HttpProxyBasePlugin):
    HOST_WHITELIST = {
        b'ocsp.digicert.com',
        b'ocsp.sca1b.amazontrust.com',
        b'big5.oversea.cnki.net',
    }

    def handle_client_request(self, request: HttpParser) -> Optional[HttpParser]:
        host = request.host or request.header(b'Host')
        if host not in self.HOST_WHITELIST:
            raise HttpRequestRejected(403)

        if any(
            request.path.endswith(suffix)
            for suffix in (
                b'.png', b'.ico', b'.jpg', b'.gif', b'.css',
            )
        ):
            raise HttpRequestRejected(403)

        return request

    def before_upstream_connection(self, request):
        return super().before_upstream_connection(request)
    def handle_upstream_chunk(self, chunk):
        return super().handle_upstream_chunk(chunk)
    def on_upstream_connection_close(self):
        pass


@contextmanager
def run_driver() -> ContextManager[WebDriver]:
    prox_type = ProxyType.MANUAL['ff_value']
    prox_host = '127.0.0.1'
    prox_port = 8889

    profile = FirefoxProfile()
    profile.set_preference('network.proxy.type', prox_type)
    profile.set_preference('network.proxy.http', prox_host)
    profile.set_preference('network.proxy.ssl', prox_host)
    profile.set_preference('network.proxy.http_port', prox_port)
    profile.set_preference('network.proxy.ssl_port', prox_port)
    profile.update_preferences()

    options = FirefoxOptions()
    options.headless = True

    plugin = f'{Path(__file__).stem}.{ContentFilterPlugin.__name__}'

    with proxy.start((
        '--hostname', prox_host,
        '--port', str(prox_port),
        '--plugins', plugin,
    )), Firefox(profile, options=options) as driver:
        yield driver


def cnki_search() -> None:
    with run_driver() as driver:
        driver.get('http://big5.oversea.cnki.net/kns55/')

        page = MainPage(driver)
        page.submit_search('人性論')
        page.switch_to_frame()
        page.max_content()

        result_page = SearchResults(driver)
        results = result_page.get_structured_elements()
        for result in results:
            print(result)
            print()

        page.next_page()


if __name__ == '__main__':
    cnki_search()

Output

題名      墨子的人性論與政治
作者     解啟揚
來源     職大學報
發表時間  2020-12-28
來源數據庫 期刊

題名      《易傳》以氣論性的人性論探析
作者     任鵬程
來源     周易研究
發表時間  2018-12-20
來源數據庫 期刊

題名      人性論研究的新視域與新路徑
作者     金辛迪
來源     倫理學研究
發表時間  2019-01-15
來源數據庫 期刊

題名      繼成的人性論:道體論的論點
作者     楊儒賓
來源     中國文化
發表時間  2019-10-31
來源數據庫 期刊

題名      淺析柏拉圖的人性論
作者     黃彩燕
來源     教育教學論壇
發表時間  2018-02-07
來源數據庫 期刊

題名      從道德教化的維度對孟荀人性論的再考察
作者     閆詠梅
來源     北京教育學院學報
發表時間  2018-03-21
來源數據庫 期刊

題名      馬克思主義視野中的人性理論
作者     葛晨虹
來源     齊魯學刊
發表時間  2018-07-15
來源數據庫 期刊

題名      《黃帝四經》人性論的理論邏輯與思想史意義
作者     白延輝
來源     中國哲學史
發表時間  2018-11-25
來源數據庫 期刊

題名      論先秦儒家人性論與道德人格培養
作者     譚清華
來源     井岡山大學學報(社會科學版)
發表時間  2018-07-15
來源數據庫 期刊

題名      基于人性論分析教育學理論體系的重構思路
作者     田艷麗
來源     山東農業工程學院學報
發表時間  2018-10-15
來源數據庫 期刊

題名      戴震的自然必然本然人性論說探微
作者     陶武
來源     學術界
發表時間  2016-09-15
來源數據庫 期刊

題名      教育理論的基礎——“人性論”問題
作者     徐彩霞
來源     佳木斯職業學院學報
發表時間  2016-11-15
來源數據庫 期刊

題名      共享的危機與共享機制的建構——基于人性論與制度博弈的視角
作者     張云飛
來源     當代中國價值觀研究
發表時間  2017-04-25
來源數據庫 期刊

題名      本體論基礎上的張載“人性論”研究
作者     彭欣欣
來源     西安石油大學學報(社會科學版)
發表時間  2017-08-15
來源數據庫 期刊

題名      論《福樂智慧》中的人性論及其現實意義
作者     宋雪蕊
來源     喀什大學學報
發表時間  2017-03-30
來源數據庫 期刊

題名      先秦法家人性論及其現代批判
作者     魏治勛
來源     山東科技大學學報(社會科學版)
發表時間  2016-10-15
來源數據庫 期刊

題名      從正名論推出人性論:董仲舒人性學說新探
作者     王冬
來源     衡水學院學報
發表時間  2016-10-20
來源數據庫 期刊

題名      孟子人性論思想及當代價值
作者     楊經偉
來源     華北水利水電大學學報(社會科學版)
發表時間  2016-10-15
來源數據庫 期刊

題名      張載與王夫之人性論思想比較研究
作者     黃聰
來源     商丘職業技術學院學報
發表時間  2014-06-17
來源數據庫 期刊

題名      錢穆人性論思想略論
作者     劉為光
來源     科教文匯(中旬刊)
發表時間  2015-02-20
來源數據庫 期刊

題名      論儒家自然人性論與禮樂教育的關系
作者     張斯珉
來源     東北師大學報(哲學社會科學版)
發表時間  2014-01-20
來源數據庫 期刊

題名      1957-1960年間的《長生殿》討論:人性論及其批判
作者     劉莘
來源     重慶師范大學學報(哲學社會科學版)
發表時間  2013-10-25
來源數據庫 期刊

題名      梁實秋莎評的人性論特征及其意義
作者     李偉昉
來源     外國文學研究
發表時間  2011-04-25
來源數據庫 期刊

題名      韓愈的人性論和教育倫理思想研究
作者     王東生
來源     河北軟件職業技術學院學報
發表時間  2011-03-25
來源數據庫 期刊

題名      董仲舒人性論思想及其評析
作者     徐睿
來源     科教導刊(中旬刊)
發表時間  2011-05-15
來源數據庫 期刊

題名      人性論對于政治發展的啟示
作者     陳媛
來源     改革與開放
發表時間  2011-07-25
來源數據庫 期刊

題名      “階級論”與“人性論”的文學史構建——以唐弢《現代文學史》和陳思和《當代文學史教程》為例
作者     唐偉
來源     海南廣播電視大學學報
發表時間  2011-12-26
來源數據庫 期刊

題名      先秦儒家人性論及其演變
作者     韓麗華
來源     南華大學學報(社會科學版)
發表時間  2011-12-28
來源數據庫 期刊

題名      基于人性論的教育學學科體系建構
作者     楊兆山
來源     教育研究
發表時間  2010-04-15
來源數據庫 期刊

題名      管子與韓非人性論之比較
作者     韓廣忠
來源     寶雞文理學院學報(社會科學版)
發表時間  2010-06-20
來源數據庫 期刊

題名      論左傳周易所體現的人性論思想
作者     朱金發
來源     晉陽學刊
發表時間  2010-09-25
來源數據庫 期刊

題名      淺淡古希臘人性論
作者     崔淑芳
來源     山東行政學院山東省經濟管理干部學院學報
發表時間  2009-02-15
來源數據庫 期刊

題名      藏通別圓視野下的人性論——天臺智者大師人性學說解析
作者     王正
來源     柳州師專學報
發表時間  2009-02-15
來源數據庫 期刊

題名      悖立與整合——論董仲舒對孟子、荀子之人性論的解釋
作者     劉國民
來源     衡水學院學報
發表時間  2009-06-20
來源數據庫 期刊

題名      王夫之別開生面的人性論探析
作者     謝芳
來源     南華大學學報(社會科學版)
發表時間  2009-08-28
來源數據庫 期刊

題名      作為保守主義者的梁實秋——以人性論為例
作者     張勁松
來源     海南師范大學學報(社會科學版)
發表時間  2008-07-30
來源數據庫 期刊

題名      試論荀子人性論的兩重性
作者     石洪波
來源     中國社會科學院研究生院學報
發表時間  2008-01-15
來源數據庫 期刊

題名      先秦儒學人性論梳析
作者     潘永輝
來源     茂名學院學報
發表時間  2006-04-30
來源數據庫 期刊

題名      馬克思主義對古希臘人學思想的批判繼承
作者     向仲敏
來源     西南交通大學學報(社會科學版)
發表時間  2006-04-30
來源數據庫 期刊

題名      簡析基督教的人性論
作者     尚九玉
來源     鄭州大學學報(哲學社會科學版)
發表時間  2006-05-25
來源數據庫 期刊

題名      思想道德修養的人性論基礎
作者     劉海鷗
來源     大學教育科學
發表時間  2006-10-28
來源數據庫 期刊

題名      孔子人性論思想探析
作者     胡敏
來源     攀登
發表時間  2005-12-05
來源數據庫 期刊

題名      《樂記》人性論思想淺議
作者     李盛龍
來源     宜賓學院學報
發表時間  2005-10-25
來源數據庫 期刊

題名      “人性論”與中西法律傳統
作者     王惠昌
來源     河南公安高等專科學校學報
發表時間  2004-08-30
來源數據庫 期刊

題名      行政管理的變遷——從人性論的角度透視
作者     王琦
來源     西南農業大學學報(社會科學版)
發表時間  2004-09-30
來源數據庫 期刊

題名      關于韓非子人性論的一點認識
作者     孫嘉琪
來源     培訓與研究(湖北教育學院學報)
發表時間  2004-12-20
來源數據庫 期刊

題名      論梁實秋人性論的性質及其演變
作者     高旭東
來源     理論學刊
發表時間  2004-12-20
來源數據庫 期刊

題名      逆性與順性——荀子人性論的內在緊張
作者     周熾成
來源     孔子研究
發表時間  2003-01-25
來源數據庫 期刊

題名      董仲舒人性論淺議
作者     高春菊
來源     衡水師專學報
發表時間  2003-03-10
來源數據庫 期刊

題名      “人性”的獨特思考——淺析梁實秋的人性論
作者     顧金春
來源     江蘇教育學院學報(社會科學版)
發表時間  2003-08-25
來源數據庫 期刊

Navigating to Next Page
\$\endgroup\$
14
  • \$\begingroup\$ I cannot run your code - module proxy is not found even after installation is successful in all my machines and virtual environments. \$\endgroup\$
    – Sati
    Commented Jun 9, 2021 at 5:59
  • \$\begingroup\$ UPDATE: It ran successfully without including the inclusion of ContentFilterPlugin. \$\endgroup\$
    – Sati
    Commented Jun 9, 2021 at 6:04
  • \$\begingroup\$ I need to study this a bit because the @dataclass approach is new to me. It's been very eye-opening to learn a new way of looking at the design problem. Thank you. \$\endgroup\$
    – Sati
    Commented Jun 9, 2021 at 6:10
  • \$\begingroup\$ Another issue is: I don't actually need all the information on each row of the table - just the author, title, date and source(journal) will do. For hyperlinks, I would need the download link just before each serial number, as well as the html article link beside the title, if that is available. \$\endgroup\$
    – Sati
    Commented Jun 9, 2021 at 8:34
  • 1
    \$\begingroup\$ Potentially, though a to_bib_file instance method would be a better fit \$\endgroup\$
    – Reinderien
    Commented Jun 9, 2021 at 10:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.