我最近尝试使用 scrapysplash 从网站上抓取数据,该网站在滚动到底部时会加载更多数据。
website: https://www.openrice.com/zh/hongkong/restaurants/district/%E5%B0%96%E6%B2%99%E5%92%80
所以我首先尝试使用 JavaScript 在开发工具的console中执行滚动:
for (let i = 0; i < 5; i++) {
setTimeout(() => window.scrollTo(0, (document.body.scrollHeight-1500)), i * 2000);
}
(我把y坐标设置为(document.body.scrollHeight-1500),因为到了最后就无法加载,所以需要调高一点)
在浏览器上的开发工具中执行此操作时,js 代码可以完美运行,因此我将其放入 scrapy flash 中: 这是我的代码:
import scrapy
from Task2.items import RestaurantItem
from scrapy_splash import SplashRequest
lua_script = """
function main(splash, args)
splash:go(args.url)
splash:wait(5.0)
local scroll = splash:jsfunc([[
function scrollWithDelay() {
for (let i = 0; i < 5; i++) {
setTimeout(() => window.scrollTo(0, (document.body.scrollHeight-1500)), i * 2000);
}
}
]])
scroll()
splash:wait(5.0)
return {html = splash:html()}
end
"""
class OpenriceTstSpider(scrapy.Spider):
name = "openrice_tst"
allowed_domains = ["www.openrice.com"]
def start_requests(self):
url = "https://www.openrice.com/zh/hongkong/restaurants/district/%E5%B0%96%E6%B2%99%E5%92%80"
yield SplashRequest(url, callback=self.parse, endpoint='execute',
args={'wait': 2, 'lua_source': lua_script, 'viewport': '1920x1080',
url: "https://www.openrice.com/zh/hongkong/restaurants/district/%E5%B0%96%E6%B2%99%E5%92%80"})
def parse(self, response):
...
我只从网站上获取前20个搜索结果,当我继续向下滚动时可以加载这些结果,它在使用任何js之前就已经存在了。
所以我想知道我是否遗漏了任何细节或者我在代码中写了什么错误?我可以得到一些结果,但它不是来自 js,js 在我的浏览器上运行得很好,所以问题是 scrapy-splash 不起作用,或者我的 lua 脚本是错误的,我继续搜索了 2 天,仍然找不到解决方案,如果你能帮助我,我将非常感谢你! 我是否可以强制它显示所有结果而不滚动?非常感谢所有愿意帮助我的人...
但是,该网站背后有一个 API,您可以直接从中提取数据。
这将抓取 15 个结果的第一页。
import requests
headers = {
'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:126.0) Gecko/20100101 Firefox/126.0',
'Accept': '*/*',
'Accept-Language': 'en-US,en;q=0.5',
}
params = {
'uiLang': 'zh',
'uiCity': 'hongkong',
'districtId': '2008',
'regionId': '0',
'startAt': '0',
'rows': '15',
'pageToken': 'CONST_DUMMY_TOKEN',
}
response = requests.get('https://www.openrice.com/api/v2/search', params=params, headers=headers)
data = response.json()
for result in data["paginationResult"]["results"]:
print(result["name"])
数据如下:
Gram cafe & pancakes
Lady Nara
Mamaday
Outdark (H8)
Nara Thai Cuisine (港威商場)
十和田總本店
JUST'er Bar & Restaurant
Amitie Kitchen
The Grill Room (The Humphreys)
Café Crêpe (K11購物藝術館)
牛魔
hoo韓國包車
古今二 (The ONE)
小魚兒 (金馬大廈)
鬼金棒
API 返回的 JSON 包含的数据远不止名称。您可以将响应转储到文本文件并在 JSON 中进行挖掘以查找您要查找的内容。
要通过 API 实现分页,您只需循环请求,每次将
'startAt'
参数中的值增加 15。当没有新结果时停止。