在支持 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
,但这不是我想要做的主要是因为希望它在后台运行,我可以使用PhantomJS
或PyVirtualDisplay
来执行此操作,但是这只能作为最后的手段。
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,最好使用 PyQt4
(DryScrape
出于某种原因无法在我的 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 一起使用