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
。
您也可以从名称为 articleid
的 meta
标签中获取它:
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格式并且更容易收集
我正在尝试抓取此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
。
您也可以从名称为 articleid
的 meta
标签中获取它:
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格式并且更容易收集