Skrobanie sieci za pomocą Pythona [zamknięte]

183

Chciałbym pobrać codzienne wschody i zachody słońca ze strony internetowej. Czy możliwe jest zeskrobywanie treści internetowych za pomocą Pythona? jakie są używane moduły? Czy jest dostępny tutorial?

eozzy
źródło
3
Python ma kilka opcji skrobania stron internetowych. I wymienił niektóre opcje tutaj w odpowiedzi na podobne pytanie.
filippo
Dlaczego nie skorzystać z wbudowanego parsera HTML w standardowej bibliotece Python? Z pewnością w przypadku zadania tak prostego i rzadkiego (tylko raz dziennie) nie widzę powodu, aby szukać innych narzędzi. docs.python.org/2.7/library/htmlparser.html
ArtOfWarfare
Mam nadzieję, że ten post może być dla kogoś przydatny. Dobry samouczek dla początkującego. samranga.blogspot.com/2015/08/web-scraping-beginner-python.html Wykorzystuje piękną bibliotekę Python do zupy do skrobania stron internetowych za pomocą Pythona.
Samitha Chathuranga

Odpowiedzi:

187

Użyj urllib2 w połączeniu z genialną biblioteką BeautifulSoup :

import urllib2
from BeautifulSoup import BeautifulSoup
# or if you're using BeautifulSoup4:
# from bs4 import BeautifulSoup

soup = BeautifulSoup(urllib2.urlopen('http://example.com').read())

for row in soup('table', {'class': 'spad'})[0].tbody('tr'):
    tds = row('td')
    print tds[0].string, tds[1].string
    # will print date and sunrise
lesmana
źródło
7
Mały komentarz: można to nieco uprościć za pomocą pakietu żądań, zastępując wiersz 6: zupa = BeautifulSoup (requests.get (' example.com'). Tekst )
D Coetzee
4
dzięki za wskazówkę. pakiet żądania jeszcze nie istniał, kiedy napisałem powyższy fragment ;-)
1
@DerrickCoetzee - twoje uproszczenie powoduje błąd MissingSchema (przynajmniej w mojej instalacji). Działa to:soup = BeautifulSoup(requests.get('http://example.com').text)
kmote
@kmote: tak wpisałem, ale zapomniałem backtickskodu i przekształciłem go w link. Dzięki!
D Coetzee,
Skąd masz pewność, że zawartość będzie w td i tr. Może być także w ul i li, prawda?
Shashank Hegde,
62

Naprawdę poleciłbym Złom.

Cytat z usuniętej odpowiedzi:

  • Indeksowanie złomowania jest najszybsze niż mechanizacja, ponieważ wykorzystuje operacje asynchroniczne (na górze Twisted).
  • Scrapy ma lepszą i najszybszą obsługę parsowania (x) HTML na libxml2.
  • Złomowanie to dojrzałe środowisko z pełnym kodem Unicode, obsługuje przekierowania, odpowiedzi zgzip, nieparzyste kodowanie, zintegrowaną pamięć podręczną http itp.
  • Po przejściu do Scrapy możesz napisać pająka w mniej niż 5 minut, który pobiera obrazy, tworzy miniatury i eksportuje wyodrębnione dane bezpośrednio do csv lub json.
Sjaak Trekhaak
źródło
13
Nie zauważyłem, że to pytanie ma już 2 lata, nadal uważam, że należy wymienić tutaj Skrapy na wypadek, gdyby ktoś miał to samo pytanie.
Sjaak Trekhaak,
4
Złomowanie jest strukturą, dlatego jest okropne i uważa, że ​​jest ważniejsze niż twój projekt. To ramy z powodu strasznych (niepotrzebnych) ograniczeń Twisted.
user1244215,
4
@ user1244215: Jest to framework, ponieważ frameworki są ładne. Jeśli nie chcesz używać go jako frameworka, nic nie powstrzyma Cię przed zablokowaniem całego kodu w jednym pliku.
Blender
1
Ale nie obsługuje Python 3.x.
17

Zebrałem razem skrypty z mojej pracy polegającej na skrobaniu stron internetowych w tej bibliotece bit-bucket .

