如何通过Web抓取具有部分静态和部分动态内容的页面?

时间:2019-04-12 19:50:54

标签: python selenium web-scraping beautifulsoup

编辑:可能的重复项不能解决我的问题,因为我试图也使用无头浏览器但没有成功。该问题并未说明如何使用无头浏览器来完成此任务或类似任务。

我要抓取此页面:

https://www.finishline.com/store/men/shoes/_/N-1737dkj?mnid=men_shoes#/store/men/shoes/nike/adidas/jordan/under-armour/puma/new-balance/reebok/champion/timberland/fila/lacoste/converse/_/N-1737dkjZhtjl46Zh51uarZvnhst2Zu4e113Z16ggje2Z1alnhbgZ1lzobj2Z7oi4waZ1hzyzukZm0ym0nZj4k440Zdshbsy?mnid=men_shoes

在用户向下滚动一点后,会先自动加载前12种产品(不使用JS),然后再加载其他(我相信48种)产品。

此代码段:

import requests
import csv
import io
import os
import re
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.chrome.options import Options
from datetime import datetime
from bs4 import BeautifulSoup

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'
    }

url_list2 = []


data2 = requests.get("https://www.finishline.com/store/men/shoes/_/N-1737dkj?mnid=men_shoes#/store/men/shoes/nike/adidas/jordan/under-armour/puma/new-balance/reebok/champion/timberland/fila/lacoste/converse/_/N-1737dkjZhtjl46Zh51uarZvnhst2Zu4e113Z16ggje2Z1alnhbgZ1lzobj2Z7oi4waZ1hzyzukZm0ym0nZj4k440Zdshbsy?mnid=men_shoes",headers=headers)
soup2 = BeautifulSoup(data2.text, 'html.parser')

x = soup2.findAll('div', attrs={'class': 'product-card'})
for url2 in x:
    get_urls = "https://www.finishline.com"+url2.find('a')['href']
    url_list2.append(get_urls)
print(url_list2)

将获得与JS独立的12种产品(可以通过在Chrome设置中关闭JS进行检查)。但是,打开JS时,页面上有60个(或59个)产品。

如何使用BS4获得所有产品?我也尝试了Selenium,但是使用它却遇到了另一个错误。

在硒测试中,我设法使所有59种产品显示在页面上。我正在使用此代码获取所有产品页面的URL,以供进一步抓取。

import requests
import csv
import io
import os
import time
from datetime import datetime
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.chrome.options import Options
from selenium.webdriver import DesiredCapabilities
from bs4 import BeautifulSoup,Tag

page = "https://www.finishline.com/store/men/shoes/_/N-1737dkj?mnid=men_shoes#/store/men/shoes/nike/adidas/jordan/under-armour/puma/new-balance/reebok/champion/timberland/fila/lacoste/converse/_/N-1737dkjZhtjl46Zh51uarZvnhst2Zu4e113Z16ggje2Z1alnhbgZ1lzobj2Z7oi4waZ1hzyzukZm0ym0nZj4k440Zdshbsy?mnid=men_shoes"

url_list2 = []

page_num = 0
#session = requests.Session()
while page_num <1160:
    driver = webdriver.Chrome()
    driver.get(page)
    getproductUrls = driver.find_elements_by_class_name('product-card')
    for url2 in getproductUrls:
        get_urls = "https://www.finishline.com"+url2.find_element_by_tag_name('a').get_attribute("href")
        url_list2.append(get_urls)
        print(url_list2)
    driver.close()

    page = "https://www.finishline.com/store/men/shoes/_/N-1737dkj?mnid=men_shoes#/store/men/shoes/nike/adidas/jordan/under-armour/puma/new-balance/reebok/champion/timberland/fila/lacoste/converse/_/N-1737dkjZhtjl46Zh51uarZvnhst2Zu4e113Z16ggje2Z1alnhbgZ1lzobj2Z7oi4waZ1hzyzukZm0ym0nZj4k440Zdshbsy?mnid=men_shoes&No={}".format(page_num)
    page_num +=40

但是,过一段时间后,该错误

raise exception_class(message, screen, stacktrace, alert_text)
selenium.common.exceptions.UnexpectedAlertPresentException: Alert Text: None
Message: unexpected alert open: {Alert text : something went wrong}

发生,因为该站点检测到异常活动。如果要在浏览器中打开网站finishline.com,则会收到“访问被拒绝”消息,并且必须清除cookie并刷新以使其再次起作用。显然,在此消息弹出之前,我的脚本还没有完成。

有人知道解决方案吗?预先谢谢你。

1 个答案:

答案 0 :(得分:1)

该内容在页面源中可用。您不能仅使用请求来获取所有请求,因为大多数请求都在script标记内。此外,您需要找到可以用来遍历多个页面的适当URL。这是right one,您可以使用chrome开发工具来获取。目前,以下脚本可以抓取120个产品。您可以根据自己的喜好更改范围。

这是您可以去的方式:

import requests
from bs4 import BeautifulSoup

url = "https://www.finishline.com/store/men/shoes/nike/adidas/jordan/under-armour/puma/new-balance/reebok/champion/timberland/fila/lacoste/converse/_/N-1737dkjZhtjl46Zh51uarZvnhst2Zu4e113Z16ggje2Z1alnhbgZ1lzobj2Z7oi4waZ1hzyzukZm0ym0nZj4k440Zdshbsy?"

qsp = {
    'mnid': 'men_shoes_nike_adidas_jordan_underarmour_puma_newbalance_reebok_champion_timberland_fila_lacoste_converse',
    'No': 0,
    'isAjax': True
}


container = []

for page_content in range(0,120,40):
    qsp['No'] = page_content
    res = requests.get(url,params=qsp,headers={"User-Agent":"Mozilla/5.0"})
    soup = BeautifulSoup(res.text, 'lxml')
    for item in soup.select(".product-card__details .product-name"):
        container.append(item.get_text(strip=True))

    for items in soup.select("script"):
        sauce = BeautifulSoup(items.text,"lxml")
        for elem in sauce.select(".product-card__details .product-name"):
            container.append(elem.get_text(strip=True))

for product in container:
    print(product)

顺便说一句,我可以在每个页面中看到40种产品。每个页面中的产品数量可能会因国家/地区而异。将其range(0,120,40)更改为从头到尾在每个页面中可以看到的数量。