刚开始使用 python 进行网页抓取,我遇到了一些问题。
我开始使用 Selenium 下载网页的源代码并保存它:
from selenium import webdriver
driver= webdriver.Firefox()
driver.get("https://www.website.com")
f=open('output.txt','w')
f.write(driver.page_source.encode('utf-8'))
f.close()
driver.quit()
一切正常,但是Selenium太耗时,所以我首先转向 Mechanize ,获取页面源:
import mechanize
browser = mechanize.Browser()
browser.set_handle_robots(False)
cookies = mechanize.CookieJar()
browser.set_cookiejar(cookies)
browser.addheaders = [('User-agent', 'Mozilla/5.0')]
browser.set_handle_refresh(False)
browser.open("https://www.website.com")
问题来了:如果我尝试通过它的 id 找到一个特定的 div,它没有返回给我:
from bs4 import BeautifulSoup as BS
soup= BS(browser.response().read(),'lxml')
print(soup.find(id="div_id"))
虽然如果我使用常规文本编辑器检查通过 mechanize 获得的源代码,我可以找到它。它是这样的:
<div id="div_id" data referrer="div_id">
这个 div 有许多其他子元素,它位于代码的大约 1/5“内”,完整的源代码大约 500kb。如果我尝试寻找附近的其他 div,也没有运气。而如果我在源代码开头附近寻找一些 div,它会找到它。更有趣的是,如果我尝试在使用 Selenium 获得的源代码中寻找相同的 div(使用 BS),而不是获得的那个使用 Mechanize,它能够找到它,尽管通过文本编辑器检查 div 看起来完全相同。
我尝试了所有 BS 支持的解析器,但没有成功。所以我认为它可能与 BS 有关,我尝试对 lxml 做同样的事情:
from lxml import etree
parser= etree.HTMLParser()
tree= etree.parse(open('source.txt'),parser)
results= tree.xpath('//div[@id="div_id"]')
print(etree.tostring(results[0]))
与 BS 一样,它能够在使用 Selenium 获得的源代码中找到 div,但不能使用 Mechanize。于是想到可能跟Mechanize有关系,转而使用Requests:
import requests
from fake_useragent import UserAgent
ua=UserAgent()
url= 'https://www.website.com'
headers= {'User-agent': str(ua.chrome)}
page = requests.get(url, headers=headers)
当使用 BS 或 lxml 查看 div 的 page.content 时,同样没有运气。无论我直接分析响应还是将其保存到文件中然后分析文件,都会发生这种情况。
我认为仅此而已...我还尝试对 Mechanize 和 Requests 响应进行编码,正如我所看到的那样,我是使用 Selenium 完成的,但没有任何变化。我也尝试使用其他 BS 版本 (3.x),没有变化。
总结一下: - 如果我在通过 Selenium 获得的源代码中寻找带有 BS 或 lxml 的 div,它会找到它。对于其他的,没有。 - 如果我在源代码的开头查找其他 div,BS 和 lxml 会找到它,与用于获取代码的方法无关。 - 经检查,div 在所有情况下都存在。
使用的版本: - python :2.7.9 -BeautifulSoup:4.6.0 - Mechanize :0.3.5 -要求:2.18.4 - Selenium :3.5.0 -lxml:4.0.0 -操作系统:linux debian
谢谢。
最佳答案
您要查找的 div 隐藏在可能通过 Javascript 处理的 HTML 注释中。您仍然可以使用 requests
首先提取隐藏的 HTML,如下所示:
from bs4 import BeautifulSoup, Comment
import requests
id = "pagelet_forsale_island"
r = requests.get("https://www.facebook.com/groups/1584160618524185/")
soup = BeautifulSoup(r.content, "html.parser")
for comment in soup.find_all(string=lambda text:isinstance(text, Comment)):
if id in comment:
hidden_soup = BeautifulSoup(comment, "html.parser")
for div in hidden_soup.find_all('div', id=id):
print div
这让 BeautifulSoup 找到 HTML 中的所有评论,然后确定是否有任何包含您的 id
.如果找到匹配项,评论本身将再次传递给 BeautifulSoup 以进行进一步处理。这将显示您的 <div>
作为:
<div data-referrer="pagelet_forsale_island" id="pagelet_forsale_island"></div>
关于python - BeautifulSoup 和 lxml 找不到 div 元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46348050/