Python: BeautifulSoup Scrape, пустые описания курсов, использующих данные - PullRequest
0 голосов
/ 27 ноября 2018

Я пытаюсь собрать некоторые данные курса с сайта https://bulletins.psu.edu/university-course-descriptions/undergraduate/ для проекта.

# -*- coding: utf-8 -*-
"""
Created on Mon Nov  5 20:37:33 2018

@author: DazedFury
"""
# Here, we're just importing both Beautiful Soup and the Requests library
from bs4 import BeautifulSoup
import requests

# returns a CloudflareScraper instance
#scraper = cfscrape.create_scraper()  

#URL and textfile
text_file = open("Output.txt", "w", encoding='UTF-8')
page_link = 'https://bulletins.psu.edu/university-course-descriptions/undergraduate/acctg/'
page_response = requests.get(page_link)
page_content = BeautifulSoup(page_response.content, "html.parser")

#Array for storing URL's
URLArray = []

#Find links
for link in page_content.find_all('a'):
    if('/university-course-descriptions/undergraduate' in link.get('href')):
        URLArray.append(link.get('href'))
k = 1

#Parse Loop        
while(k != 242):
    print("Writing " + str(k))

    completeURL = 'https://bulletins.psu.edu' + URLArray[k]  

    # this is the url that we've already determined is safe and legal to scrape from.
    page_link = completeURL

    # here, we fetch the content from the url, using the requests library
    page_response = requests.get(page_link)

    #we use the html parser to parse the url content and store it in a variable.
    page_content = BeautifulSoup(page_response.content, "html.parser")
    page_content.prettify    

    #Find and print all text with tag p
    paragraphs = page_content.find_all('div', {'class' : 'course_codetitle'})
    paragraphs2 = page_content.find_all('div', {'class' : 'courseblockdesc'})
    j = 0
    for i in range(len(paragraphs)):
        if i % 2 == 0:
            text_file.write(paragraphs[i].get_text())
            text_file.write("\n")
            if j < len(paragraphs2):
                text_file.write(" ".join(paragraphs2[j].get_text().split()))
                text_file.write("\n")
                text_file.write("\n")
                if(paragraphs2[j].get_text() != ""):
                    j += 1

    k += 1

#FORMAT
#text_file.write("<p style=\"page-break-after: always;\">&nbsp;</p>")
#text_file.write("\n\n")

#Close Text File
text_file.close()

Конкретная информация, которая мне нужна, - это название курса и описание.Проблема состоит в том, что некоторые курсы имеют пустые описания, которые портят порядок и дают неверные данные.

output.txt

bulletin

Я думал о том, чтобы просто проверить, если описание курса пустое, но на сайте тег 'courseblockdesc' не существует, если у курса нет описания.Поэтому, когда я нахожу_all courseblockdesc, список на самом деле не добавляет элемент add в массив, поэтому порядок в итоге испортился.Здесь слишком много ошибок, чтобы их можно было исправить вручную, поэтому я надеялся, что кто-нибудь может помочь мне найти решение этой проблемы.

Ответы [ 2 ]

0 голосов
/ 27 ноября 2018

Возможно, вы несколько усложняете процедуру, но вы точно на правильном пути.Вместо того, чтобы хранить информацию в массиве и полагаться на все индексы для выстраивания в ряд, напишите текстовый файл при прохождении курсов, динамически извлекая заголовок и описание из каждого блока курса.Если у блока нет описания, вы можете обработать его на месте.Вот рабочий пример:

from bs4 import BeautifulSoup
import requests

url = "https://bulletins.psu.edu/university-course-descriptions/undergraduate/acctg/"

with open("out.txt", "w", encoding="UTF-8") as f:
    for link in BeautifulSoup(requests.get(url).content, "html.parser").find_all("a"):
        if "/university-course-descriptions/undergraduate" in link["href"]:
            soup = BeautifulSoup(requests.get("https://bulletins.psu.edu" + link["href"]).content, "html.parser")

            for course in soup.find_all("div", {"class": "courseblock"}):
                title = course.find("div", {"class" : "course_title"}).get_text().strip()

                try:
                    desc = course.find("div", {"class" : "courseblockdesc"}).get_text().strip()
                except AttributeError:
                    desc = "No description available"

                f.write(title + "\n" + desc + "\n\n")

Фрагмент вывода (от конца текстового файла для проверки выравнивания):

WLED 495: **SPECIAL TOPICS**
No description available

WLED 495B: Field Experience for World Languages Teacher Preparation in Grades 1-5
WL ED 495B Field Experience for World Languages Teacher Preparation in Grades 1-5 (3) Practicum situation where Prospective World Language teachers will demonstrate acquired knowledge on second language learning/teaching and educational theories. Prospective World Language teachers will have assigned school placements and will attend a weekly seminar where issues in World Language learning and teaching will be discussed. At their assigned school placement, prospective World Language teachers will have many opportunities to observe/work with children in grades 1-5 (1) focusing on second language learning/teaching and the socio/cultural issues associated to classroom practices while implementing and self-evaluated own designed activities and lessons; (2) weekly seminars will engage students in reflective activities that will enable them to analyze each week's events; (3) inquiry projects on teaching and learning of World Languages.

WLED 495C: Field Experience for World Languages Teacher Preparation in Grades 6-12
WL ED 495C Field Experience for World Languages Teacher Preparation in Grades 6-12 (3) Practicum situation where prospective World Language teachers will demonstrate acquired knowledge on second language learning/teaching and educational theories. Prospective World Language teachers will have assigned school placements in grades 6-12 and will attend a weekly seminar where issues in World Language learning and teaching will be discussed. At their assigned school placement, prospective World Language teachers will have many opportunities to observe/work with students in grades 6-12 (1) focusing on second language learning/teaching and the socio/cultural issues associated to classroom practices while implementing and self-evaluating their own designed activities and lessons, (2) weekly seminars will engage students in reflective activities that will enable them to analyze each week's events, and (3) inquiry projects on teaching and learning of World Languages.

Дополнительные второстепенные замечания:

  • Рекомендуется использовать ключевое слово with для файлового ввода-вывода.Это автоматически закроет дескриптор файла, когда закончите.

  • Подробные промежуточные переменные и комментарии, которые добавляют шум, такие как:

# Here, we're just importing both Beautiful Soup and the Requests library
from bs4 import BeautifulSoup

или

#Close Text File
text_file.close()

всегда могут бытьудален, что облегчает логику программы.

0 голосов
/ 27 ноября 2018

Самое простое решение - просмотреть каждый элемент в одном find_all для родителей искомых элементов.

for block in page_content.find_all('div', class_="courseblock"):
    title = block.find('div', {'class' : 'course_codetitle'})
    description = block.find('div', {'class' : 'courseblockdesc'})
    #  do what you need with the navigable strings here.
    print(title.get_text()
    if description:
       print(description.get_text())
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...