Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Python

Thu thập dữ liệu web với lxml trong Python

Giới thiệu về web scraping và lxml

Web scraping không chỉ thu hút các nhà khoa học dữ liệu mà còn là công cụ hữu ích cho sinh viên và người học muốn khám phá sâu hơn các trang web. Python cung cấp nhiều thư viện scraping như Scrapy, Urllib, BeautifulSoup, Selenium, Requests và lxml.

Thư viện lxml được xây dựng trên libxml2 (viết bằng C), giúp tốc độ xử lý nhanh hơn BeautifulSoup nhưng cài đặt trên Windows có thể gặp khó khăn.

Cài đặt và import lxml

pip install lxml
# hoặc
conda install -c anaconda lxml

Import module html để phân tích HTML:

from lxml import html

Cần thư viện requests để tải nội dung HTML:

pip install requests

Ví dụ: Thu thập dữ liệu chứng khoán từ Yahoo Finance

Chúng ta sẽ trích xuất các trường dữ liệu cổ phiếu Microsoft (MSFT) từ https://finance.yahoo.com/quote/msft bao gồm: Previous Close, Open, Bid, Ask, Day's Range, 52 Week Range, Volume, v.v.

Mã nguồn hoàn chỉnh (lxml_scrape3.py)

from lxml import html
import requests
from time import sleep
import json
import argparse
from collections import OrderedDict

def parse(ticker):
    url = "https://finance.yahoo.com/quote/%s?p=%s" % (ticker, ticker)
    response = requests.get(url, verify=False)
    print("Parsing %s" % (url))
    sleep(4)
    
    parser = html.fromstring(response.text)
    summary_table = parser.xpath('//div[contains(@data-test,"summary-table")]//tr')
    summary_data = OrderedDict()
    
    # Lấy dữ liệu bổ sung từ API JSON
    other_details_json_link = ("https://query2.finance.yahoo.com/v10/finance/quoteSummary/{0}?"
                              "formatted=true&lang=en-US®ion=US&modules=summaryProfile,"
                              "financialData,recommendationTrend,upgradeDowngradeHistory,"
                              "earnings,defaultKeyStatistics,calendarEvents&corsDomain=finance.yahoo.com").format(ticker)
    
    summary_json_response = requests.get(other_details_json_link)
    
    try:
        json_loaded_summary = json.loads(summary_json_response.text)
        y_Target_Est = json_loaded_summary["quoteSummary"]["result"][0]["financialData"]["targetMeanPrice"]['raw']
        earnings_list = json_loaded_summary["quoteSummary"]["result"][0]["calendarEvents"]['earnings']
        eps = json_loaded_summary["quoteSummary"]["result"][0]["defaultKeyStatistics"]["trailingEps"]['raw']
        
        datelist = []
        for i in earnings_list['earningsDate']:
            datelist.append(i['fmt'])
        earnings_date = ' to '.join(datelist)
        
        for table_data in summary_table:
            raw_table_key = table_data.xpath('.//td[contains(@class,"C(black)")]//text()')
            raw_table_value = table_data.xpath('.//td[contains(@class,"Ta(end)")]//text()')
            table_key = ''.join(raw_table_key).strip()
            table_value = ''.join(raw_table_value).strip()
            summary_data.update({table_key: table_value})
        
        summary_data.update({
            '1y Target Est': y_Target_Est,
            'EPS (TTM)': eps,
            'Earnings Date': earnings_date,
            'ticker': ticker,
            'url': url
        })
        return summary_data
    except:
        print("Failed to parse json response")
        return {"error": "Failed to parse json response"}

if __name__ == "__main__":
    argparser = argparse.ArgumentParser()
    argparser.add_argument('ticker', help='Stock ticker symbol')
    args = argparser.parse_args()
    ticker = args.ticker
    
    print("Fetching data for %s" % (ticker))
    scraped_data = parse(ticker)
    print("Writing data to output file")
    
    with open('%s-summary.json' % (ticker), 'w') as fp:
        json.dump(scraped_data, fp, indent=4)

Chạy chương trình

python lxml_scrape3.py MSFT

Kết quả: File msft-summary.json được tạo trong thư mục hiện tại chứa toàn bộ dữ liệu cổ phiếu.

Lưu ý quan trọng

  • Yahoo Finance có thể thay đổi cấu trúc HTML/API bất cứ lúc nào
  • Nên tuân thủ robots.txt và điều khoản dịch vụ của trang web
  • Cân nhàng sử dụng API chính thức nếu có sẵn