2017-10-16 2 views
1

Ceci est ma première tentative d'utilisation de la programmation pour quelque chose d'utile, alors s'il vous plaît gardez avec moi. La rétroaction constructive est très appréciée :)Création d'une liste d'URL à partir d'un site Web spécifique

Je travaille à la construction d'une base de données avec tous les communiqués de presse du Parlement européen. Jusqu'à présent, j'ai construit un grattoir qui peut récupérer les données que je veux d'une URL spécifique. Cependant, après avoir lu et consulté quelques tutoriels, je n'arrive toujours pas à comprendre comment créer une liste d'URL contenant tous les communiqués de presse de ce site spécifique. Peut-être que c'est lié à la façon dont le site Web est construit, ou je suis (probablement) juste manquant une chose évidente qu'un programme expérimenté réaliserait tout de suite, mais je ne sais pas vraiment comment procéder à partir d'ici.

Ceci est l'URL de départ: http://www.europarl.europa.eu/news/en/press-room

Voici mon code:

links = [] # Until now I have just manually pasted a few links 
      # into this list, but I need it to contain all the URLs to scrape 

# Function for removing html tags from text 
TAG_RE = re.compile(r'<[^>]+>') 
def remove_tags(text): 
    return TAG_RE.sub('', text) 

# Regex to match dates with pattern DD-MM-YYYY 
date_match = re.compile(r'\d\d-\d\d-\d\d\d\d') 

# For-loop to scrape variables from site 
for link in links: 

    # Opening up connection and grabbing page 
    uClient = uReq(link) 

    # Saves content of page in new variable (still in HTML!!) 
    page_html = uClient.read() 

    # Close connection 
    uClient.close() 

    # Parsing page with soup 
    page_soup = soup(page_html, "html.parser") 

    # Grabs page 
    pr_container = page_soup.findAll("div",{"id":"website"}) 

    # Scrape date 
    date_container = pr_container[0].time 
    date = date_container.text 
    date = date_match.search(date) 
    date = date.group() 

    # Scrape title 
    title = page_soup.h1.text 
    title_clean = title.replace("\n", " ") 
    title_clean = title_clean.replace("\xa0", "") 
    title_clean = ' '.join(title_clean.split()) 
    title = title_clean 

    # Scrape institutions involved 
    type_of_question_container = pr_container[0].findAll("div", {"class":"ep_subtitle"}) 
    text = type_of_question_container[0].text 
    question_clean = text.replace("\n", " ") 
    question_clean = text.replace("\xa0", " ") 
    question_clean = re.sub("\d+", "", question_clean) # Redundant? 
    question_clean = question_clean.replace("-", "") 
    question_clean = question_clean.replace(":", "") 
    question_clean = question_clean.replace("Press Releases"," ") 
    question_clean = ' '.join(question_clean.split()) 
    institutions_mentioned = question_clean 

    # Scrape text 
    text_container = pr_container[0].findAll("div", {"class":"ep-a_text"}) 
    text_with_tags = str(text_container) 
    text_clean = remove_tags(text_with_tags) 
    text_clean = text_clean.replace("\n", " ") 
    text_clean = text_clean.replace(",", " ") # Removing commas to avoid trouble with .csv-format later on 
    text_clean = text_clean.replace("\xa0", " ") 
    text_clean = ' '.join(text_clean.split()) 

    # Calculate word count 
    word_count = len(text_clean.split()) 
    word_count = str(word_count) 

    print("Finished scraping: " + link) 

    time.sleep(randint(1,5)) 

    f.write(date + "," + title + ","+ institutions_mentioned + "," + word_count + "," + text_clean + "\n") 

    f.close() 
+0

html ont méthode actuelle pour urls puting, en html, nous avons: src, href et de l'action pour tous les liens, pour src => ('script', 'img', 'source', 'video', ' audio ',' embed ',' iframe ',' input ',' track '), pour href => (' a ',' link ',' area ',' base ') et pour l'action => (' forme '), vous devez d'abord extraire ces balises, puis extraire leur chaque src, href et action sub_tag (sans rien analyser ou supprimer les chaînes sales), avec cette méthode, vous pouvez extraire toutes les URL html standard, vous pouvez le faire avec le module beautifulsoup et deux fors! – DRPK

