Python 使用Scrapy模拟AJAX请求以收集分页数据

Python 使用Scrapy模拟AJAX请求以收集分页数据,python,python-3.x,scrapy,data-science,Python,Python 3.x,Scrapy,Data Science,我正在做一个小项目,从一个流行的传奇联盟网站www.op.gg收集一些数据。例如,如果您转到第页,您将看到右侧显示了价值10场比赛的数据。如果你一直向下滚动,你会在底部看到接下来的20个结果,以此类推。当我使用chrome工具检查“Show More”元素时,我看到以下条目: <a href="#" onclick="$.OP.GG.matches.list.loadMore($(this)); return false;" class="Button">Show More</

我正在做一个小项目,从一个流行的传奇联盟网站www.op.gg收集一些数据。例如,如果您转到第页,您将看到右侧显示了价值10场比赛的数据。如果你一直向下滚动,你会在底部看到接下来的20个结果,以此类推。当我使用chrome工具检查“Show More”元素时,我看到以下条目:

<a href="#" onclick="$.OP.GG.matches.list.loadMore($(this)); return false;" class="Button">Show More</a>

仅使用
Selenium
您只需单击按钮即可。使用其他工具,您可以在DevTools(在tab Network中)中检查当您单击按钮(特别是XHR请求)时它发送的请求并使用它-也许它可以在不模拟AJAX的情况下工作,您可以获得JSON数据,这些数据可以轻松地转换为Python的列表/字典。要模拟AJAX,当我使用网络选项卡并单击“显示更多”时,必须添加一个标题
XMLHttpRequest
,这样会出现类似的链接。这是一个HTML字符串的JSON——你知道用我能从Scrapy中解析CSS的同样方法来解析它的最有效方法吗?你可以使用
lxml
Beautifulsoup
来解析它,并使用gn
CSS
xpath
进行搜索。或者您可以使用Scrapy和
HtmlResponse
Selector
从字符串/HTML创建响应-请参阅您是否尝试将此HTML直接与
HtmlResponse
Selector
BeautifulSoup
lmxl
一起使用。它们不需要完整的HTML即可工作。从Scrapy导入选择器数据=Selector(text=string)data.css('#myid::text').get()
import scrapy

class PostsSpider(scrapy.Spider):
    name = "posts"
    start_urls = [
        'https://na.op.gg/summoner/userName=C9+Zven',
        'https://na.op.gg/summoner/userName=From+Iron'
    ]

    def parse(self, response):
        summoner_name = response.css('.SummonerLayout>.Header>.Profile>.Information>.Name::text').get()
        rank_type = response.css('.TierRankInfo .RankType::text').get()
        tier_rank = response.css('.TierRankInfo .TierRank::text').get()   

        game_lists = []
        dict_per_game = {}

        for game in response.css('div.GameItemWrap'):
            dict_per_game['summoner_id'] = game.css('.GameItem::attr(data-summoner-id)').get() 
            dict_per_game['data_game_time'] = game.css('.GameItem::attr(data-game-time)').get() 
            dict_per_game['game_type'] = str.strip(game.css('.Content .GameStats .GameType::text').get())
            dict_per_game['date_time_epoch'] = game.css('.Content .GameStats .TimeStamp ._timeago::attr(data-datetime)').get()
            dict_per_game['game_result'] = str.strip(game.css('.Content .GameStats .GameResult::text').get())
            dict_per_game['champ_name'] = game.css('.Content .GameSettingInfo .ChampionName a::text').get()
            dict_per_game['kill'] = game.css('.Content .KDA .KDA .Kill::text').get()
            dict_per_game['death'] = game.css('.Content .KDA .KDA .Death::text').get()
            dict_per_game['assist'] = game.css('.Content .KDA .KDA .Assist::text').get()
            game_lists.append(dict_per_game)
            dict_per_game = {}

        yield {
            'summoner_name': summoner_name,
            'rank_type': rank_type, 
            'tier_rank': tier_rank, 
            'games': game_lists
        }

        # This is where I would like to add some code to retrieve more results for this profile going back to 30 days ago from runtime