scrapy 一个使用python进行无限滚动的抓取站点

uurity8g  于 2022-11-09  发布在  Python
关注(0)|答案(5)|浏览(259)

我一直在做研究,到目前为止,我发现了python包,我将计划使用它的scrapy,现在,我试图找出一个好的方法来建立一个刮刀使用scrapy爬行网站与无限滚动。经过挖掘周围,我发现有一个包叫 selenium ,它有python模块。我有一种感觉,有人已经这样做了,使用Scrapy和Selenium刮网站与无限滚动。这将是伟大的,如果有人可以指出一个例子。

tsm1rwdh

tsm1rwdh1#

你可以用 selenium 来废除像twitter或facebook这样的无限滚动网站。
步骤1:使用pip安装Selenium

pip install selenium

第2步:使用下面的代码自动执行无限滚动并提取源代码

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import Select
from selenium.webdriver.support.ui import WebDriverWait
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import NoAlertPresentException
import sys

import unittest, time, re

class Sel(unittest.TestCase):
    def setUp(self):
        self.driver = webdriver.Firefox()
        self.driver.implicitly_wait(30)
        self.base_url = "https://twitter.com"
        self.verificationErrors = []
        self.accept_next_alert = True
    def test_sel(self):
        driver = self.driver
        delay = 3
        driver.get(self.base_url + "/search?q=stackoverflow&src=typd")
        driver.find_element_by_link_text("All").click()
        for i in range(1,100):
            self.driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")
            time.sleep(4)
        html_source = driver.page_source
        data = html_source.encode('utf-8')

if __name__ == "__main__":
    unittest.main()

for循环允许您解析无限滚动和post,从中可以提取加载的数据。
第3步:如果需要,打印数据。

bd1hkmkf

bd1hkmkf2#

这是一个简短的代码,这是为我工作:

SCROLL_PAUSE_TIME = 20

# Get scroll height

last_height = driver.execute_script("return document.body.scrollHeight")

while True:
    # Scroll down to bottom
    driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")

    # Wait to load page
    time.sleep(SCROLL_PAUSE_TIME)

    # Calculate new scroll height and compare with last scroll height
    new_height = driver.execute_script("return document.body.scrollHeight")
    if new_height == last_height:
        break
    last_height = new_height

posts = driver.find_elements_by_class_name("post-text")

for block in posts:
    print(block.text)
vm0i2vca

vm0i2vca3#

from selenium.webdriver.common.keys import Keys
import selenium.webdriver
driver = selenium.webdriver.Firefox()
driver.get("http://www.something.com")
lastElement = driver.find_elements_by_id("someId")[-1]
lastElement.send_keys(Keys.NULL)

这将打开一个页面,找到最底部的元素,并滚动到视图中。随着页面加载的增加,您将不得不不断查询驱动程序以获得最后一个元素,而且我发现当页面变大时,这个过程非常慢,主要是调用driver.find_element_*,因为我不知道有什么方法可以显式查询页面中的最后一个元素。
通过实验,您可能会发现页面动态加载的元素数量有一个上限,最好编写一些加载该数量的内容,然后才调用driver.find_element_*

nimxete2

nimxete24#

对于无限滚动数据请求 AJAX 调用。打开网页浏览器--〉network_tab --〉通过点击停止图标清除以前的请求历史记录--〉滚动网页--〉现在您可以找到滚动事件的新请求--〉打开请求标题--〉您可以找到请求的URL---〉在单独的选项卡中复制并粘贴URL--〉您可以找到Ajax调用的结果-- 〉只形成请求的URL以获取数据页,直到页尾

igsr9ssn

igsr9ssn5#

好问题!🤓

挑战者
当使用一个无限滚动页面(或动态加载网站)时,没有办法真正知道加载新项目需要多长时间,因此很难知道在加载新项目之前要等待多长时间,我们可以点击page-down
另外,即使我们能解决第一个问题,我们也要确保我们滚动到页面底部的次数足够多,所以我们要向下滚动足够多的次数,以便真正到达页面底部。

TLDR;如果网站不是很快,或者由于某种原因数据加载需要一段时间,我们不希望过早退出。

我的解决方案

  • 首先,定义一个scroll_down函数,该函数将驱动器和正整数n作为输入。
  • 该函数包含一个for-loop,在两次翻页之间,向下翻页n次,等待0.01秒(这可以更改)
  • 将当前窗口高度存储在名为prev_height的变量中
  • for-loop中,利用预定义的功能向下滚动。
  • 在每次迭代中,暂停一段时间,以便加载更多项(我等待了10秒)
  • 暂停后,比较prev_height和当前高度,如果相同则退出,否则继续。

编号

滚动功能:

def scroll_down(elem, num):
    for _ in range(num):
        time.sleep(.01)
        elem.send_keys(Keys.PAGE_DOWN)

主要代码:

driver = <load driver etc.> 
    SCROLL_PAUSE_TIME = 10
    elem = driver.find_element_by_tag_name("body")
    prev_height = elem.get_attribute("scrollHeight")

    for i in range(0, 500):
        # note that the pause between page downs is only .01 seconds
        # in this case that would be a sum of 1 second waiting time
        scroll_down(elem,100)
        # Wait to allow new items to load
        time.sleep(SCROLL_PAUSE_TIME)

        #check to see if scrollable space got larger
        #also we're waiting until the second iteration to give time for the initial loading
        if elem.get_attribute("scrollHeight") == prev_height and i > 0:
            break
        prev_height = elem.get_attribute("scrollHeight")

注意:我在程序中使用的实际数字可能对你不起作用。但我相信解决方案本身是一个可靠的方法。另外,虽然解决方案对我来说相当可靠,但它也是一个需要时间的方法。

相关问题