Ważną umiejętnością pozyskiwania danych ze stron internetowych jest web scraping. Przykładami tego typu stron są Pinterest i Instagram, które dynamicznie ładują zawartość poprzez interakcję z użytkownikiem. Zwykłe metody skrobania są niewystarczające w przypadku obsługi materiałów opartych na JavaScript. W tym artykule omówimy Playwright jako narzędzie do automatyzacji, podczas gdy lxml będzie używany do ekstrakcji danych z takich dynamicznych witryn, które wymagają Javascript do prawidłowego działania. W tej notatce możemy omówić wykorzystanie serwerów proxy w Playwright, aby uniknąć wykrycia jako boty. W tym samouczku zeskrobujemy profil Instagrama, aby pobrać wszystkie adresy URL postów, symulując zachowanie użytkownika, takie jak przewijanie i oczekiwanie na załadowanie postów.
Narzędzia, których będziemy używać w tym przewodniku:
Zilustrujemy ten proces na przykładzie skrobania profilu na Instagramie w celu wyodrębnienia adresów URL postów, symulując działania użytkownika, takie jak przewijanie strony i oczekiwanie na załadowanie nowych danych. Dynamiczne strony internetowe asynchronicznie ładują swoją zawartość za pomocą żądań AJAX, co oznacza, że nie cała zawartość strony jest natychmiast dostępna.
Zanim zaczniemy, zainstaluj niezbędne pakiety:
pip install playwright
pip install lxml
Konieczne będzie również zainstalowanie przeglądarki Playwright:
playwright install
Użyjemy Playwright, aby zautomatyzować przeglądarkę, załadować dynamiczną zawartość Instagrama i przewinąć stronę, aby załadować więcej postów. Stwórzmy podstawowy skrypt automatyzacji:
Skrypt automatyzacji (przeglądarka bezgłowa):
import asyncio
from playwright.async_api import async_playwright
async def scrape_instagram():
async with async_playwright() as p:
browser = await p.chromium.launch(headless=True) # Headless mode No visual feedback
page = await browser.new_page()
# Odwiedź adres URL profilu
await page.goto("https://www.instagram.com/profile name/", wait_until="networkidle")
# Kliknij przycisk, aby załadować więcej postów
await page.get_by_role("button", name="Show more posts from").click()
# Przewijanie strony w celu załadowania zawartości dynamicznej
scroll_count = 5 # Dostosuj to na podstawie tego, ile razy chcesz przewijać.
for _ in range(scroll_count):
await page.evaluate('window.scrollBy(0, 700);')
await page.wait_for_timeout(3000) # Wait for posts to load
await page.wait_for_load_state("networkidle")
# Pobierz zawartość strony
content = await page.content()
await browser.close()
return content
# Uruchom funkcję asynchroniczną
asyncio.run(scrape_instagram())
Po załadowaniu zawartości możemy użyć lxml do przeanalizowania HTML i wyodrębnienia danych za pomocą XPath. W tym przypadku wyodrębniamy adresy URL wszystkich postów z profilu.
Parsowanie zawartości strony i wyodrębnianie adresów URL postów:
from lxml import html
import json
def extract_post_urls(page_content):
# Parsowanie zawartości HTML przy użyciu lxml
tree = html.fromstring(page_content)
# XPath do wyodrębniania adresów URL postów
post_urls_xpath = '//a[contains(@href, "/p/")]/@href'
# Wyodrębnianie adresów URL
post_urls = tree.xpath(post_urls_xpath)
# Konwertowanie względnych adresów URL na bezwzględne
base_url = "https://www.instagram.com"
post_urls = [f"{base_url}{url}" for url in post_urls]
return post_urls
Przykładowa funkcja zapisująca wyodrębnione dane w formacie JSON:
def save_data(profile_url, post_urls):
data = {profile_url: post_urls}
with open('instagram_posts.json', 'w') as json_file:
json.dump(data, json_file, indent=4)
# Skrobanie i wyodrębnianie adresów URL
page_content = asyncio.run(scrape_instagram())
post_urls = extract_post_urls(page_content)
# Zapisz wyodrębnione adresy URL w pliku JSON
save_data("https://www.instagram.com/profile name/", post_urls)
Aby skrobać dynamiczne strony internetowe, często trzeba symulować nieskończone przewijanie. W naszym skrypcie przewijamy stronę za pomocą JavaScript:
(window.scrollBy(0, 700))
I poczekać na załadowanie nowej zawartości za pomocą tego polecenia:
wait_for_load_state("networkidle")
Instagram ma ścisłe limity szybkości i środki zapobiegające botom. Aby uniknąć zablokowania, można użyć serwerów proxy do rotacji adresów IP i dystrybucji żądań. Playwright ułatwia integrację serwerów proxy z automatyzacją skrobania.
Wdrażanie serwerów proxy w Playwright:
async def scrape_with_proxy():
async with async_playwright() as p:
browser = await p.chromium.launch(
headless=False,
proxy={"server": "http://your-proxy-server:port"}
)
page = await browser.new_page()
await page.goto("https://www.instagram.com/profile name/", wait_until="networkidle")
# Kontynuować skrobanie jak poprzednio...
Playwright obsługuje również proxy przekazywane jako nazwa użytkownika, hasło i przykład serwera podany poniżej.
async def scrape_with_proxy():
async with async_playwright() as p:
browser = await p.chromium.launch(
headless=False,
proxy={"server": "http://your-proxy-server:port", "username": "username", "password": "password"}
)
page = await browser.new_page()
await page.goto("https://www.instagram.com/profile name/", wait_until="networkidle")
# Kontynuować skrobanie jak poprzednio...
Serwery proxy pomagają uniknąć zakazów IP, wyzwań CAPTCHA i zapewniają płynne pobieranie danych z witryn z dużą ilością danych lub witryn z ograniczeniami, takich jak Instagram.
import asyncio
from playwright.async_api import async_playwright
from lxml import html
import json
# Funkcja automatyzacji przeglądarki i skrobania dynamicznej zawartości za pomocą serwerów proxy
async def scrape_instagram(profile_url, proxy=None):
async with async_playwright() as p:
# Skonfiguruj przeglądarkę z serwerem proxy, jeśli jest dostępny
browser_options = {
'headless': True, # Użyj przeglądarki z nagłówkiem, aby zobaczyć akcję (można ustawić na True dla trybu bezgłowego)
}
if proxy:
browser_options['proxy'] = proxy
# Uruchom przeglądarkę
browser = await p.chromium.launch(**browser_options)
page = await browser.new_page()
# Odwiedź stronę profilu na Instagramie
await page.goto(profile_url, wait_until="networkidle")
# Spróbuj kliknąć przycisk "Pokaż więcej postów" (opcjonalnie, może się nie udać, jeśli przycisk nie zostanie znaleziony).
try:
await page.click('button:has-text("Show more posts from")')
except Exception as e:
print(f"No 'Show more posts' button found: {e}")
# Przewiń stronę, aby załadować więcej postów
scroll_count = 5 # Liczba przewinięć do załadowania postów
for _ in range(scroll_count):
await page.evaluate('window.scrollBy(0, 500);')
await page.wait_for_timeout(3000) # Wait for new posts to load
await page.wait_for_load_state("networkidle")
# Uzyskaj pełną zawartość strony po przewinięciu
content = await page.content()
await browser.close() # Po zakończeniu zamknij przeglądarkę
return content
# Funkcja analizująca zawartość strony i wyodrębniająca adresy URL postów.
def extract_post_urls(page_content):
# Parsowanie zawartości HTML przy użyciu lxml
tree = html.fromstring(page_content)
# XPath do wyodrębniania adresów URL postów
post_urls_xpath = '//a[contains(@href, "/p/")]/@href'
# Wyodrębnianie adresów URL postów przy użyciu XPath
post_urls = tree.xpath(post_urls_xpath)
# Konwersja względnych adresów URL na bezwzględne adresy URL
base_url = "https://www.instagram.com"
post_urls = [f"{base_url}{url}" for url in post_urls]
return post_urls
# Funkcja zapisująca wyodrębnione adresy URL postów w pliku JSON
def save_data(profile_url, post_urls):
# Struktura danych w formacie JSON
data = {profile_url: post_urls}
# Zapisywanie danych do pliku
with open('instagram_posts.json', 'w') as json_file:
json.dump(data, json_file, indent=4)
print(f"Data saved to instagram_posts.json")
# Główna funkcja do uruchamiania scrapera i zapisywania danych
async def main():
# Zdefiniuj adres URL profilu na Instagramie
profile_url = "https://www.instagram.com/profile name/"
# Opcjonalnie można skonfigurować serwer proxy
proxy = {"server": "server", "username": "username", "password": "password"} # Use None if no proxy is required
# Scrape'owanie strony na Instagramie za pomocą serwerów proxy
page_content = await scrape_instagram(profile_url, proxy=proxy)
# Wyodrębnij adresy URL postów z treści zeskrobanej strony
post_urls = extract_post_urls(page_content)
# Zapisz wyodrębnione adresy URL postów w pliku JSON
save_data(profile_url, post_urls)
if __name__ == '__main__':
asyncio.run(main())
Podczas gdy Playwright jest doskonałym wyborem do skrobania dynamicznych stron internetowych, inne narzędzia mogą być odpowiednie dla różnych scenariuszy:
Każde narzędzie oferuje unikalne zalety i może być wybrane w oparciu o konkretne potrzeby i warunki projektu.
Do skutecznego skrobania dynamicznych stron internetowych, które aktywnie wykorzystują JavaScript i żądania AJAX, niezbędne są potężne narzędzia zdolne do wydajnej obsługi nieskończonego przewijania i złożonych elementów interaktywnych. Jednym z takich rozwiązań jest Playwright - narzędzie firmy Microsoft, które zapewnia pełną automatyzację przeglądarki, dzięki czemu jest idealnym wyborem dla platform takich jak Instagram. W połączeniu z biblioteką lxml do parsowania HTML, Playwright znacznie upraszcza ekstrakcję danych, pozwalając na automatyzację interakcji z elementami strony i proces parsowania bez ręcznej interwencji. Dodatkowo, wykorzystanie serwerów proxy pomaga obejść ochronę przed botami i zapobiega blokowaniu IP, zapewniając stabilne i nieprzerwane operacje skrobania.
Komentarze: 0