【问题标题】:How to retrieve the values of dynamic html content using Python如何使用 Python 检索动态 html 内容的值
【发布时间】:2013-07-09 23:07:50
【问题描述】:

我正在使用 Python 3,并且正在尝试从网站检索数据。但是,这些数据是动态加载的,我现在的代码不起作用:

url = eveCentralBaseURL + str(mineral)
print("URL : %s" % url);

response = request.urlopen(url)
data = str(response.read(10000))

data = data.replace("\\n", "\n")
print(data)

在我试图找到一个特定值的地方,我找到了一个模板,例如“{{formatPrice median}}”而不是“4.48”。

我怎样才能使我可以检索值而不是占位符文本?

编辑:This 是我试图从中提取信息的特定页面。我正在尝试获取使用模板 {{formatPrice median}}

的“中值”值

编辑 2:我已经安装并设置了我的程序以使用 Selenium 和 BeautifulSoup。

我现在的代码是:

from bs4 import BeautifulSoup
from selenium import webdriver

#...

driver = webdriver.Firefox()
driver.get(url)

html = driver.page_source
soup = BeautifulSoup(html)

print "Finding..."

for tag in soup.find_all('formatPrice median'):
    print tag.text

Here 是程序执行时的屏幕截图。不幸的是,它似乎没有找到任何指定“formatPrice 中位数”的东西。

【问题讨论】:

  • 在浏览器中访问网址时,是否得到模板标签?编辑:另外,您的模板是如何呈现的。如果您使用的是 javascript 模板引擎(例如 Handlebars),这可能意味着您将在响应中获得模板标签。
  • RE 编辑 2 - 这只是一个新问题......无论如何,我认为您需要查看 find_all 的文档,因为您的 find_all 字符串无效。我将在下面更新一些更接近您需要的内容crummy.com/software/BeautifulSoup/bs3/…
  • 干杯!我尝试使用soup.findall(True) 来获取所有标签,而我需要的信息就在那里!只需准确找到我需要搜索哪个标签来获取该信息。

标签: python html templates urllib


【解决方案1】:

假设您尝试从使用 javascript 模板(例如 handlebars 之类的东西)呈现的页面中获取值,那么这就是您将使用任何标准解决方案(即 beautifulsoup 或 @987654330 @)。

这是因为浏览器使用 javascript 来更改它收到的内容并创建新的 DOM 元素。 urllib 将像浏览器一样执行请求部分,而不是模板渲染部分。 A good description of the issues can be found here。本文讨论了三个主要的解决方案:

  1. 直接解析ajax JSON
  2. 使用离线Javascript解释器处理请求SpiderMonkey,crowbar
  3. 使用浏览器自动化工具splinter

This answer 为选项 3 提供了更多建议,例如 selenium 或 watir。我使用 selenium 进行自动化 Web 测试,它非常方便。


编辑

从您的 cmets 看来,它是一个由车把驱动的站点。我推荐硒和美丽的汤。 This answer 提供了一个很好的代码示例,可能有用:

from bs4 import BeautifulSoup
from selenium import webdriver
driver = webdriver.Firefox()
driver.get('http://eve-central.com/home/quicklook.html?typeid=34')

html = driver.page_source
soup = BeautifulSoup(html)

# check out the docs for the kinds of things you can do with 'find_all'
# this (untested) snippet should find tags with a specific class ID
# see: http://www.crummy.com/software/BeautifulSoup/bs4/doc/#searching-by-css-class
for tag in soup.find_all("a", class_="my_class"):
    print tag.text

基本上 selenium 从您的浏览器获取呈现的 HTML,然后您可以使用来自 page_source 属性的 BeautifulSoup 对其进行解析。祝你好运:)

【讨论】:

  • 感谢您的帮助。我对网络语言或基于网络的编程经验很少,但如果有帮助,我会链接我试图从中解析数据的网站。
  • 我也会开始研究 requests 和 beautifulsoup。
  • 我已经查看了该站点 - 加载几次几乎破坏了我的计算机 :) 是的,如果您是 Chrome,请按 F12 并且如果您转到“网络”选项卡,您会看到Backboneunderscorehandlebars 都已加载。我认为您将不得不采用selenium 方法。我将使用一些示例代码进行编辑
  • 再次感谢。我已经尝试了您推荐的内容并更新了我的帖子。 :)
  • 在服务器上使用的最佳解决方案是什么?在服务器(不是本地机器)上使用selenium 是一种好习惯吗? @will-hart
