2016-02-15 21 views
5

Bitte tragen Sie mit mir. Ich bin ziemlich neu bei Python - aber mit viel Spaß. Ich versuche einen Web-Crawler zu programmieren, der durch die Wahlergebnisse des letzten Referendums in Dänemark kriecht. Ich habe es geschafft, alle relevanten Links von der Hauptseite zu extrahieren. Und jetzt möchte ich, dass Python jedem der 92 Links folgt und 9 Informationen von jeder dieser Seiten sammelt. Aber ich bin so festgefahren. Hoffe, du kannst mir einen Hinweis geben.Web-Crawler - folgende Links

Hier ist mein Code:

import requests 
import urllib2 
from bs4 import BeautifulSoup 

# This is the original url http://www.kmdvalg.dk/ 

soup = BeautifulSoup(urllib2.urlopen('http://www.kmdvalg.dk/').read()) 

my_list = [] 
all_links = soup.find_all("a") 

for link in all_links: 
    link2 = link["href"] 
    my_list.append(link2) 

for i in my_list[1:93]: 
    print i 

# The output shows all the links that I would like to follow and gather information from. How do I do that? 
+0

Können Sie mehr über 9 Stück Informationen erwähnen, die Sie in jedem Links greifen möchten? – titipata

+0

Wow - ihr seid super !! Ich werde einige Zeit damit verbringen müssen, Ihre Lösungen zu verstehen. Ich werde zurück sein, sobald ich sie verstanden habe. DANKE VIELMALS! – Metods

+0

@titipat: Ja. Schauen Sie sich diese Unterseite an. Ich will "stemmeberettigede/Anzahl der Leute, die abstimmen können", "Optalte stemmer/gezählte Stimmen", "JA-stemmer/Leute, die ja stimmen", "NEJ-stemmer/leute, die nicht gewählt haben", "Blanke stemmer/blank Stimmen "," Ugyldige stemmer/ungültige Stimmen "und der Name der Gemeinde (Assenskredsen in diesem Fall) – Metods

Antwort

4

Ein einfacher Ansatz wäre durch die Liste von URLs zu wiederholen und analysieren sie jede einzeln:

for url in my_list: 
    soup = BeautifulSoup(urllib2.urlopen(url).read()) 
    # then parse each page individually here 

Alternativ könnten Sie die Dinge beschleunigen deutlich Futures verwenden.

from requests_futures.sessions import FuturesSession 

def my_parse_function(html): 
    """Use this function to parse each page""" 
    soup = BeautifulSoup(html) 
    all_paragraphs = soup.find_all('p') 
    return all_paragraphs 

session = FuturesSession(max_workers=5) 
futures = [session.get(url) for url in my_list] 

page_results = [my_parse_function(future.result()) for future in results] 
+0

Das ist einfach so toll. Mein Skript funktioniert jetzt dank Ihres Kommentars zum Durchlaufen meiner Liste von URLs. – Metods

+0

UPS - wurde nicht gemacht. Ich bin sicher, dass alle anderen Vorschläge auf dieser Seite cooler sind - aber ich wähle den Frieden des Rates, den ich verstehen konnte. Vielen Dank. Dies ist mein endgültiger Code, der funktioniert - wenn Sie Vorschläge haben, um es schlauer zu machen, lassen Sie es mich wissen. Viele Grüße von Methoden. – Metods

5

Hier ist meine Lösung lxml verwenden. Es ist ähnlich wie BeautifulSoup

import lxml 
from lxml import html 
import requests 

page = requests.get('http://www.kmdvalg.dk/main') 
tree = html.fromstring(page.content) 
my_list = tree.xpath('//div[@class="LetterGroup"]//a/@href') # grab all link 
print 'Length of all links = ', len(my_list) 

my_list ist eine Liste aller Links bestehen. Und jetzt können Sie for-Schleife verwenden, um Informationen innerhalb jeder Seite zu scrappen.

Wir können für jede Links durchschleifen. Auf jeder Seite können Sie Informationen als Beispiel extrahieren. Dies ist nur für den obersten Tisch.

table_information = [] 
for t in my_list: 
    page_detail = requests.get(t) 
    tree = html.fromstring(page_detail.content) 
    table_key = tree.xpath('//td[@class="statusHeader"]/text()') 
    table_value = tree.xpath('//td[@class="statusText"]/text()') + tree.xpath('//td[@class="statusText"]/a/text()') 
    table_information.append(zip([t]*len(table_key), table_key, table_value)) 

Für Tabelle unterhalb der Seite,

table_information_below = [] 
for t in my_list: 
    page_detail = requests.get(t) 
    tree = html.fromstring(page_detail.content) 
    l1 = tree.xpath('//tr[@class="tableRowPrimary"]/td[@class="StemmerNu"]/text()') 
    l2 = tree.xpath('//tr[@class="tableRowSecondary"]/td[@class="StemmerNu"]/text()') 
    table_information_below.append([t]+l1+l2) 

Hope this Hilfe!

2

Das wäre meine Lösung für Ihr Problem

import requests 
from bs4 import BeautifulSoup 


def spider(): 
    url = "http://www.kmdvalg.dk/main" 
    source_code = requests.get(url) 
    plain_text = source_code.text 
    soup = BeautifulSoup(plain_text, 'html.parser') 

    for link in soup.findAll('div', {'class': 'LetterGroup'}): 
     anc = link.find('a') 
     href = anc.get('href') 

     print(anc.getText()) 
     print(href) 
     # spider2(href) call a second function from here that is similar to this one(making url = to herf) 
     spider2(href) 
     print("\n") 


def spider2(linktofollow): 
    url = linktofollow 
    source_code = requests.get(url) 
    plain_text = source_code.text 
    soup = BeautifulSoup(plain_text, 'html.parser') 

    for link in soup.findAll('tr', {'class': 'tableRowPrimary'}): 
     anc = link.find('td') 

     print(anc.getText()) 
    print("\n") 


spider() 

seine nicht getan sein ... ich nur ein einfaches Element aus der Tabelle erhalten, aber Sie bekommen die Idee und wie seine angeblich zu arbeiten.

+0

anstelle von find ('td') in der zweiten Funktion können Sie findAll mit dem Namen der td-Klasse verwenden, die Sie finden möchten. – CVasquezG

1

Hier ist mein abschließender Code, der reibungslos funktioniert. Bitte lassen Sie es mich wissen, wenn ich es klüger hätte machen können!

import urllib2 
from bs4 import BeautifulSoup 
import codecs 

f = codecs.open("eu2015valg.txt", "w", encoding="iso-8859-1") 

soup = BeautifulSoup(urllib2.urlopen('http://www.kmdvalg.dk/').read()) 

liste = [] 

alle_links = soup.find_all("a") 

for link in alle_links: 
    link2 = link["href"] 
    liste.append(link2) 

for url in liste[1:93]: 
    soup = BeautifulSoup(urllib2.urlopen(url).read().decode('iso-8859-1')) 
    tds = soup.findAll('td') 
    stemmernu = soup.findAll('td', class_='StemmerNu') 
    print >> f, tds[5].string,";",tds[12].string,";",tds[14].string,";",tds[16].string,";", stemmernu[0].string,";",stemmernu[1].string,";",stemmernu[2].string,";",stemmernu[3].string,";",stemmernu[6].string,";",stemmernu[8].string,";",'\r\n' 

f.close()