我正试图解析 https:/www.tandfonline.comtocicbi20current 为所有文章的标题。该 HTML
分为卷和期。每一卷有一个问题,对应一个月。所以第36卷有12期。在当前的卷(37)中,有4个问题,我想解析每个问题,并得到每个文章的名字。
为了达到这个目的,并自动搜索,我需要取得 href
每期的链接。最初我选择了父母的 div
id
: id = 'tocList'
.
import requests
from bs4 import BeautifulSoup, SoupStrainer
chronobiology = requests.get("https://www.tandfonline.com/toc/icbi20/current")
chrono_coverpage = chronobiology.content
issues = SoupStrainer(id ='tocList')
issues_soup = BeautifulSoup(chrono_coverpage, 'html.parser', parse_only = issues)
for issue in issues_soup:
print(issue)
返回一个bs4对象 但是 只与 href
从卷的链接 div
. 更糟糕的是,这个 div
应包括以下两个方面 div
和问题 div
.
所以,我决定尝试减少我的搜索空间,使其更具体,并选择了。div
含有发行的 href
链接 (class_='issues'
)
这个时候木星会思考一下,但不会返回anything。只是空白。什么都没有。Zippo。但是... 如果我问什么类型的 "nothing "已经返回,木星通知它是一个"String
"??? 我就不知道该怎么说了。
所以,首先我有一个问题,为什么《问题》中的 div
元素不响应解析?当我尝试运行 print(BeautifulSoup(chrono_coverpage, 'html.parser').prettify())
同样的情况发生,问题 div
不出现(当 Inspect Element
在...上 html
页,它紧贴在最后一卷的下面。span
):
所以我怀疑它一定是面向javascript或其他什么的,而不是面向HTML。也可能是 class = 'open'
有什么关系。
如有任何说明,敬请谅解。另外,如何解析Javascript链接来获取它们?
好的,所以我已经"决心"的问题,不过我需要填补一些理论上的空白。
首先,这个片段是解题的关键所在。
正如我们所看到的 <div class = 'container'>
紧接着是一个 ::before
伪元素和我感兴趣的链接都包含在一个 div
紧挨着这个伪元素的下面。最后这个 div
然后,完成与 ::after
伪元素。
首先我意识到我的问题是我需要选择一个伪元素。我发现这在 BeutifulSoup
's soup.select()
既然 BeautifulSoup
用途 Soup Sieve
其中"旨在允许用户使用CSS选择器来锁定XMLHTML元素。它实现了许多伪类[...]。"
该段的最后一部分说:
"汤筛子也不会匹配任何东西的 伪类,只有在实时的浏览器环境中才有意义。, 但如果它们已经实施,它将优雅地处理它们。;"
所以这让我想到,我不知道 "只有在实时浏览器环境下才有意义的伪类 "是什么意思。但我又对自己说:"但它也说,如果实现了它们,BS4应该可以解析它们"。既然我肯定能看到 div
含有我 href
感兴趣的链接 Inspect
工具,我虽说一定要落实。
这句话的第一部分就引起了我的思考。"但我需要一个实时浏览器来工作吗?"
所以这让我想到了 Selenium
的网络驱动程序。
import requests
from bs4 import BeautifulSoup, SoupStrainer
from selenium import webdriver
driver = webdriver.Chrome()
url_chronobiology = driver.get("https://www.tandfonline.com/toc/icbi20/current")
chronobiology_content = driver.page_source
chronobiology_soup = BeautifulSoup(chronobiology_content)
chronobiology_soup.select('#tocList > div > div > div.yearContent > div.issues > div > div')
[Out]: []
显然,这个结果让我很伤心,因为我以为我已经明白是怎么回事了。但后来我想,如果我从之前打开的浏览器中 "点击 "其中一个问题,它就会工作(出于某种原因,说实话,我很确定是绝望让我产生了这种想法)。
好吧,我知道了。惊讶 惊喜: 竟然成功了。在点击 "第四期 "后,重新运行... script
我得到了我想要的东西。
未回答的问题?
1 - 显然,这些伪元素只有""。存在",否则代码就无法识别它们的存在。为什么要这样做?
2 - 必须运行哪些代码才能进行初始点击并激活这些伪元素,这样代码才能自动打开这些链接并解析我想要的信息?(文章标题)
更新
问题2使用Selenium的ActionChain来回答。
import requests
from bs4 import BeautifulSoup, SoupStrainer
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
driver = webdriver.Chrome()
url_chronobiology = driver.get("https://www.tandfonline.com/toc/icbi20/current")
chronobiology_content = driver.page_source
chronobiology_soup = BeautifulSoup(chronobiology_content)
action=ActionChains(driver)
action.move_to_element(driver.find_element_by_xpath('//*[@id="tocList"]/div/div/div[3]/div[2]/div')).perform()
chronobiology_soup.select('#tocList > div > div > div.yearContent > div.issues > div > div')
[Out]:
[<div class="loi-issues-scroller">
<a class="open" href="/toc/icbi20/37/4?nav=tocList">Issue<span>4</span></a>
<a class="" href="/toc/icbi20/37/3?nav=tocList">Issue<span>3</span></a>
<a class="" href="/toc/icbi20/37/2?nav=tocList">Issue<span>2</span></a>
<a class="" href="/toc/icbi20/37/1?nav=tocList">Issue<span>1</span></a>
</div>]
唯一的缺点是 是一个人必须留在页面上为 Selenium
's ActionChain.perform()
可以实际点击该元素。不过 至少我已经自动完成了这一步。
如果有人能 回答问题1 那就好了