파이썬에서 동적 콘텐츠(자바스크립트로 작성)로 페이지를 스크랩하려면 어떻게 해야 합니까?
저는 간단한 웹 스크레이퍼를 개발하려고 합니다.HTML 마크업 없이 일반 텍스트를 추출하고 싶습니다.내 코드는 일반(정적) HTML에서 작동하지만 페이지에 내장된 JavaScript에 의해 콘텐츠가 생성될 때는 작동하지 않습니다.
특히, 제가 사용할 때는urllib2.urlopen(request)
페이지 내용을 읽을 때 자바스크립트 코드에 의해 추가될 어떤 것도 표시되지 않습니다. 왜냐하면 그 코드는 어디에서도 실행되지 않기 때문입니다.일반적으로 웹 브라우저에서 실행되지만 제 프로그램의 일부가 아닙니다.
파이썬 코드 내에서 이 동적 콘텐츠에 액세스하려면 어떻게 해야 합니까?
Scrapy 관련 답변은 AJAX를 사용하는 웹 사이트에서 동적 콘텐츠를 지우는 데 Scrapy를 사용할 수 있습니까?를 참조하십시오.
9월: 편년 2021월 9집:phantomjs
.
EDIT 30/Dec/2017:이 답변은 구글 검색의 상위 결과에 나타나므로 업데이트하기로 했습니다.오래된 답은 여전히 끝에 있습니다.
Dryscape는 더 이상 유지 관리되지 않으며 Dryscape 개발자들이 추천하는 라이브러리는 Python 2뿐입니다.저는 Phantom JS와 함께 Selenium의 파이톤 라이브러리를 웹 드라이버로 충분히 빠르고 쉽게 사용할 수 있다는 것을 알게 되었습니다.
Phantom JS를 설치한 후에는 다음 사항을 확인합니다.phantomjs
현재 경로에서 이진을 사용할 수 있습니다.
phantomjs --version
# result:
2.1.1
#예를 들어 다음 HTML 코드로 샘플 페이지를 만들었습니다.(link):
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Javascript scraping test</title>
</head>
<body>
<p id='intro-text'>No javascript support</p>
<script>
document.getElementById('intro-text').innerHTML = 'Yay! Supports javascript';
</script>
</body>
</html>
과 같이 표시됩니다: Javascript 없이같말합다니이.No javascript support
javascript: Javascript:Yay! Supports javascript
#JS 지원 없이 스크래핑:
import requests
from bs4 import BeautifulSoup
response = requests.get(my_url)
soup = BeautifulSoup(response.text)
soup.find(id="intro-text")
# Result:
<p id="intro-text">No javascript support</p>
#JS 지원을 통한 스크래핑:
from selenium import webdriver
driver = webdriver.PhantomJS()
driver.get(my_url)
p_element = driver.find_element_by_id(id_='intro-text')
print(p_element.text)
# result:
'Yay! Supports javascript'
또한 Python 라이브러리 드라이스크립트를 사용하여 Javascript 기반 웹 사이트를 스크랩할 수 있습니다.
#JS 지원을 통한 스크래핑:
import dryscrape
from bs4 import BeautifulSoup
session = dryscrape.Session()
session.visit(my_url)
response = session.body()
soup = BeautifulSoup(response)
soup.find(id="intro-text")
# Result:
<p id="intro-text">Yay! Supports javascript</p>
자바스크립트에서 생성된 콘텐츠를 DOM에서 렌더링해야 하므로 정확한 결과를 얻지 못하고 있습니다.HTML 페이지를 가져올 때, 우리는 자바스크립트에 의해 수정되지 않은 초기의 DOM을 가져옵니다.
따라서 페이지를 탐색하기 전에 자바스크립트 내용을 렌더링해야 합니다.
셀레늄이 이 스레드에서 이미 여러 번 언급되었기 때문에(그리고 셀레늄이 얼마나 느려지는지도 언급되었습니다), 저는 두 가지 다른 가능한 해결책을 나열하겠습니다.
해결책 1: 이것은 Scrapy를 사용하여 Javascript 생성 콘텐츠를 크롤링하는 방법에 대한 매우 좋은 튜토리얼이며 우리는 그것을 따를 것입니다.
필요한 것:
우리 기계에 도커가 설치되어 있습니다.이는 OS 독립 플랫폼을 활용하기 때문에 현재까지 다른 솔루션에 비해 장점입니다.
해당 OS에 대해 나열된 지침에 따라 스플래시를 설치합니다.
스플래시 설명서에서 인용한 내용:스플래시는 자바스크립트 렌더링 서비스입니다.Twisted 및 QT5를 사용하여 Python 3에 구현된 HTTP API를 갖춘 경량 웹 브라우저입니다.
기본적으로 우리는 자바스크립트 생성 콘텐츠를 렌더링하기 위해 스플래시를 사용할 것입니다.
서버를 합니다.
sudo docker run -p 8050:8050 scrapinghub/splash
.Scrapy-Splash 플러그인을 설치합니다.
pip install scrapy-splash
Scrapy 프로젝트가 이미 생성되었다고 가정하고(만약 그렇지 않다면, 만들자) 가이드에 따라 업데이트할 것입니다.
settings.py
:그런 다음 스크레이피 프로젝트로 이동합니다.
settings.py
다음 미들웨어를 설정합니다.DOWNLOADER_MIDDLEWARES = { 'scrapy_splash.SplashCookiesMiddleware': 723, 'scrapy_splash.SplashMiddleware': 725, 'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware': 810, }
스플래시 서버의 URL(Win 또는 OSX를 사용하는 경우)은 도커 컴퓨터의 URL이어야 합니다.호스트에서 도커 컨테이너의 IP 주소를 가져오는 방법:
SPLASH_URL = 'http://localhost:8050'
마지막으로 다음 값도 설정해야 합니다.
DUPEFILTER_CLASS = 'scrapy_splash.SplashAwareDupeFilter' HTTPCACHE_STORAGE = 'scrapy_splash.SplashAwareFSCacheStorage'
마지막으로 다음을 사용할 수 있습니다.
일반 거미에는 URL을 여는 데 사용할 수 있는 Request 개체가 있습니다.열려는 페이지에 JS 생성 데이터가 포함되어 있는 경우 페이지를 렌더링하기 위해 SplunkRequest(또는 SplunkFormRequest)를 사용해야 합니다.다음은 간단한 예입니다.
class MySpider(scrapy.Spider): name = "jsscraper" start_urls = ["http://quotes.toscrape.com/js/"] def start_requests(self): for url in self.start_urls: yield SplashRequest( url=url, callback=self.parse, endpoint='render.html' ) def parse(self, response): for q in response.css("div.quote"): quote = QuoteItem() quote["author"] = q.css(".author::text").extract_first() quote["quote"] = q.css(".text::text").extract_first() yield quote
스플래시 요청은 URL을 html로 렌더링하고 콜백(parse) 메서드에서 사용할 수 있는 응답을 반환합니다.
해결책 2: 현재 (2018년 5월) 실험이라고 부르겠습니다...
이 솔루션은 현재 Python 버전 3.6 전용입니다.
요청 모듈을 알고 계십니까? (누가 모를까요?)
이제 웹 크롤링 작은 형제자매가 있습니다: requests-HTML:
이 라이브러리는 구문 분석 HTML(예: 웹 스크래핑)을 가능한 한 간단하고 직관적으로 만들기 위한 것입니다.
요청 - html: - html:
pipenv install requests-html
페이지의 URL로 요청합니다.
from requests_html import HTMLSession session = HTMLSession() r = session.get(a_page_url)
Javascript 생성 비트를 가져오도록 응답을 렌더링합니다.
r.html.render()
마지막으로, 모듈은 스크래핑 기능을 제공하는 것으로 보입니다.
또는 문서화된 BeautifulSoup 사용 방법을 다음과 같이 사용해 볼 수 있습니다.r.html
방금 렌더링한 개체입니다.
아마 셀레늄이 할 수 있을 겁니다.
from selenium import webdriver
import time
driver = webdriver.Firefox()
driver.get(url)
time.sleep(5)
htmlSource = driver.page_source
사용해본 ,Requests
가 새로 만든 .Requests-HTML
이제 자바스크립트를 렌더링할 수 있는 기능도 마찬가지입니다.
또한 이 모듈에 대해 자세히 알아보려면 https://html.python-requests.org/ 을 방문하거나 JavaScript 렌더링에 관심이 있는 경우 https://html.python-requests.org/ ?#javascript-support를 방문하여 모듈을 사용하여 Python을 사용하여 JavaScript를 렌더링하는 방법을 직접 배울 수 있습니다.
에는 기적으설치면하게올을 사용합니다.Requests-HTML
위 링크에 표시된 모듈의 다음 예는 이 모듈을 사용하여 웹 사이트를 스크랩하고 웹 사이트에 포함된 JavaScript를 렌더링하는 방법을 보여줍니다.
from requests_html import HTMLSession
session = HTMLSession()
r = session.get('http://python-requests.org/')
r.html.render()
r.html.search('Python 2 will retire in only {months} months!')['months']
'<time>25</time>' #This is the result.
저는 최근에 유튜브 영상을 통해 이것에 대해 알게 되었습니다.모듈 작동 방식을 보여주는 YouTube 비디오를 보려면 여기를 클릭하십시오.
당신이 정말 찾고 있는 데이터는 주 페이지의 일부 자바스크립트에 의해 호출되는 보조 URL을 통해 접근할 수 있는 것처럼 들립니다.
서버에서 Javascript를 실행하여 이를 처리할 수 있지만, 보다 간단한 방법은 Firefox를 사용하여 페이지를 로드하고 Charles 또는 Firebug와 같은 도구를 사용하여 보조 URL이 무엇인지 정확하게 식별하는 것입니다.그런 다음 관심 있는 데이터에 대해 해당 URL을 직접 쿼리하면 됩니다.
이것은 훌륭한 블로그 게시물에서 가져온 좋은 해결책인 것 같습니다.
import sys
from PyQt4.QtGui import *
from PyQt4.QtCore import *
from PyQt4.QtWebKit import *
from lxml import html
#Take this class for granted.Just use result of rendering.
class Render(QWebPage):
def __init__(self, url):
self.app = QApplication(sys.argv)
QWebPage.__init__(self)
self.loadFinished.connect(self._loadFinished)
self.mainFrame().load(QUrl(url))
self.app.exec_()
def _loadFinished(self, result):
self.frame = self.mainFrame()
self.app.quit()
url = 'http://pycoders.com/archive/'
r = Render(url)
result = r.frame.toHtml()
# This step is important.Converting QString to Ascii for lxml to process
# The following returns an lxml element tree
archive_links = html.fromstring(str(result.toAscii()))
print archive_links
# The following returns an array containing the URLs
raw_links = archive_links.xpath('//div[@class="campaign"]/a/@href')
print raw_links
셀레늄은 JS와 Ajax 콘텐츠를 스크랩하기에 가장 좋습니다.
Python을 사용하여 웹에서 데이터를 추출하는 방법은 이 문서를 참조하십시오.
$ pip install selenium
그런 다음 Chrome 웹 드라이버를 다운로드합니다.
from selenium import webdriver
browser = webdriver.Chrome()
browser.get("https://www.python.org/")
nav = browser.find_element_by_id("mainnav")
print(nav.text)
쉽죠?
웹 드라이버를 사용하여 Javascript를 실행할 수도 있습니다.
from selenium import webdriver
driver = webdriver.Firefox()
driver.get(url)
driver.execute_script('document.title')
또는 변수에 값을 저장합니다.
result = driver.execute_script('var text = document.title ; return text')
저는 개인적으로 스크레이피와 셀레늄을 사용하는 것을 더 좋아하고 두 가지를 모두 별도의 용기에 넣어 도커화하는 것을 선호합니다.이런 방식으로 당신은 최소한의 번거로움으로 설치할 수 있고 거의 모든 웹사이트가 한 형태 또는 다른 형태로 자바스크립트를 포함하고 있는 최신 웹사이트를 탐색할 수 있습니다.다음은 예입니다.
을 합니다.scrapy startproject
스크레이퍼를 만들고 거미를 쓰기 위해 골격은 다음과 같이 단순할 수 있습니다.
import scrapy
class MySpider(scrapy.Spider):
name = 'my_spider'
start_urls = ['https://somewhere.com']
def start_requests(self):
yield scrapy.Request(url=self.start_urls[0])
def parse(self, response):
# do stuff with results, scrape items etc.
# now were just checking everything worked
print(response.body)
진짜 마법은 middlewares.py 에서 일어납니다.두 .__init__
그리고.process_request
다음과 같은 방법으로:
# import some additional modules that we need
import os
from copy import deepcopy
from time import sleep
from scrapy import signals
from scrapy.http import HtmlResponse
from selenium import webdriver
class SampleProjectDownloaderMiddleware(object):
def __init__(self):
SELENIUM_LOCATION = os.environ.get('SELENIUM_LOCATION', 'NOT_HERE')
SELENIUM_URL = f'http://{SELENIUM_LOCATION}:4444/wd/hub'
chrome_options = webdriver.ChromeOptions()
# chrome_options.add_experimental_option("mobileEmulation", mobile_emulation)
self.driver = webdriver.Remote(command_executor=SELENIUM_URL,
desired_capabilities=chrome_options.to_capabilities())
def process_request(self, request, spider):
self.driver.get(request.url)
# sleep a bit so the page has time to load
# or monitor items on page to continue as soon as page ready
sleep(4)
# if you need to manipulate the page content like clicking and scrolling, you do it here
# self.driver.find_element_by_css_selector('.my-class').click()
# you only need the now properly and completely rendered html from your page to get results
body = deepcopy(self.driver.page_source)
# copy the current url in case of redirects
url = deepcopy(self.driver.current_url)
return HtmlResponse(url, body=body, encoding='utf-8', request=request)
settings.py 파일의 다음 줄에 주석을 달아서 이 미들웨어를 활성화하는 것을 잊지 마십시오.
DOWNLOADER_MIDDLEWARES = {
'sample_project.middlewares.SampleProjectDownloaderMiddleware': 543,}
다음은 도커화입니다.다음을 작성합니다.Dockerfile
경량 이미지(여기서 Python Alpine을 사용하고 있습니다)에서 프로젝트 디렉토리를 복사하고 설치 요구 사항:
# Use an official Python runtime as a parent image
FROM python:3.6-alpine
# install some packages necessary to scrapy and then curl because it's handy for debugging
RUN apk --update add linux-headers libffi-dev openssl-dev build-base libxslt-dev libxml2-dev curl python-dev
WORKDIR /my_scraper
ADD requirements.txt /my_scraper/
RUN pip install -r requirements.txt
ADD . /scrapers
그리고 마침내 모든 것을 한데 모읍니다.docker-compose.yaml
:
version: '2'
services:
selenium:
image: selenium/standalone-chrome
ports:
- "4444:4444"
shm_size: 1G
my_scraper:
build: .
depends_on:
- "selenium"
environment:
- SELENIUM_LOCATION=samplecrawler_selenium_1
volumes:
- .:/my_scraper
# use this command to keep the container running
command: tail -f /dev/null
려달을 합니다.docker-compose up -d
처음 이 작업을 수행하는 경우 최신 셀레늄/독립 실행형 크롬을 가져오고 스크레이퍼 이미지도 빌드하는 데 시간이 걸립니다.
작업이 완료되면 컨테이너가 다음과 같이 실행되는지 확인할 수 있습니다.docker ps
그리고 또한 셀레늄 용기의 이름이 스크레이퍼 용기에 전달된 환경 변수의 이름과 일치하는지 확인합니다(여기서, 그것은SELENIUM_LOCATION=samplecrawler_selenium_1
).
에 스레이입기하력을 합니다.docker exec -ti YOUR_CONTAINER_NAME sh
나를 위한 명령은.docker exec -ti samplecrawler_my_scraper_1 sh
하고 올른디를에리 CD넣고실로 합니다.scrapy crawl my_spider
.
모든 것이 내 깃허브 페이지에 있고 당신은 여기서 그것을 얻을 수 있습니다.
아름다운 수프와 셀레늄의 혼합물은 저에게 아주 잘 맞습니다.
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from bs4 import BeautifulSoup as bs
driver = webdriver.Firefox()
driver.get("http://somedomain/url_that_delays_loading")
try:
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "myDynamicElement"))) #waits 10 seconds until element is located. Can have other wait conditions such as visibility_of_element_located or text_to_be_present_in_element
html = driver.page_source
soup = bs(html, "lxml")
dynamic_text = soup.find_all("p", {"class":"class_name"}) #or other attributes, optional
else:
print("Couldnt locate element")
추신: 여기에서 더 많은 대기 조건을 확인할 수 있습니다.
PyQt5 사용
from PyQt5.QtWidgets import QApplication
from PyQt5.QtCore import QUrl
from PyQt5.QtWebEngineWidgets import QWebEnginePage
import sys
import bs4 as bs
import urllib.request
class Client(QWebEnginePage):
def __init__(self,url):
global app
self.app = QApplication(sys.argv)
QWebEnginePage.__init__(self)
self.html = ""
self.loadFinished.connect(self.on_load_finished)
self.load(QUrl(url))
self.app.exec_()
def on_load_finished(self):
self.html = self.toHtml(self.Callable)
print("Load Finished")
def Callable(self,data):
self.html = data
self.app.quit()
# url = ""
# client_response = Client(url)
# print(client_response.html)
페이지의 다양한 부분(예를 들어)에 대해 스크립트에 URLlib, 요청, BeautifulSoup 및 셀레늄 웹 드라이버를 사용할 수 있습니다.
때때로 이러한 모듈 중 하나만으로도 필요한 것을 얻을 수 있습니다.
때때로 이러한 모듈이 두 개, 세 개 또는 모두 필요할 수 있습니다.
때때로 브라우저의 js를 꺼야 할 수도 있습니다.
스크립트에 헤더 정보가 필요할 수도 있습니다.
어떤 웹 사이트도 같은 방식으로 스크랩할 수 없으며 어떤 웹 사이트도 일반적으로 몇 달 후에 크롤러를 수정할 필요 없이 영원히 같은 방식으로 스크랩할 수 없습니다.하지만 그것들은 모두 긁힐 수 있습니다!의지가 있는 곳에 확실한 방법이 있습니다.
앞으로 계속 데이터를 스크랩해야 하는 경우 필요한 모든 데이터를 스크랩하여 피클과 함께 .dat 파일에 저장하기만 하면 됩니다.
이 모듈로 무엇을 시도하는 방법을 계속 검색하고 오류를 복사하여 Google에 붙여넣으십시오.
2022년 말 현재, 피페티어는 더 이상 유지되지 않습니다; 대안으로 극작가-피톤을 고려합니다.
피피터
Chrome/Chromium 드라이버 프런트엔드 Puppeteer의 Python 포트인 Pipeteer를 고려해 볼 수 있습니다.
다음은 Pypeteer를 사용하여 페이지에 주입된 데이터에 동적으로 액세스하는 방법을 보여주는 간단한 예입니다.
import asyncio
from pyppeteer import launch
async def main():
browser = await launch({"headless": True})
[page] = await browser.pages()
# normally, you go to a live site...
#await page.goto("http://www.example.com")
# but for this example, just set the HTML directly:
await page.setContent("""
<body>
<script>
// inject content dynamically with JS, not part of the static HTML!
document.body.innerHTML = `<p>hello world</p>`;
</script>
</body>
""")
print(await page.content()) # shows that the `<p>` was inserted
# evaluate a JS expression in browser context and scrape the data
expr = "document.querySelector('p').textContent"
print(await page.evaluate(expr, force_expr=True)) # => hello world
await browser.close()
asyncio.run(main())
파이피터의 참조 문서를 참조하십시오.
API에 직접 액세스해 보십시오.
스크래핑에서 볼 수 있는 일반적인 시나리오는 웹 페이지에서 API 끝점에서 비동기식으로 데이터를 요청하는 것입니다.이에 대한 최소한의 예는 다음 사이트입니다.
<body>
<script>
fetch("https://jsonplaceholder.typicode.com/posts/1")
.then(res => {
if (!res.ok) throw Error(res.status);
return res.json();
})
.then(data => {
// inject data dynamically via JS after page load
document.body.innerText = data.title;
})
.catch(err => console.error(err))
;
</script>
</body>
대부분의 경우, API는 CORS 또는 액세스 토큰에 의해 보호되거나 제한적으로 속도가 제한되지만, 다른 경우에는 공개적으로 액세스할 수 있으며 웹 사이트를 완전히 우회할 수 있습니다.CORS 문제는 어디서든 시도할 수 있습니다.
일반적인 절차는 브라우저의 개발자 도구 네트워크 탭을 사용하여 페이지에서 요청한 데이터의 키워드/부분 문자열을 검색하는 것입니다.되지 않은 수 , 는 종종보 API 청요며있으함, 이통직수로 수 .urllib
또는requests
수 있는 위 가능한 연습에 사용할 수 있는 위 실행 가능한 스니펫의 경우입니다.한 후 탭에서
이 예제는 고안된 것입니다. 엔드포인트 URL은 동적으로 조립되고, 최소화되고, 수십 개의 다른 요청 및 엔드포인트 아래에 묻힐 수 있기 때문에 정적 마크업을 볼 때 분명하지 않을 수 있습니다.네트워크 요청에는 액세스 토큰과 같은 관련 요청 페이로드 세부 정보도 표시됩니다.
엔드포인트 URL 및 관련 세부 정보를 얻은 후 표준 HTTP 라이브러리를 사용하여 Python에서 요청을 작성하고 데이터를 요청합니다.
>>> import requests
>>> res = requests.get("https://jsonplaceholder.typicode.com/posts/1")
>>> data = res.json()
>>> data["title"]
'sunt aut facere repellat provident occaecati excepturi optio reprehenderit'
여러분이 그것을 피할 수 있을 때, 이것은 셀레늄, 극작가-파이톤, 스크레이피, 또는 여러분이 이 게시물을 읽고 있을 때 인기 있는 스크레이핑 라이브러리를 가지고 페이지를 스크레이핑하는 것보다 훨씬 더 쉽고, 빠르고, 더 신뢰할 수 있는 경향이 있습니다.
만약 당신이형식으로 , 은 원래의 일부일 수 .<script>
태그(JSON 문자열 또는 JS 개체일 가능성이 높음).예:
<body>
<script>
var someHardcodedData = {
userId: 1,
id: 1,
title: 'sunt aut facere repellat provident occaecati excepturi optio reprehenderit',
body: 'quia et suscipit\nsuscipit recusandae con sequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto'
};
document.body.textContent = someHardcodedData.title;
</script>
</body>
이 데이터를 얻을 수 있는 유일한 방법은 없습니다.하여 BeautifulSoup에 입니다.<script>
텍스트에 태그를 지정한 다음 정규식 또는 구문 분석을 적용하여 개체 구조, JSON 문자열 또는 데이터 형식을 추출합니다.다음은 위에 표시된 샘플 구조에 대한 개념 증명입니다.
import json
import re
from bs4 import BeautifulSoup
# pretend we've already used requests to retrieve the data,
# so we hardcode it for the purposes of this example
text = """
<body>
<script>
var someHardcodedData = {
userId: 1,
id: 1,
title: 'sunt aut facere repellat provident occaecati excepturi optio reprehenderit',
body: 'quia et suscipit\nsuscipit recusandae con sequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto'
};
document.body.textContent = someHardcodedData.title;
</script>
</body>
"""
soup = BeautifulSoup(text, "lxml")
script_text = str(soup.select_one("script"))
pattern = r"title: '(.*?)'"
print(re.search(pattern, script_text, re.S).group(1))
유효하지 않은 JSON 개체를 구문 분석하려면 다음 리소스를 확인하십시오.
다음은 API를 사용하여 스크래핑을 생략한 몇 가지 추가 사례 연구/개념 증명입니다.
- Python beautiful soup을 사용하여 옐프 리뷰와 스타 등급을 CSV로 스크랩하는 방법
- 기존 요소에서 Beautiful Soup이 없음을 반환합니다.
- BeautifulSoup Python에서 데이터 추출
- POST를 통한 밴드캠프 팬 컬렉션 스크레이핑(웹사이트에 대한 첫 번째 요청이 이루어진 하이브리드 접근 방식을 사용하여 BeautifulSoup을 사용하여 마크업에서 토큰을 추출합니다. 이는 JSON 엔드포인트에 대한 두 번째 요청에서 사용되었습니다.)
그렇지 않으면 이 스레드에 나열된 여러 동적 스크래핑 라이브러리 중 하나를 사용해 보십시오.
극작가-피톤
그러나 또 다른 옵션은 Microsoft Playwright(Puppeteer의 영향을 받은 브라우저 자동화 라이브러리)의 Python 포트입니다.
다음은 요소를 선택하고 텍스트를 가져오는 최소한의 예입니다.
from playwright.sync_api import sync_playwright
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
page.goto("http://whatsmyuseragent.org/")
ua = page.query_selector(".user-agent");
print(ua.text_content())
browser.close()
앞서 언급했듯이, Selenium은 JavaScript의 결과를 렌더링하는 데 좋은 선택입니다.
from selenium.webdriver import Firefox
from selenium.webdriver.firefox.options import Options
options = Options()
options.headless = True
browser = Firefox(executable_path="/usr/local/bin/geckodriver", options=options)
url = "https://www.example.com"
browser.get(url)
그리고 gazpacho는 렌더링된 html을 통해 구문 분석하기 정말 쉬운 라이브러리입니다.
from gazpacho import Soup
soup = Soup(browser.page_source)
soup.find("a").attrs['href']
저는 최근에 requests_html 라이브러리를 사용하여 이 문제를 해결했습니다.
readthedocs.io 의 확장된 문서는 상당히 좋습니다(pypi.org 의 주석이 달린 버전을 참조).사용 사례가 기본이라면 어느 정도 성공할 가능성이 높습니다.
from requests_html import HTMLSession
session = HTMLSession()
response = session.request(method="get",url="www.google.com/")
response.html.render()
response.html.render()로 필요한 데이터를 렌더링하는 데 문제가 있는 경우, 필요한 특정 js 개체를 렌더링하기 위해 일부 Javascript를 렌더 함수에 전달할 수 있습니다.이 문서는 해당 문서에서 복사한 것이지만 필요한 것일 수도 있습니다.
스크립트를 지정하면 런타임에 제공된 JavaScript가 실행됩니다.예:
script = """
() => {
return {
width: document.documentElement.clientWidth,
height: document.documentElement.clientHeight,
deviceScaleFactor: window.devicePixelRatio,
}
}
"""
다음과 같은 스크립트가 제공된 경우 실행된 스크립트의 반환 값을 반환합니다.
>>> response.html.render(script=script)
{'width': 800, 'height': 600, 'deviceScaleFactor': 1}
제 경우, 제가 원하는 데이터는 자바스크립트 플롯을 채우는 배열이었지만 데이터는 html의 어느 곳에서도 텍스트로 렌더링되지 않았습니다.데이터가 동적으로 채워질 경우 원하는 데이터의 개체 이름이 무엇인지 전혀 알 수 없는 경우가 있습니다.뷰 소스에서 직접 js 개체를 추적하거나 검사할 수 없는 경우 브라우저(Chrome)의 디버거 콘솔에서 "window"에 이어 ENTER를 입력하여 브라우저에서 렌더링한 개체의 전체 목록을 가져올 수 있습니다.데이터가 저장된 위치에 대해 몇 가지 교육적인 추측을 해본다면, 거기서 데이터를 찾을 수 있을 것입니다.내 그래프 데이터가 콘솔의 window.view.data 아래에 있었기 때문에 위에서 인용한 .render() 메서드에 전달된 "script" 변수에서 다음을 사용했습니다.
return {
data: window.view.data
}
쉽고 빠른 솔루션:
저도 같은 문제를 다루고 있었습니다.자바스크립트로 빌드된 데이터를 긁어내고 싶습니다.BeautifulSoup으로 이 사이트의 텍스트만 스크랩하면 텍스트 태그로 끝납니다.저는 이 태그를 렌더링하고 이 태그에서 정보를 얻고자 합니다.또한 Scrapy와 selenium과 같은 무거운 프레임워크를 사용하고 싶지 않습니다.
그래서 get method of requests 모듈은 URL을 사용하고 스크립트 태그를 렌더링합니다.
예:
import requests
custom_User_agent = "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0"
url = "https://www.abc.xyz/your/url"
response = requests.get(url, headers={"User-Agent": custom_User_agent})
html_text = response.text
그러면 로드 사이트가 렌더링되고 태그가 렌더링됩니다.
이것이 스크립트 태그로 로드된 사이트를 빠르고 쉽게 렌더링할 수 있는 솔루션이 되기를 바랍니다.
언급URL : https://stackoverflow.com/questions/8049520/how-can-i-scrape-a-page-with-dynamic-content-created-by-javascript-in-python
'sourcecode' 카테고리의 다른 글
누가 원래 이런 유형의 구문을 발명했는가: -*- 코딩: utf-8 -*- (0) | 2023.07.18 |
---|---|
.NET Core 5.0의 ODP.Net 드라이버 던지기 예외 (0) | 2023.07.18 |
Admob 광고와 Firebase 광고의 차이점 (0) | 2023.07.18 |
openxml 스프레드쉬트 다른 이름으로 저장 (0) | 2023.07.18 |
탭을 사용하지 않고 주피터 노트북에서 자동 완성하는 방법은 무엇입니까? (0) | 2023.07.18 |