Przykładowy skrypt dla twojej sprawy:

from webscraping import download, xpath
D = download.Download()

html = D.get('http://example.com')
for row in xpath.search(html, '//table[@class="spad"]/tbody/tr'):
    cols = xpath.search(row, '/td')
    print 'Sunrise: %s, Sunset: %s' % (cols[1], cols[2])

Wynik:

Sunrise: 08:39, Sunset: 16:08
Sunrise: 08:39, Sunset: 16:09
Sunrise: 08:39, Sunset: 16:10
Sunrise: 08:40, Sunset: 16:10
Sunrise: 08:40, Sunset: 16:11
Sunrise: 08:40, Sunset: 16:12
Sunrise: 08:40, Sunset: 16:13
hoju
źródło
10

Zdecydowanie polecam sprawdzenie piractwa . Wykorzystuje składnię podobną do jquery (aka css-like), dzięki czemu jest naprawdę łatwa dla osób pochodzących z tego tła.

W twoim przypadku byłoby to mniej więcej tak:

from pyquery import *

html = PyQuery(url='http://www.example.com/')
trs = html('table.spad tbody tr')

for tr in trs:
  tds = tr.getchildren()
  print tds[1].text, tds[2].text

Wynik:

5:16 AM 9:28 PM
5:15 AM 9:30 PM
5:13 AM 9:31 PM
5:12 AM 9:33 PM
5:11 AM 9:34 PM
5:10 AM 9:35 PM
5:09 AM 9:37 PM
scottmrogowski
źródło
7

Możesz użyć urllib2 do wysyłania żądań HTTP, a wtedy będziesz mieć zawartość internetową.

Możesz to zrobić w następujący sposób:

import urllib2
response = urllib2.urlopen('http://example.com')
html = response.read()

Piękna Zupa to parser HTML w Pythonie, który powinien być dobry do zgarniania ekranu.

W szczególności, oto ich samouczek na temat parsowania dokumentu HTML.

Powodzenia!

Danben
źródło
Pomysłem może być ustawienie maksymalnej liczby odczytanych bajtów. response.read (100000000) lub coś takiego, aby te adresy URL ISO nie wypełniały pamięci RAM. Wesołego górnictwa.
andrew pate
4

Używam kombinacji Scrapemark (znajdowanie adresów URL - py2) i httlib2 (pobieranie obrazów - py2 + 3). Scrapemark.py ma 500 wierszy kodu, ale używa wyrażeń regularnych, więc może nie być tak szybki, nie testował.

Przykład skrobania witryny:

import sys
from pprint import pprint
from scrapemark import scrape

pprint(scrape("""
    <table class="spad">
        <tbody>
            {*
                <tr>
                    <td>{{[].day}}</td>
                    <td>{{[].sunrise}}</td>
                    <td>{{[].sunset}}</td>
                    {# ... #}
                </tr>
            *}
        </tbody>
    </table>
""", url=sys.argv[1] ))

Stosowanie:

python2 sunscraper.py http://www.example.com/

Wynik:

[{'day': u'1. Dez 2012', 'sunrise': u'08:18', 'sunset': u'16:10'},
 {'day': u'2. Dez 2012', 'sunrise': u'08:19', 'sunset': u'16:10'},
 {'day': u'3. Dez 2012', 'sunrise': u'08:21', 'sunset': u'16:09'},
 {'day': u'4. Dez 2012', 'sunrise': u'08:22', 'sunset': u'16:09'},
 {'day': u'5. Dez 2012', 'sunrise': u'08:23', 'sunset': u'16:08'},
 {'day': u'6. Dez 2012', 'sunrise': u'08:25', 'sunset': u'16:08'},
 {'day': u'7. Dez 2012', 'sunrise': u'08:26', 'sunset': u'16:07'}]
Nils Lindemann
źródło
1

Ułatw sobie życie, używając CSS Selectors

Wiem, że spóźniłem się na imprezę, ale mam dla ciebie fajną sugestię.

