Привет снова FromThe6ix!
Сегодня вечером я провел некоторое время, пытаясь заставить строку cookie начать работу. MarketWatch проделал довольно приличную работу по защите своих данных. Чтобы создать весь файл cookie, вам понадобится ключ API wsj (я думаю, поставщик финансовых данных их сайта) и некоторые скрытые переменные, которые потенциально доступны только для сервера клиента и строго скрыты в зависимости от вашего веб-драйвера или его отсутствия. его.
Например, если вы пытаетесь выполнить запрос: POST https://browser.pipe.aria.microsoft.com/Collector/3.0/?qsp=true&content-type=application/bond-compact-binary&client-id=NO_AUTH&sdk-version=ACT-Web-JS-2.7.1&x-apikey=c34cce5c21da4a91907bc59bce4784fb-42e261e9-5073-49df-a2e1-42415e012bc6-6954
Вы получите 400 несанкционированных ошибок.
Помните, что существует также большая вероятность того, что мастер кластера клиентского хост-сервера и различные API-интерфейсы, с которыми он взаимодействует, обмениваются данными без того, чтобы наши браузеры могли получать сетевой трафик. Это можно сделать через какое-то промежуточное программное обеспечение, например. Я полагаю, что может объяснить недостающие значения X-Hash-Result и X-Token-Value.
Я не говорю, что невозможно создать эту строку cookie, просто это неэффективный путь с точки зрения времени и усилий на разработку. Теперь я также подвергаю сомнению легкость масштабируемости этого метода с точки зрения использования различных тикеров, кроме AAPL. Если нет явного требования не использовать веб-драйвер и / или сценарий не должен быть легко переносимым без какой-либо конфигурации, разрешенной вне pip install, я бы не выбрал этот метод.
Это, в сущности, оставляет нас либо с Scrapy Spider, либо с Selenium Scraper (и, к сожалению, с небольшой дополнительной конфигурацией среды, но очень важными навыками, которые нужно выучить, если вы хотите писать и развертывать веб-скребки. запросы + bs4 - для идеальных простых операций очистки / необычной переносимости кода).
Я разработал Selenium Scraper ETL Class, используя для вас веб-драйвер PhantomJS. Он принимает строку тикера в качестве параметра и работает с другими акциями, кроме AAPL. Это было непросто, так как marketwatch.com не будет перенаправлять трафик с веб-драйвера PhantomJS (я могу сказать, что они потратили много ресурсов, пытаясь отговорить веб-скребков. Кстати, гораздо больше, чем, скажем, yahoo.com).
В любом случае, вот последний сценарий Selenium, он работает на питоне 2 и 3:
# Market Watch Test Scraper ETL
# Tested on python 2.7 and 3.5
# IMPORTANT: Ensure PhantomJS Web Driver is configured and installed
import pip
import sys
import signal
import time
# Package installer function to handle missing packages
def install(package):
print(package + ' package for Python not found, pip installing now....')
pip.main(['install', package])
print(package + ' package has been successfully installed for Python\n Continuing Process...')
# Ensure beautifulsoup4 is installed
try:
from bs4 import BeautifulSoup
except:
install('beautifulsoup4')
from bs4 import BeautifulSoup
# Ensure selenium is installed
try:
from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
except:
install('selenium')
from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
# Class to extract and transform raw marketwatch.com financial data
class MarketWatchETL:
def __init__(self, ticker):
self.ticker = ticker.upper()
# Set up desired capabilities to spoof Firefox since marketwatch.com rejects any PhantomJS Request
self._dcap = dict(DesiredCapabilities.PHANTOMJS)
self._dcap["phantomjs.page.settings.userAgent"] = ("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/29.0.1547.57 Safari/537.36")
self._base_url = 'https://www.marketwatch.com/investing/stock/'
self._retries = 10
# Private Static Method to clean and organize Key Data Extract
@staticmethod
def _cleaned_key_data_object(raw_data):
cleaned_data = {}
raw_labels = raw_data['labels']
raw_values = raw_data['values']
i = 0
for raw_label in raw_labels:
raw_value = raw_values[i]
cleaned_data.update({str(raw_label.get_text()): raw_value.get_text()})
i += 1
return cleaned_data
# Private Method to scrap data from MarketWatch's web page
def _scrap_financial_key_data(self):
raw_data_obj = {}
try:
driver = webdriver.PhantomJS(desired_capabilities=self._dcap)
except:
print('***SETUP ERROR: The PhantomJS Web Driver is either not configured or incorrectly configured!***')
sys.exit(1)
driver.get(self._base_url + self.ticker)
i = 0
while i < self._retries:
try:
time.sleep(3)
html = driver.page_source
soup = BeautifulSoup(html, "html.parser")
labels = soup.find_all('small', class_="kv__label")
values = soup.find_all('span', class_="kv__primary")
if labels and values:
raw_data_obj.update({'labels': labels})
raw_data_obj.update({'values': values})
break
else:
i += 1
except:
i += 1
continue
if i == self._retries:
print('Please check your internet connection!\nUnable to connect...')
sys.exit(1)
driver.service.process.send_signal(signal.SIGTERM)
driver.quit()
return raw_data_obj
# Public Method to return a Stock's Key Data Object
def get_stock_key_data(self):
raw_data = self._scrap_financial_key_data()
return self._cleaned_key_data_object(raw_data)
# Script's Main Process to test MarketWatchETL('TICKER')
if __name__ == '__main__':
# Run financial key data extracts for Microsoft, Apple, and Wells Fargo
msft_key_data = MarketWatchETL('MSFT').get_stock_key_data()
aapl_key_data = MarketWatchETL('AAPL').get_stock_key_data()
wfc_key_data = MarketWatchETL('WFC').get_stock_key_data()
# Print result dictionaries
print(msft_key_data.items())
print(aapl_key_data.items())
print(wfc_key_data.items())
Какие выходы:
dict_items([('Rev. per Employee', '$841.03K'), ('Short Interest', '44.63M'), ('Yield', '1.53%'), ('Market Cap', '$831.23B'), ('Open', '$109.27'), ('EPS', '$2.11'), ('Shares Outstanding', '7.68B'), ('Ex-Dividend Date', 'Aug 15, 2018'), ('Day Range', '108.51 - 109.64'), ('Average Volume', '25.43M'), ('Dividend', '$0.42'), ('Public Float', '7.56B'), ('P/E Ratio', '51.94'), ('% of Float Shorted', '0.59%'), ('52 Week Range', '72.05 - 111.15'), ('Beta', '1.21')])
dict_items([('Rev. per Employee', '$2.08M'), ('Short Interest', '42.16M'), ('Yield', '1.34%'), ('Market Cap', '$1.04T'), ('Open', '$217.15'), ('EPS', '$11.03'), ('Shares Outstanding', '4.83B'), ('Ex-Dividend Date', 'Aug 10, 2018'), ('Day Range', '216.33 - 218.74'), ('Average Volume', '24.13M'), ('Dividend', '$0.73'), ('Public Float', '4.82B'), ('P/E Ratio', '19.76'), ('% of Float Shorted', '0.87%'), ('52 Week Range', '149.16 - 219.18'), ('Beta', '1.02')])
dict_items([('Rev. per Employee', '$384.4K'), ('Short Interest', '27.44M'), ('Yield', '2.91%'), ('Market Cap', '$282.66B'), ('Open', '$58.87'), ('EPS', '$3.94'), ('Shares Outstanding', '4.82B'), ('Ex-Dividend Date', 'Aug 9, 2018'), ('Day Range', '58.76 - 59.48'), ('Average Volume', '18.45M'), ('Dividend', '$0.43'), ('Public Float', '4.81B'), ('P/E Ratio', '15.00'), ('% of Float Shorted', '0.57%'), ('52 Week Range', '49.27 - 66.31'), ('Beta', '1.13')])
Единственный дополнительный шаг, который вам нужно сделать перед запуском, - это установить и настроить веб-драйвер PhantomJS в своих средах развертывания. Если вам необходимо автоматизировать развертывание веб-скребка, например для этого вы можете написать сценарий установщика оболочки bash / power для предварительной настройки PhantomJS вашей среды.
Некоторые ресурсы для установки и настройки PhantomJS:
Исполняемые файлы установки Windows / Mac PhantomJS
Руководство по установке Debian Linux PhantomJS
RHEL PhantomJS Руководство по установке
Если вы считаете это неполным ответом, то я заранее извиняюсь. Я просто сомневаюсь в практичности и даже в возможности сборки Cookie, как я предлагал в вашем предыдущем посте.
Я думаю, что другой практической возможностью здесь является написание Scrapy Crawler, который я могу попытаться сделать для вас завтра вечером, если хотите.
Надеюсь, это все поможет!