首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >scrapy + selenium:<a>标记没有href,但内容由javascript加载

scrapy + selenium:<a>标记没有href,但内容由javascript加载
EN

Stack Overflow用户
提问于 2020-07-12 20:33:55
回答 1查看 40关注 0票数 0

我第一次尝试使用scrapy,selenium从加载了javascript内容的网站收集数据,就快完成了。

下面是我的代码:

代码语言:javascript
复制
# -*- coding: utf-8 -*-
import scrapy
from selenium import webdriver
from scrapy.selector import Selector
from scrapy.http import Request
from selenium.webdriver.common.by import By
import time

class FreePlayersSpider(scrapy.Spider):
    name = 'free_players'
    allowed_domains = ['www.forge-db.com']
    start_urls = ['https://www.forge-db.com/fr/fr11/players/?server=fr11']
    driver = {}

    def __init__(self):
        self.driver = webdriver.Chrome('/home/alain/Documents/repository/web/foe-python/chromedriver')
        self.driver.get('https://forge-db.com/fr/fr11/players/?server=fr11')

    def start_requests(self):
        for url in self.start_urls:
            yield scrapy.Request(url=url, callback=self.parse)

    def parse(self, response):
        #time.sleep(1)
        sel = Selector(text = self.driver.page_source)

        players = sel.xpath('.//table/tbody/tr')

        for player in players:
            joueur = player.xpath('.//td[3]/a/text()').get()
            guilde = player.xpath('.//td[4]/a/text()').get()

            yield {
                'player' : joueur,
                'guild' : guilde
            }

        next_page_btn = self.driver.find_element_by_xpath('//a[@class="paginate_button next"]')
       

        if next_page_btn:
            time.sleep(2)
            next_page_btn.click()
            yield scrapy.Request(url = self.start_urls, callback=self.parse)

        # Close the selenium driver, so in fact it closes the testing browser
        self.driver.quit()

    def parse_players(self):
        pass        

我想收集用户名和他们的相关行会,并输出到一个csv文件。现在,我的问题是转到下一页,再次解析javascript加载的内容。

如果我能够模拟点击NEXT标签,我不能100%确定代码将继续处理所有页面,并且我无法使用相同的函数解析新内容。

你知道我该怎么解决这个问题吗?谢谢。

EN

回答 1

Stack Overflow用户

发布于 2020-07-12 23:43:01

您应该尝试重新创建请求来更新表,而不是使用selenium。如果你仔细观察chrometools下的HTML。您可以看到,请求是通过参数发出的,并且响应以一种良好的结构化格式返回数据。

关于scrapy中的动态内容,请参阅here。正如它解释了思考的第一步一样,是否有必要重新创建浏览器活动?或者,我是否可以从反向工程HTTP get请求中获得所需的信息。有时使用<script></script>标记隐藏信息,您可以使用一些正则表达式或字符串方法来获得您想要的信息。呈现页面,然后使用浏览器活动应该被认为是最后一步。

现在,在我介绍反向工程请求的一些背景知识之前,您试图从其获取信息的网站只需要对HTTP请求进行反向工程。

在Scrapy中对HTTP请求进行反向工程

现在,就实际的web本身而言,我们可以通过右键单击页面上的inspect来使用chrome devtools。单击网络选项卡可以查看浏览器为呈现页面而发出的所有请求。在本例中,您希望看到单击next时会发生什么。

Image1:here

在这里,当您单击页面上的next时,您可以看到所有请求。我总是寻找最大的响应,因为那最有可能有你的数据。

Image2:here

在这里你可以看到请求头/参数等等。发出正确的HTTP请求所需的内容。我们可以看到,引用的网址实际上是带有所有参数的getplayers.php,用来添加下一个页面。如果向下滚动,您可以看到它发送给getplayers.php的所有相同参数。记住这一点,有时我们需要发送头部,cookie和参数。

Image3:here

这是如果我们发出正确的请求,我们将从服务器返回的数据的预览,这是一个很好的整洁的格式,非常适合抓取。

现在你可以将头文件、参数、cookie复制到scrapy中,但是经过一些搜索之后,总是值得先检查一下,如果只需要传入一个带有url的HTTP请求就可以得到你想要的数据,那么这就是最简单的方法了。

在这种情况下,这是真的,事实上,您会得到一个包含所有数据的很好的need格式。

代码示例

代码语言:javascript
复制
import scrapy

class TestSpider(scrapy.Spider):
    name = 'test'
    allowed_domains = ['forge-db.com']
    
    def start_requests(self):
        url = 'https://www.forge-db.com/fr/fr11/getPlayers.php?'
        yield scrapy.Request(url=url)
    def parse(self,response):
        for row in response.json()['data']:
           yield {'name':row[2],'guild':row[3] }

设置

在settings.py中,您需要设置ROBOTSTXT_OBEY = False站点不希望您访问此数据,因此我们需要将其设置为false。当心,你可能最终会被禁止访问服务器。

我还建议一些其他设置,以便尊重和缓存结果,以便如果您想要处理这个大型数据集,您不会敲打服务器。

代码语言:javascript
复制
CONCURRENT_REQUESTS = 1
DOWNLOAD_DELAY = 3
HTTPCACHE_ENABLED = True
HTTPCACHE_DIR = 'httpcache'

对代码的注释

我们向https://www.forge-db.com/fr/fr11/getPlayers.php?发出一个请求,如果您要打印响应,您将从表中获得所有数据,这是相当多的……现在它看起来是json格式的,所以我们使用scrapy的新特性来处理json并将其转换为python字典。response.json()确保您有最新的scrapy来利用这一点。否则,您可以使用python提供的json库来做同样的事情。

现在您必须看一下这里的预览数据,但是单独的行在response.json()['data'][i]中,其中i在数据行中。名称和行会在response.json()['data'][i][2]response.json()['data'][i][3]中。所以循环遍历每个response.json()['data']并抓取名称和行会。

如果数据没有像这里这样结构化,并且需要修改,我强烈建议您使用Items或ItemLoaders来创建字段,然后可以输出数据。您可以使用ItemLoaders更轻松地修改提取的数据,并且可以使用管道与重复项等进行交互。这些只是我未来的一些想法,我几乎不会使用生成字典来提取数据,特别是大型数据集。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62861144

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档