在支持 POST 的同时在不使用 Selenium 的情况下渲染 JSON/Javascript 后从网页中抓取 HTML

Posted

技术标签:

【中文标题】在支持 POST 的同时在不使用 Selenium 的情况下渲染 JSON/Javascript 后从网页中抓取 HTML【英文标题】:Scrape the HTML from a webpage after rendering the JSON/Javascript without Selenium while supporting POSTing 【发布时间】:2016-09-04 04:22:14 【问题描述】:

我正在尝试使用以下代码,它可以正常工作,但它不会让 javascript 先运行,这意味着我没有从网页中获得所需的 html

我查看了DryScrape,但据我所知,它不支持您在auto_login() 函数中看到的发帖,PyQt4 也是如此。

有问题的网站有 4 位 JSON“列表”?在加载/渲染时形成页面;如果我查看源代码,它不会很好地显示并且我无法轻松找到其中的内容,但是如果我在页面上“检查元素”,HTML 看起来很完美,然后我可以使用 BeautifulSoup 轻松查看它。

我知道我可以使用Selenium,但这不是我想要做的主要是因为希望它在后台运行,我可以使用PhantomJSPyVirtualDisplay 来执行此操作,但是这只能作为最后的手段。

import requests
from bs4 import BeautifulSoup

HEADERS = 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8', 'Accept-Encoding': 'gzip, deflate', 'Accept-Language': 'en-US,en;q=0.8', 'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.116 Safari/537.36'
SESSION = requests.session()
RESPONSE = requests.Response

email = "mail@mail.com"
pass = "password123"

def auto_login():
    global RESPONSE
    url = "https://website.com/log.php"
    payload = 
        "log":email,
        "pwd":pass,
    "finish":"https://website.com/listed/public/gen1/",
    
    RESPONSE = SESSION.post(url, data=payload, headers=HEADERS, verify=False)

def process_html():
    PROCESSED_HTML = BeautifulSoup(RESPONSE.content, 'html.parser')
    return PROCESSED_HTML

def main():
    auto_login()
    PROCESSED_HTML = get_html()

if __name__ == "__main__":
    main()

如何在不使用 Selenium 的情况下使用我的脚本(已修改)轻松呈现网页的 JavaScript,最好使用 PyQt4DryScrape 出于某种原因无法在我的 Windows 10、Python 2.7 上正确安装)。

任何想法都将不胜感激。

【问题讨论】:

你试用 Selenium 了吗? Buaban,不,这是我还不知道该怎么做的最后一个选择选项,我需要进一步研究背景Selenium 路线并找出可行的方法。我主要在寻找使用PyQt4 的选项并使我的代码更改最少的更改。 运行无头硒测试真的很简单......只需几行代码即可与 Xvfb 集成:github.com/cgoldberg/… "[...] doesn't let the JavaScript run" 您是否在代码中执行了可以运行 JavaScript 的操作?很难理解你的想法。 @rakslice 不...这就是我要问的问题,我给了你一些可以工作但不能渲染/运行 javascript 的代码的副本。 【参考方案1】:

我无法让 Dryscape 为我工作,所以我无法对此进行测试;但是,我认为这个想法/hack 可能会奏效 - 可能需要一些小的调整。

这个想法是您创建一个小的本地 HTML 文件,其中包含一个表单和您需要传递的参数。这个 HTML 文件是在 Python 中创建的,因此您可以将值传递给每个参数。

根据文档,dryscrape 可以提交表单,因此您提交表单,它应该可以将您带到您需要去的地方。

类似:

import dryscrape

payload = 'log':email, 'pwd':pass, 'finish':'https://website.com/listed/public/gen1/'

html = '''
    <form action="https://website.com/log.php" method="POST">
        <input name="log" type="text" value="log">
        <input name="pwd" type="password" value="pwd">
        <input name="finish" type="text" value="finish">
        <input type="submit">
    </form>
    '''.format(**payload)

with open('./temp.html','w') as hf:
    hf.write(html)

sess = dryscrape.Session(base_url = './') # maybe 'file://' is needed?

q = sess.visit('/temp.html')
q.form().submit()

# Remainder of your code to follow...

同样,我无法自行测试,因此可能需要进行一些小调整。

不是很优雅,只是一个想法...... :-)

【讨论】:

【参考方案2】:

一些代理服务可以选择在页面上呈现 javascript。我用于工作的那个叫做 ProxyCrawl,但我确信还有其他的存在。这是一项付费服务​​(根据请求),可能不适用于您的应用程序。只是一个想法。我的大部分抓取项目的流程是这样的:ProxyCrawl -> Scrapy -> 数据库。

【讨论】:

以上是关于在支持 POST 的同时在不使用 Selenium 的情况下渲染 JSON/Javascript 后从网页中抓取 HTML的主要内容,如果未能解决你的问题,请参考以下文章

如何在不调整窗口大小的情况下使用 Java 在 Selenium Webdriver 中捕获屏幕截图 [重复]

如何在不使用pip或conda安装的情况下链接Selenium等库?

Selenium 在不使用 XPath 的情况下从已经给定的元素中查找近元素

在不使用 Selenium 的情况下将 ChromeDriver 与 WebDriverIO 一起使用

如何在不需要自定义库的情况下在 Google Colabs 上使用 Selenium IDE,例如科拉?

我可以在不重置浏览器状态的情况下按顺序运行多个 RSpec/Selenium 测试吗?