BeautifulSoupSugeruje się już używanie tego narzędzia. Wolałbym używać CSS Selectorsdo zeskrobywania danych wewnątrz HTML

import urllib2
from bs4 import BeautifulSoup

main_url = "http://www.example.com"

main_page_html  = tryAgain(main_url)
main_page_soup = BeautifulSoup(main_page_html)

# Scrape all TDs from TRs inside Table
for tr in main_page_soup.select("table.class_of_table"):
   for td in tr.select("td#id"):
       print(td.text)
       # For acnhors inside TD
       print(td.select("a")[0].text)
       # Value of Href attribute
       print(td.select("a")[0]["href"])

# This is method that scrape URL and if it doesnt get scraped, waits for 20 seconds and then tries again. (I use it because my internet connection sometimes get disconnects)
def tryAgain(passed_url):
    try:
        page  = requests.get(passed_url,headers = random.choice(header), timeout = timeout_time).text
        return page
    except Exception:
        while 1:
            print("Trying again the URL:")
            print(passed_url)
            try:
                page  = requests.get(passed_url,headers = random.choice(header), timeout = timeout_time).text
                print("-------------------------------------")
                print("---- URL was successfully scraped ---")
                print("-------------------------------------")
                return page
            except Exception:
                time.sleep(20)
                continue 
Umair
źródło
1

Jeśli myślimy o uzyskaniu nazw elementów z dowolnej określonej kategorii, możemy to zrobić, określając nazwę klasy tej kategorii za pomocą selektora css:

import requests ; from bs4 import BeautifulSoup

soup = BeautifulSoup(requests.get('https://www.flipkart.com/').text, "lxml")
for link in soup.select('div._2kSfQ4'):
    print(link.text)

To są częściowe wyniki wyszukiwania:

Puma, USPA, Adidas & moreUp to 70% OffMen's Shoes
Shirts, T-Shirts...Under ₹599For Men
Nike, UCB, Adidas & moreUnder ₹999Men's Sandals, Slippers
Philips & moreStarting 99LED Bulbs & Emergency Lights
SIM
źródło
0

Oto prosty przeszukiwacz sieci, użyłem BeautifulSoup, a my wyszukamy wszystkie linki (kotwice), których nazwa klasy to _3NFO0d. Korzystałem z Flipkar.com, jest to sklep internetowy.

import requests
from bs4 import BeautifulSoup
def crawl_flipkart():
    url = 'https://www.flipkart.com/'
    source_code = requests.get(url)
    plain_text = source_code.text
    soup = BeautifulSoup(plain_text, "lxml")
    for link in soup.findAll('a', {'class': '_3NFO0d'}):
        href = link.get('href')
        print(href)

crawl_flipkart()
Atul Chavan
źródło
0

Python ma dobre opcje na zeskrobywanie sieci. Najlepszym z ramami jest złomowanie . Może to być nieco trudne dla początkujących, więc tutaj jest mała pomoc.
1. Zainstaluj python powyżej 3.5 (niższe będą działały do ​​2.7).
2. Utwórz środowisko w conda (zrobiłem to).
3. Zainstaluj złom w miejscu i stamtąd.
4. Scrapy shellda ci interaktywny interfejs do testowania twojego kodu.
5. Scrapy startproject projectnamestworzy ramy.
6. Scrapy genspider spidernamestworzy pająka. Możesz stworzyć tyle pająków, ile chcesz. Robiąc to, upewnij się, że jesteś w katalogu projektu.


Łatwiej jest użyć próśb i pięknej zupy . Przed rozpoczęciem poświęć godzinę na przejrzenie dokumentacji, która rozwiąże większość twoich wątpliwości. BS4 oferuje szeroką gamę parserów, które możesz wybrać. Użyj user-agenti, sleepaby ułatwić skrobanie. BS4 zwraca bs.tag, więc użyj variable[0]. Jeśli działa js, nie będziesz w stanie zgarniać bezpośrednio za pomocą żądań i bs4. Możesz pobrać link interfejsu API, a następnie przeanalizować JSON, aby uzyskać potrzebne informacje lub wypróbować selenium.

Chris D'mello
źródło