我一直在浏览这个问题,并为我的问题找到了一些工作,但是想知道是否有更好的解决方案。
特别是,我需要从网页获取所有pdf文件的链接 - 例如:http://stock.walmart.com/investors/financial-information/annual-reports-and-proxies/default.aspx
我最初尝试使用简单的东西(我正在使用Python3):
import requests
from bs4 import BeautifulSoup
import urllib
import os
base_url = 'http://stock.walmart.com/investors/financial-information/annual-reports-and-proxies/default.aspx'
headers = {"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36"}
r = requests.get(url=base_url, headers=headers)
soup = BeautifulSoup(r.text)
links = soup.findAll('a', href=True)
for tag in links:
tag['href'] = urllib.parse.urljoin(base_url, tag['href'])
if os.path.splitext(os.path.basename(tag['href']))[1] == '.pdf':
print(tag['href'])
但这没有做,因为我错过了所有PDF链接。我不是这方面的专家,但阅读它似乎是因为它们是用JavaScript动态呈现的,或者通过后续的POST请求获得。
因此,我尝试了第二种方法,使用Selenium:
driver = webdriver.Chrome('./chromedriver')
driver.get(url)
elems = driver.find_elements_by_xpath("//a[@href]")
print([link for link in url_list if link[-4:].lower() == '.pdf'])
这很有效,但对于我来说这看起来很容易。因此:
wget
,它似乎可以工作并找到所有pdf链接(!!),因此可能有一种简单的方法可以做到这一点... 一般而言,任何其他完成任务的提示都非常受欢迎。我应该看看scrapy吗?或者那会出现同样的问题吗?
非常感谢。
答案 0 :(得分:1)
一个真正通用的解决方案必须考虑到许多现代网页使用JavaScript来呈现其内容的事实。因此,缺少JavaScript运行时的任何工具或库(例如requests
或import capybara
from capybara.dsl import page
import re
@capybara.register_driver("selenium_chrome_headless")
def init_selenium_chrome_headless_driver(app):
from selenium.webdriver.chrome.options import Options
from capybara.selenium.driver import Driver
chrome_options = Options()
chrome_options.add_argument("--headless")
return Driver(app, browser="chrome", chrome_options=chrome_options)
capybara.current_driver = "selenium_chrome_headless"
page.visit(url)
links = page.find_all("link",
# Match only URLs ending in ".pdf"
href=re.compile(r"\.pdf$"),
# Assuming you expect, and would like to wait
# for, at least one PDF link on the page
minimum=1)
urls = [link["href"] for link in links]
)都无法访问此类内容。需要一个JavaScript运行时,实际上意味着需要一个浏览器,而Selenium是控制浏览器最强大的方式。
对于“轻量级”方法,PhantomJS当然是一种选择,但随着Chrome等主流浏览器开始提供越来越可靠的无头操作,它的支持和随后的价值已经减弱。在这一点上,我强烈建议使用无头Chrome,而不是PhantomJS。
虽然Selenium为您提供了控制浏览器的基本工具,但它将处理现代异步Web应用程序作为读者的练习。例如,如果加载页面上的内容需要一段时间,该怎么办? Selenium要求您反复明确地管理它。
capybara-py通过在Selenium上提供一个层来帮助解决这个问题,除了其他方面之外,它还可以透明地同步您的交互,无论您是在加载页面还是填写表单字段或点击链接和按钮:
materials[i] = new THREE.MeshLambertMaterial({ map:texture });