Python BeautifulSoup如何从伪元素/类获取href链接
我试图解析所有文章的标题。Python BeautifulSoup如何从伪元素/类获取href链接,python,selenium,web-scraping,beautifulsoup,Python,Selenium,Web Scraping,Beautifulsoup,我试图解析所有文章的标题。HTML分为卷和期。每卷都有一期,对应于一个月。因此,第36卷将有12期。在当前的卷(37)中有4个问题,我想分析每个问题并获得每篇文章的名称 为了实现这一点并自动搜索,我需要获取每个问题的href链接。最初,我选择了父级的divid:id='tocList' import requests from bs4 import BeautifulSoup, SoupStrainer chronobiology = requests.get("https://www.ta
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对象,但只返回卷div
中的href
链接。更糟糕的是,这个div
应该包括卷div
和发行div
因此,我决定尽量减少我的搜索空间,使其更加具体,并选择了包含问题href
链接的div
(class='issues'
)
这一次木星会想一想,但不会返回任何东西。一片空白。没有什么。齐波但是如果我问返回了什么类型的“nothing”,jupiter会通知它是一个“字符串”
”???我只是不知道该怎么办。
因此,首先我有一个问题,为什么Issuediv
元素不响应解析?
当我尝试运行print(BeautifulSoup(chrono_coverpage,'html.parser').prettify())
时,同样的情况也会发生,问题div
不会出现(当html
页面上的Inspect元素
时,它会立即出现在最终卷的下方span
):
所以我怀疑它一定是面向javascript或其他什么的,而不是太面向HTML。或者,class='open'
可能与此有关
如有任何澄清,将不胜感激。另外,如何通过Javascripted链接解析它们呢?好的,我已经解决了这个问题,尽管我需要填补一些理论空白:
首先,这段代码是解决问题的关键:
可以看到,
后面紧跟着一个::before
伪元素,我感兴趣的链接包含在这个伪元素下面的div中。最后一个div
用::after
伪元素完成
首先我意识到我的问题是我需要选择一个伪元素。我发现这对于BeutifulSoup
的soup.select()
是不可能的,因为显然BeutifulSoup
使用了soup-siever
,它“旨在允许用户使用CSS选择器以XML/HTML元素为目标。它实现了许多伪类[…]”
该段最后一部分指出:
“对于仅在实时浏览器环境中相关的伪类,,汤筛也不会匹配任何内容,但如果它们已经实现,它将优雅地处理它们。”
所以这让我觉得我不知道“只有在实时浏览器环境中才相关的伪类”是什么意思。但后来我对自己说,“但它也说,如果它们已经实现,BS4应该能够解析它们”。由于我可以使用Inspect
工具明确地看到div
元素,其中包含我感兴趣的href
链接,因此我认为我必须实现
这句话的第一部分让我思考:“但我需要一个实时浏览器才能工作吗?”
这让我想到了Selenium的web驱动程序:
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')
很明显,这个结果让我很伤心,因为我认为我已经明白发生了什么。但后来我想,如果我从之前打开的浏览器中“点击”了其中一个问题,它会起作用(出于某种原因,老实说,我很确定绝望让我产生了这种想法)
嗯,惊喜惊喜。它成功了:在点击“问题4”并重新运行脚本后,我得到了我想要的:
未回答的问题?
1-显然,这些伪元素只有在单击时才“存在”,因为否则代码无法识别它们。为什么?
2必须运行什么代码才能进行初始单击并激活这些伪元素,以便代码能够自动打开这些链接并解析我想要的信息?(文章标题)
更新
使用Selenium的ActionChain回答问题2:
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]:
[
]
唯一的缺点是人们必须停留在页面上查看Selenium
的ActionChain。perform()
实际上可以单击元素,但是至少我已经自动化了这一步
如果有人能回答问题1,那就太好了好的,所以我已经解决了这个问题,尽管我需要填补一些理论空白:
首先,这段代码是解决问题的关键:
可以看到,
后面紧跟着一个::before
伪元素,我感兴趣的链接包含在这个伪元素下面的div中。最后一个div
用::after
伪元素完成
首先我意识到我的问题是我需要选择一个伪元素。我发现这对于BeutifulSoup
的soup.select()
是不可能的,因为显然BeutifulSoup
使用了soup-siever
,它“旨在允许用户使用CSS选择器以XML/HTML元素为目标。它实现了许多伪类[…]”
该段最后一部分指出:
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>]