1

I wrote a python code to scrape data from the site. It doesn't seem to work the way it supposed to do. I want to get all the articles from the page, but I get one paragraph from the first article multiple times. I can't see what's wrong with the code. Please help me fix it if you know what's the issue.

import requests
from bs4 import BeautifulSoup

URL = 'https://zdravi.doktorka.cz/clanky?page=0'

HEADERS = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36', 'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9'}

HOST = 'https://zdravi.doktorka.cz'

def get_html(url, params=None):
    r = requests.get(url, headers=HEADERS, params=params)
    return r

def get_content(html):
    soup = BeautifulSoup(html, 'html.parser')
    items = soup.find_all('article', class_='node-teaser-display')

    articles = []
    for item in items:
        articles.append({
            HOST + item.find('a').get('href'),
            
        })
        
    arts = []
    
    for each in articles:
        b = ''.join(each)
        arts.append(b)

    for art in arts:
        page = get_html(art)
        pagesoup = BeautifulSoup(html, 'html.parser')
        parags = pagesoup.find('p').get_text()
        print(art)
        print(parags)

def parse():
    html = get_html(URL)
    if html.status_code == 200:
        get_content(html.text)
    else:
        print('Error')
parse()

This is the response:

https://zdravi.doktorka.cz/infekcnost-bezpriznakovych-nosicu-covid-19-muze-byt-slaba-naznacuje-studie
Jsme tým lékařů, terapeutů, kosmetiček, odborníků pracujících ve zdravotnictví, v oboru fitness a ekologie. Náš web funguje od roku 1999 a patří mezi nejnavštěvovanější weby zabývající se zdravým životním stylem v ČR.
https://zdravi.doktorka.cz/pri-operativni-lecbe-sedeho-zakalu-existuji-tri-moznosti
Jsme tým lékařů, terapeutů, kosmetiček, odborníků pracujících ve zdravotnictví, v oboru fitness a ekologie. Náš web funguje od roku 1999 a patří mezi nejnavštěvovanější weby zabývající se zdravým životním stylem v ČR.
https://zdravi.doktorka.cz/epidemiolog-varuje-pred-dlouhodobym-nosenim-rousek
Jsme tým lékařů, terapeutů, kosmetiček, odborníků pracujících ve zdravotnictví, v oboru fitness a ekologie. Náš web funguje od roku 1999 a patří mezi nejnavštěvovanější weby zabývající se zdravým životním stylem v ČR.
https://zdravi.doktorka.cz/jidlo-muze-prozradit-na-co-mate-alergii
Jsme tým lékařů, terapeutů, kosmetiček, odborníků pracujících ve zdravotnictví, v oboru fitness a ekologie. Náš web funguje od roku 1999 a patří mezi nejnavštěvovanější weby zabývající se zdravým životním stylem v ČR.
https://zdravi.doktorka.cz/jak-muzeme-nyni-posilit-svou-imunitu
Jsme tým lékařů, terapeutů, kosmetiček, odborníků pracujících ve zdravotnictví, v oboru fitness a ekologie. Náš web funguje od roku 1999 a patří mezi nejnavštěvovanější weby zabývající se zdravým životním stylem v ČR.
kindall
  • 178,883
  • 35
  • 278
  • 309

1 Answers1

1

In for-loop you have to use page.text instead of html

for art in arts:
    page = get_html(art)
    pagesoup = BeautifulSoup(page.text, 'html.parser')
    parags = pagesoup.find('p').get_text()
    print(art)
    print(parags)

In html you have HTML from main page - so you always parsed the same HTML. But later you get new response from subpage and assing to variable page - and this variable has HTML from subpage.

BTW: Probably you would see it if you would check print( html )


EDIT: Full working code with other changes and with saving to file .csv

import requests
from bs4 import BeautifulSoup
import csv

URL = 'https://zdravi.doktorka.cz/clanky?page=0'

HEADERS = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36', 'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9'}

HOST = 'https://zdravi.doktorka.cz'

def get_soup(url, headers=HEADERS, params=None):
    r = requests.get(url, headers=headers, params=params)
    
    if r.status_code != 200:
        print('Error:', r.status_code, url)
        return

    return BeautifulSoup(r.text, 'html.parser')

def get_content(soup):
    
    data = []
    
    articles = soup.find_all('article', class_='node-teaser-display')

    for item in articles:
        url = HOST + item.find('a').get('href')
        print(url)
        
        soup = get_soup(url)
        if soup:
        
            paragraph = soup.find('p').get_text().strip()
            print(paragraph)
  
            data.append({
                'url': url,
                'paragraph': paragraph,
            })
    
        print('---')
        
    with open('output.csv', 'w') as fh:
        csv_writer = csv.DictWriter(fh, ['url', 'paragraph'])
        csv_writer.writeheader()
        csv_writer.writerows(data)           
        
def parse():
    soup = get_soup(URL)
    if soup:
        get_content(soup)
       
if __name__ == '__main__':        
    parse()
furas
  • 134,197
  • 12
  • 106
  • 148
  • hi Furas : many thanks for this great answer to an interesting question. And many thanks for the idea with saving to a csv-file: this is very helpful - also here - in the great work that we both have set up: https://stackoverflow.com/questions/62595317/login-to-page-with-selenium-works-parsing-with-bs4-works-but-not-the-combina - well i think i have to digg deeper into your ideas and approach - and i need to set the selenium-session to work with bs4 - or what would you say?! - look forward to hear from you. Regards zero – zero Jul 02 '20 at 23:26