【发布时间】:2020-03-16 08:30:23
【问题描述】:
使用lxml提取p节点中的所有内容很简单,我从网页的p节点中提取所有内容,并使用以下代码将其写入文件/tmp/content1.txt。
import urllib.request
import lxml.html
url = 'https://www.statnews.com/pharmalot/2020/03/13/gilead-coronavirus-covid19-clinical-trials/'
ob=urllib.request.urlopen(url).read()
root=lxml.html.document_fromstring(ob)
content=root.xpath("//p")
with open('/tmp/content1.txt','w') as fh:
for etxt in content:
fh.write(etxt.text_content() + '\n')
现在用 selenium 做同样的工作,将解析后的内容写入content2.txt。
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
chrome_options = Options()
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument('--disable-dev-shm-usage')
chrome_options.add_argument("--headless")
browser = webdriver.Chrome(options=chrome_options,executable_path='/usr/bin/chromedriver')
wait = WebDriverWait(browser, 30)
url = 'https://www.statnews.com/pharmalot/2020/03/13/gilead-coronavirus-covid19-clinical-trials/'
browser.get(url)
wait.until(lambda e: e.execute_script('return document.readyState') != "loading")
wait.until(EC.presence_of_all_elements_located([By.CSS_SELECTOR, "p"]))
content = browser.find_elements_by_xpath('//p')
with open('/tmp/content2.txt','w') as fh:
for etxt in content:
fh.write(etxt.text + '\n')
按照 Svetlana Levinsohn 的建议进行操作:尝试删除 chrome_options.add_argument("--headless")。
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
chrome_options = Options()
chrome_options.add_argument('--no-sandbox')
chrome_options.add_argument('--disable-dev-shm-usage')
browser = webdriver.Chrome(options=chrome_options,executable_path='/usr/bin/chromedriver')
wait = WebDriverWait(browser, 30)
url = 'https://www.statnews.com/pharmalot/2020/03/13/gilead-coronavirus-covid19-clinical-trials/'
browser.get(url)
wait.until(lambda e: e.execute_script('return document.readyState') != "loading")
wait.until(EC.presence_of_all_elements_located([By.CSS_SELECTOR, "p"]))
content = browser.find_elements_by_xpath('//p')
with open('/tmp/content3.txt','w') as fh:
for etxt in content:
fh.write(etxt.text + '\n')
比较content1.txt和content2.txt和content3.txt。
cd /tmp
wc -c content1.txt
11442 content1.txt
wc -c content2.txt
838 content2.txt
wc -c /tmp/content3.txt
12105 /tmp/content3.txt
1.为什么用selenium删除chrome_options.add_argument("--headless")时会得到更多的行?为什么这个动作背后的原理是?
2.有没有办法用 selenium 和 lxml 获得相同的内容?
按照 supputuri 的建议,将最后一行更改为 fh.write(etxt.get_attribute("textContent") + '\n'),问题仍然存在。
wc -c content1.txt
12402 content1.txt
wc -c content2.txt
12410 content2.txt
让我们检查一下为什么 content2.txt 比 content1.txt 多 8 个字节。
diff content1.txt content2.txt
1c1
< By Ed Silverman @Pharmalot
---
> By Ed Silverman2 @Pharmalot3
3,4c3,4
< As anticipation mounts over the prospects for an experimental Gilead Sciences (GILD) drug to combat the novel coronavirus, two Wall Street analysts suggested it remains uncertain whether the antiviral therapy will be successful after assessing a new paper that examined a dozen U.S. patients.
< The paper, published on a preprint server without peer review, described the epidemiology, clinical course, and viral characteristics of the first 12 U.S. patients with Covid-19, only three of whom were treated with remdesivir, which was developed to treat the Ebola virus but shelved after proving less effective than other drugs during testing. The analysis was conducted by the Centers for Disease Control and Prevention Covid-19 response team.
---
> As anticipation mounts over the prospects for an experimental Gilead Sciences (GILD4) drug to combat the novel coronavirus, two Wall Street analysts suggested it remains uncertain whether the antiviral therapy will be successful after assessing a new paper that examined a dozen U.S. patients.
> The paper5, published on a preprint server without peer review, described the epidemiology, clinical course, and viral characteristics of the first 12 U.S. patients with Covid-19, only three of whom were treated with remdesivir, which was developed to treat the Ebola virus but shelved after proving less effective than other drugs during testing. The analysis was conducted by the Centers for Disease Control and Prevention Covid-19 response team.
22,24c22,24
< Coronavirus
< drug development
< research
---
> Coronavirus10
> drug development11
> research12
26c26
< Republish this article
---
> Republish this article13
59c59
< ????
---
>
content2.txt 中的字节,而不是 content1.txt 中的字节。
line1 2,3 线 3-4 4,5 线 22-24 10,11,12 第26行13
4 字节存储 2,3,4,5
8字节存储10,11,12,13
content1.txt 中的字节,而不是 content2.txt 中的字节。
line59 ????
对于??????,它需要4个字节f09f918d来存储。
4+8-4 = 8 = 12410-12402
注意:lxml 或 selenium 解析的内容是动态变化的,可能会得到 content1.txt 和 content2.txt 不同的字节。
是时候检查另一个重要问题了。
对于lxml解析的content1.txt的第一行。
By Ed Silverman @Pharmalot
对于 selenium 解析的 content2.txt 中的第一行。
By Ed Silverman2 @Pharmalot3
为什么selenium在这里添加2和3?selenium添加一些原始网页中没有的数字,它们是什么意思?
而且我从未见过 javascript 代码来更改网页的 dom 树。
获取get_attribute("textContent")时如何防止selenium加号?
Vladimir M 通知所有号码都在原始站点中。
我做了验证。
import urllib.request
import lxml.html
url = 'https://www.statnews.com/pharmalot/2020/03/13/gilead-coronavirus-covid19-clinical-trials/'
ob=urllib.request.urlopen(url).read()
root=lxml.html.document_fromstring(ob)
content=root.xpath("//p[@class='author']")[0]
lxml.html.tostring(content)
我们得到html源代码:
b'<p class="author">
<em>By</em>
<a ...>Ed Silverman</a>
<a ...>@Pharmalot</a>
</p>'
不要包含sup这样的标签Vladimir M显示:
<p class="author">
<em>By</em>
<a ...>Ed Silverman</a>
<sup class="footnote">3</sup>
<a ...>@Pharmalot</a>
<sup class="footnote">4</sup>
</p>
如果原始html源代码中包含sup标签,lxml中的text_content可以显示出来。
import lxml.html as lh
data = """<p class="author"><em>By</em> <a href="https://www.statnews.com/staff/ed-silverman/" \
class="author-name-link author-name author-main">Ed Silverman</a><sup class="footnote">3</sup> \
<a href="https://twitter.com/Pharmalot" class="author-social" target="_blank" rel="noopener"> \
@Pharmalot</a><sup class="footnote">4</sup> </p>"""
doc = lh.fromstring(data)
data = doc.xpath('//p')[0]
print(data.text_content())
输出如下:
By Ed Silverman3 @Pharmalot4
我推断sup 这两个标签是由一些javascript 代码创建的。
为了提高我的javascript知识,最后一个问题与js有关:
如何知道哪个js文件创建了位于<p class="author">节点的号码?
请回答并获得500分。
【问题讨论】:
-
尝试删除
chrome_options.add_argument("--headless"),可能会解决这个问题 -
找到至少一个元素时返回所有元素的存在:selenium.dev/selenium/docs/api/java/org/openqa/selenium/support/… 标准睡眠将是这里最简单的方法......(顺便说一句,你不需要第一次在那里等待,Selenium将在获取后等待就绪状态)
-
如果您检查源代码,如果它实际上是一个链接(锚),则会在文本中添加数字。
标签: python-3.x selenium