【解决方案2】:

我用硒+铬

 from selenium import webdriver
 from selenium.webdriver.chrome.options import Options

 url = "www.sitetotarget.com"
 options = Options()
 options.add_argument('--headless')
 options.add_argument('--disable-gpu')
 options.add_argument('--no-sandbox')
 options.add_argument('--disable-dev-shm-usage')`

【讨论】:

    【解决方案3】:

    建立另一个答案。我有一个类似的问题。 wget 和 curl 不再适用于获取网页的内容。动态和懒惰的内容尤其破坏了它。使用 Chrome(或 Firefox 或 Chromium 版本的 Edge)可以让您处理重定向和脚本。

    下面将启动一个 Chrome 实例,将超时时间增加到 5 秒,并将此浏览器实例导航到一个 url。我是从 Jupyter 运行的。

    import time
    from tqdm.notebook import trange, tqdm
    from PIL import Image, ImageFont, ImageDraw, ImageEnhance
    from selenium import webdriver
    driver = webdriver.Chrome('/usr/bin/chromedriver')
    driver.set_page_load_timeout(5)
    time.sleep(1)
    driver.set_window_size(2100, 9000)
    time.sleep(1)
    driver.set_window_size(2100, 9000)
    ## You can manually adjust the browser, but don't move it after this.
    ## Do stuff ...
    driver.quit()
    

    获取锚定(因此是“a”标签)HTML对象的动态内容和屏幕截图的示例,超链接的另一个名称:

    url = 'http://www.example.org' ## Any website
    driver.get(url)
    
    pageSource = driver.page_source
    print(driver.get_window_size())
    
    locations = []
    
    for element in driver.find_elements_by_tag_name("a"):
    
        location = element.location;
        size = element.size;
        # Collect coordinates of object: left/right, top/bottom 
        x1 = location['x'];
        y1 = location['y'];
        x2 = location['x']+size['width'];
        y2 = location['y']+size['height'];
        locations.append([element,x1,y1,x2,y2, x2-x1, y2-y1])
    locations.sort(key = lambda x: -x[-2] - x[-1])     
    locations = [ (el,x1,y1,x2,y2, width,height)
        for el,x1,y1,x2,y2,width,height in locations
        if not (        
                ## First, filter links that are not visible (located offscreen or zero pixels in any dimension)
                x2 <= x1 or y2 <= y1 or x2<0 or y2<0
                ## Further restrict if you expect the objects to be around a specific size
                ## or width<200 or height<100
               )
    ]
    
    for el,x1,y1,x2,y2,width,height in tqdm(locations[:10]):
        try:
            print('-'*100,f'({width},{height})')
            print(el.text[:100])
            element_png = el.screenshot_as_png
            with open('/tmp/_pageImage.png', 'wb') as f:
                f.write(element_png)
            img = Image.open('/tmp/_pageImage.png')
            display(img)
        except Exception as err:
            print(err)
    

    mac+chrome的安装:

    pip install selenium
    brew cask install chromedriver
    brew cask install google-chrome
    

    我使用 Mac 作为原始答案,并在更新后通过 WSL2 进行 Ubuntu + Windows 11 预览。 Chrome 在 Windows 上使用 X 服务从 Linux 端运行以呈现 UI。

    关于责任,请尊重每个网站上的 robots.txt。

    【讨论】:

      【解决方案4】:

      我知道这是一个老问题,但有时有比使用重硒更好的解决方案。

      这个用于 python 的request module 带有 JS 支持(在后台它仍然是铬),你仍然可以像往常一样使用 beautifulsoup。 不过,有时如果您必须单击元素或某事,我想硒是唯一的选择。

      【讨论】:

        猜你喜欢
        • 2021-12-22
        • 2013-04-01
        • 1970-01-01
        • 1970-01-01
        • 2013-02-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多