抓取网站时动态 JS 生成代码

Posted

技术标签:

【中文标题】抓取网站时动态 JS 生成代码【英文标题】:dynamic JS generated Code while scraping a site 【发布时间】:2019-08-16 06:56:46 【问题描述】:

我是爬虫的新手。我正在尝试使用按钮立即购买从this site 中获取价值。 我尝试过的选项是:

from PyQt4.QtGui import QApplication
from PyQt4.QtCore import QUrl
from PyQt4.QtWebKit import QWebPage

class Client(QWebPage):
    def __init__(self):
        self.app = QApplication(sys.argv)
        QWebPage.__init__(self)
        # self.loadFinished.connect(self.on_page_load)
        # self.mainFrame().load(QUrl(url))
        # self.app.exec_()
    def on_page_load(self):
        self.app.quit()
    def mypage(self, url):
        self.loadFinished.connect(self.on_page_load)
        self.mainFrame().load(QUrl(url))
        self.app.exec_()
client_response = Client()
def parse(url):                # OSRS + RS3
    client_response.mypage(url)
    source = client_response.mainFrame().tohtml()
    soup = BeautifulSoup(source, 'html.parser')
    osrs_text = soup.findAll('input', attrs='type': 'number')
    quantity = (osrs_text[0])['min']
    final = 0
    if(quantity == '1'):
        final_osrs = round(float(soup.findAll('span', attrs='id':'goldprice')[0].text),3)
        print(final_osrs)

    else:
        price = round(float(soup.findAll('span', attrs='id':'goldprice')[0].text),3)
        final_rs3 = price/int(quantity)
        print(final_rs3)

这种方法不好,因为它需要太多时间来抓取。 我也尝试过 Selenium 方法,但目前也不需要。 你们能建议我更好的方法来获取价值吗? 。 任何帮助将不胜感激。谢谢。

P.S:我尝试了这个库,因为内容是动态生成的。

【问题讨论】:

对于一个新的贡献者来说,这是一个很好的问题。 + 1.记得通过edit使用sn-p工具插入html。优化问题也可能是 code review site 的候选问题 - 但请务必在发布之前阅读他们的指导。 【参考方案1】:

我不确定您将获得多少性能差异,但您可以尝试检查此解决方案。

import requests
from bs4 import BeautifulSoup

baseUrl = 'https://www.rsmalls.com/osrs-gold'
postUrl = 'https://www.rsmalls.com/index.php?route=common/quickbuy/rsdetail'

with requests.Session() as session:
    res = session.get(baseUrl)
    soup = BeautifulSoup(res.text, 'lxml')
    game_id = soup.select_one("#choose-game > option[selected]")['value']
    response = session.post(postUrl, data='game_id': game_id).json()
    print(f"'Gold Price:' response['price']")

在这段代码中,首先我得到“Runescape 2007”的 id,以防万一网站所有者更改它。如果您确定它不会更改,您可以跳过该步骤并直接将值 '345' 作为 id 提供给下一个 post 请求。

如你所说,价格是用 JS 代码加载的。使用浏览器开发工具,我可以获得实际的 POST 请求以获取价格,这需要从下拉列表中选择 id。对https://www.rsmalls.com/index.php?route=common/quickbuy/rsdetail 的 POST 请求会给出一个 json 响应,例如:

"success":true,"product_id":"30730","price":0.85,"server_id":"1661","server_option":"463","quantity":"1|5|10|20|50|100|200|300|500|1000|1500|2000","name":"M"

所以,我已将响应解析为 json 并从中获取价格。 如果您有任何问题,请告诉我。

编辑:

https://rsmalls.com/runescape3-gold 上发出了不同的 POST 请求,因此相同的解决方案不起作用。每个页面/网站/数据的 POST 请求可能不同。 您可以使用浏览器开发工具自行找到此类发布请求,如下所示。在右侧,您可以看到向 ​​URL 发出 POST 请求,在底部您也可以找到发送到 POST 请求的数据。另请注意,在响应此请求时,它始终以 1 个单位的价格回复,因此如果网站上的默认单位数量超过 1 个(如以下屏幕截图中的 5 个),则可能不匹配。

【讨论】:

补充说明。您甚至不需要导入 json,因为 requests 已经内置了该功能。因此您可以将这两行合并为:'json_res = sea.post(...).json()' 但是对于这个网站rsmalls.com/runescape3-gold 它不起作用。 感谢@chitown88 和 SIM 改进我的代码。

以上是关于抓取网站时动态 JS 生成代码的主要内容,如果未能解决你的问题,请参考以下文章

网页抓取具有动态 javascript 内容的网站

Java_爬虫,如何抓取Js动态生成数据的页面?

抓取动态网站

使用 Selenium 和 Python 进行用户输入的网页抓取动态网站

使用python读取动态生成的网页

抓取js动态生成数据