Répondre

1

est inférieure à la façon simple d'obtenir la liste des liens nécessaires avec python-requests et lxml:

from lxml import html 
import requests 
url = "http://www.europarl.europa.eu/news/en/press-room/page/" 
list_of_links = [] 
for page in range(10): 
    r = requests.get(url + str(page)) 
    source = r.content 
    page_source = html.fromstring(source) 
    list_of_links.extend(page_source.xpath('//a[@title="Read more"]/@href')) 
print(list_of_links) 
+0

Merci beaucoup pour vos commentaires. Je me demandais si vous pouviez clarifier comment je peux savoir si un site Web est dynamique ou non? Votre méthode fonctionne pour les 15 premiers liens de l'URL initiale, mais ai-je besoin du module Selenium pour "cliquer" sur le bouton "charger plus"? –

+1

Si le contenu est dans la source de la page - c'est un contenu statique, s'il est généré par JavaScript - c'est un contenu dynamique. Simple mettre, vous pouvez vérifier la source de la page par un clic droit sur la page web dans le navigateur: si vous pouvez trouver le contenu requis - il est statique, sinon - il est dynamique. – Andersson

+1

@DanielHansen, vous pouvez vérifier la réponse mise à jour qui est applicable aux 10 premières pages (150 liens). Vous pouvez définir une plus grande plage ou remplacer la boucle 'for' par' while' – Andersson

0

Edit: Les 15 premières URL peuvent être obtenus sans utiliser le module de sélénium.


Vous ne pouvez pas utiliser urllib.request (je suppose que c'est ce que vous utilisez) pour obtenir les URL des communiqués de presse, parce que le contenu de ce site est chargé dynamiquement.

Vous pouvez essayer d'utiliser le module sélénium.

from bs4 import BeautifulSoup 
from selenium import webdriver 
from selenium.webdriver.support.ui import WebDriverWait 

driver = webdriver.Firefox() 
driver.get('http://www.europarl.europa.eu/news/en/press-room') 

# Click "Load More", repeat these as you like 
WebDriverWait(driver, 50).until(EC.visibility_of_element_located((By.ID, "continuesLoading_button"))) 
driver.find_element_by_id("continuesLoading_button").click() 

# Get urls 
soup = BeautifulSoup(driver.page_source) 
urls = [a["href"] for a in soup.select(".ep_gridrow-content .ep_title a")] 
+0

Non. Ce contenu n'est pas dynamique – Andersson

0

Vous pouvez lire le BeautifulSoup documentation officiel pour obtenir un meilleur à gratter. Vous devriez également vérifier Scrapy.

Voici un extrait simple permettant d'extraire les liens requis de cette page.
J'utilise la bibliothèque Requests dans l'exemple suivant. Faites-moi savoir si vous avez d'autres questions.

Bien que ce script ne clique pas sur "Charger plus" et charge des versions supplémentaires.
Je vous laisse à vous;) (Astuce: Utilisez Selenium ou Scrapy)

def scrape_press(url): 
    page = requests.get(url) 

    if page.status_code == 200: 
     urls = list() 
     soup = BeautifulSoup(page.content, "html.parser") 
     body = soup.find_all("h3", {"class": ["ep-a_heading", "ep-layout_level2"]}) 
     for b in body: 
      links = b.find_all("a", {"title": "Read more"}) 
      if len(links) == 1: 
       link = links[0]["href"] 
       urls.append(link) 

     # Printing the scraped links 
     for _ in urls: 
      print(_) 

Remarque: Vous devez grattez les données à partir d'un site Web si et seulement s'il est légal de le faire .

1

Vous pouvez saisir les liens en utilisant requests et BeautifulSoup avec seulement six codes de doublure. Bien que le script soit essentiellement identique à Sir Andersson, la bibliothèque et l'utilisation appliquée ici sont légèrement différentes.

import requests ; from bs4 import BeautifulSoup 

base_url = "http://www.europarl.europa.eu/news/en/press-room/page/{}" 
for url in [base_url.format(page) for page in range(10)]: 
    soup = BeautifulSoup(requests.get(url).text,"lxml") 
    for link in soup.select('[title="Read more"]'): 
     print(link['href'])