Scrapyjs + Splash 不从 XHR 请求中检索动态加载的内容

Scrapyjs + Splash does not retrieve dynamically loaded content from XHR Requests

我正在尝试抓取此link的评论部分内容https://www.cnnindonesia.com/nasional/20200607164937-20-510762/risma-usul-ke-khofifah-agar-tak-perpanjang-psbb-surabaya

但是,它是通过 XHR 请求用 Javascript 动态加载的。我已经使用 Chrome 开发工具确定了请求:

https://newcomment.detik.com/graphql?query={ search(type: "comment",size: 10 ,page:1,sort:"newest", adsLabelKanal: "cnn_nasional", adsEnv: "desktop", query: [{name: "news.artikel", terms: "510762" } , {name: "news.site", terms: "cnn"} ]) { paging sorting counter counterparent profile hits { posisi hasAds results { id author content like prokontra status news create_date pilihanredaksi refer liker { id } reporter { id status_report } child { id child parent author content like prokontra status create_date pilihanredaksi refer liker { id } reporter { id status_report } authorRefer } } } } }

很臃肿抱歉,但我也发现在每次请求时获取特定文章的评论部分的关键是在这个特定的查询字符串参数:

terms: "510762"

不幸的是,我还没有找到一种方法来从页面中抓取所需的 "terms" 参数,以便我可以模拟对 许多不同页面的请求。

这就是我选择 Scrapyjs 和 Splash 的原因。我已遵循此 link 中公认的解决方案:How can Scrapy deal with Javascript

但是,我从 scrapy SplashRequest 得到的响应仍然不包含 javascript 加载的内容 (评论部分)!我已经按照说明在 docker 容器中设置了 settings.py、运行 splash,并修改了我的 scrapy spider 以这种方式产生:

            yield scrapy.Request(url, self.parse, meta={
                'splash': {
                    'endpoint': 'render.html',
                    'args': {'wait': 0.5}
                }
            })

我是否遗漏了某些步骤,或者我应该放弃并为此使用 Selenium?提前谢谢你。

直接解析url即可得到文章id:

import re

url = "https://www.cnnindonesia.com/nasional/20200607164937-20-510762/risma-usul-ke-khofifah-agar-tak-perpanjang-psbb-surabaya"
articleid = re.search('(\d+)-(\d+)-(\d+)', url).group(3)
print(f"request for article {articleid}")

请注意,最后一个字符串是此处的文章 ID 510762

您也可以从名称为 articleidmeta 标签中获取它:

from bs4 import BeautifulSoup
import requests

r = requests.get("https://www.cnnindonesia.com/nasional/20200607164937-20-510762/risma-usul-ke-khofifah-agar-tak-perpanjang-psbb-surabaya")
soup = BeautifulSoup(r.text, "html.parser")
print(soup.find("meta", {"name":"articleid"})["content"])

如果您采用第一种解决方案,并且知道 url,则无需使用抓取来获取数据。这是获取评论的示例:

import requests
import re

url = "https://www.cnnindonesia.com/nasional/20200607164937-20-510762/risma-usul-ke-khofifah-agar-tak-perpanjang-psbb-surabaya"

articleid = re.search('(\d+)-(\d+)-(\d+)', url).group(3)
print(f"request for article {articleid}")

query = """
{ 
  search(type: "comment",size: 10 ,page:1,sort:"newest", adsLabelKanal: "cnn_nasional", adsEnv: "desktop", query: [{name: "news.artikel", terms: "%s" } , {name: "news.site", terms: "cnn"} ]) { 
    paging 
    sorting 
    counter 
    counterparent 
    profile 
    hits { 
      posisi 
      hasAds 
      results { 
        id 
        author 
        content 
        like 
        prokontra 
        status 
        news 
        create_date 
        pilihanredaksi 
        refer 
        liker { 
          id 
        } 
        reporter { 
          id 
          status_report 
        } 
        child { 
          id 
          child 
          parent 
          author 
          content 
          like 
          prokontra 
          status 
          create_date 
          pilihanredaksi 
          refer 
          liker { 
            id 
          } 
          reporter { 
            id 
            status_report 
          } 
          authorRefer  
        }  
      }  
    }  
  }  
}""" % articleid

r = requests.get("https://newcomment.detik.com/graphql",
    params = {
        "query": query
    })

results = r.json()

print([t for t in results["data"]["search"]["hits"]["results"]])

字词 510762 在 url 页 您可以在 python 中使用正则表达式提取它 稍后你可以使用 graphpql api 来提取commets 它将是json格式并且更容易收集