Удалите несколько страниц с помощью BeautifulSoup и Python

Мой код успешно сбрасывает теги tr align = center из [http://my.gwu.edu/mod/pws/courses.cfm?campId=1&termId=201501&subjId=ACCY] и записывает элементы td в текстовый файл.

Однако на сайте выше доступны несколько страниц, в которых я хотел бы очистить.

Например, с указанным выше адресом, когда я нажимаю ссылку на "стр. 2", общий URL не изменяется. Я посмотрел на источник страницы и увидел javascript-код для перехода на следующую страницу.

Как мой код может быть изменен для очистки данных со всех доступных страниц?

Мой код, который работает только для страницы 1:

import bs4
import requests 

response = requests.get('http://my.gwu.edu/mod/pws/courses.cfm?campId=1&termId=201501&subjId=ACCY')

soup = bs4.BeautifulSoup(response.text)
soup.prettify()

acct = open("/Users/it/Desktop/accounting.txt", "w")

for tr in soup.find_all('tr', align='center'):
    stack = []
    for td in tr.findAll('td'):
        stack.append(td.text.replace('\n', '').replace('\t', '').strip())

    acct.write(", ".join(stack) + '\n')

Ответ 1

Трюк здесь заключается в том, чтобы проверять запросы, которые входят и выходят из действия изменения страницы, когда вы нажимаете на ссылку, чтобы просмотреть другие страницы. Способ проверить это - использовать инструмент проверки Chrome (нажав F12) или установить расширение Firebug в Firefox. В этом ответе я буду использовать инструмент проверки Chrome. Ниже приведены мои настройки.

enter image description here

Теперь то, что мы хотим увидеть, - это либо запрос GET на другую страницу, либо запрос POST, который изменяет страницу. Пока инструмент открыт, щелкните номер страницы. В течение очень короткого момента появится только один запрос, который будет отображаться, и это метод POST. Все остальные элементы будут быстро следовать и заполнять страницу. Смотрите ниже, что мы ищем.

enter image description here

Нажмите на выше описанный метод POST. Он должен вызывать вспомогательные окна, имеющие вкладки. Перейдите на вкладку Headers. На этой странице перечислены заголовки запросов, в значительной степени идентификационные данные, которые другая сторона (например, сайт) нуждается в вас, чтобы иметь возможность подключиться (кто-то может объяснить этот muuuch лучше, чем я).

Всякий раз, когда URL-адрес имеет переменные, такие как номера страниц, маркеры местоположений или категории, чаще всего это не так, сайт использует строки запросов. Короткий длинный рассказ похож на SQL-запрос (на самом деле это SQL-запрос, иногда), который позволяет сайту извлекать нужную вам информацию. Если это так, вы можете проверить заголовки запросов для параметров строки запроса. Прокрутите вниз немного, и вы должны его найти.

enter image description here

Как вы можете видеть, параметры строки запроса соответствуют переменным в нашем URL-адресе. Немного ниже, вы можете видеть Form Data с pageNum: 2 под ним. Это ключ.

POST запросы чаще известны как запросы формы, потому что это те запросы, которые были сделаны при отправке форм, регистрации на веб-сайтах и ​​т.д. В принципе, практически все, что вам нужно, чтобы отправлять информацию. Большинство людей не видят, что запросы POST имеют URL-адрес, за которым они следуют. Хорошим примером этого является, когда вы входите в систему на веб-сайт и, очень кратко, видите, что ваш адресный бар превращается в какой-то талисманный URL-адрес перед тем, как установить /index.html или somesuch.

В основном это означает, что вы можете (но не всегда) добавлять данные формы к своему URL-адресу, и он выполнит запрос POST для вас при выполнении. Чтобы узнать точную строку, которую вы должны добавить, нажмите view source.

enter image description here

Проверьте, работает ли он, добавив его в URL.

enter image description here

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

Измененный код ниже:

from bs4 import BeautifulSoup as bsoup
import requests as rq
import re

base_url = 'http://my.gwu.edu/mod/pws/courses.cfm?campId=1&termId=201501&subjId=ACCY'
r = rq.get(base_url)

soup = bsoup(r.text)
# Use regex to isolate only the links of the page numbers, the one you click on.
page_count_links = soup.find_all("a",href=re.compile(r".*javascript:goToPage.*"))
try: # Make sure there are more than one page, otherwise, set to 1.
    num_pages = int(page_count_links[-1].get_text())
except IndexError:
    num_pages = 1

# Add 1 because Python range.
url_list = ["{}&pageNum={}".format(base_url, str(page)) for page in range(1, num_pages + 1)]

# Open the text file. Use with to save self from grief.
with open("results.txt","wb") as acct:
    for url_ in url_list:
        print "Processing {}...".format(url_)
        r_new = rq.get(url_)
        soup_new = bsoup(r_new.text)
        for tr in soup_new.find_all('tr', align='center'):
            stack = []
            for td in tr.findAll('td'):
                stack.append(td.text.replace('\n', '').replace('\t', '').strip())
            acct.write(", ".join(stack) + '\n')

Мы используем регулярные выражения для получения правильных ссылок. Затем, используя понимание списка, мы создали список строк URL. Наконец, мы перебираем их.

Результаты:

Processing http://my.gwu.edu/mod/pws/courses.cfm?campId=1&termId=201501&subjId=ACCY&pageNum=1...
Processing http://my.gwu.edu/mod/pws/courses.cfm?campId=1&termId=201501&subjId=ACCY&pageNum=2...
Processing http://my.gwu.edu/mod/pws/courses.cfm?campId=1&termId=201501&subjId=ACCY&pageNum=3...
[Finished in 6.8s]

enter image description here

Надеюсь, что это поможет.

EDIT:

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

from bs4 import BeautifulSoup as bsoup
import requests as rq
import re

spring_2015 = "http://my.gwu.edu/mod/pws/subjects.cfm?campId=1&termId=201501"
r = rq.get(spring_2015)
soup = bsoup(r.text)
classes_url_list = [c["href"] for c in soup.find_all("a", href=re.compile(r".*courses.cfm\?campId=1&termId=201501&subjId=.*"))]
print classes_url_list

with open("results.txt","wb") as acct:
    for class_url in classes_url_list:
        base_url = "http://my.gwu.edu/mod/pws/{}".format(class_url)
        r = rq.get(base_url)

        soup = bsoup(r.text)
        # Use regex to isolate only the links of the page numbers, the one you click on.
        page_count_links = soup.find_all("a",href=re.compile(r".*javascript:goToPage.*"))
        try:
            num_pages = int(page_count_links[-1].get_text())
        except IndexError:
            num_pages = 1

        # Add 1 because Python range.
        url_list = ["{}&pageNum={}".format(base_url, str(page)) for page in range(1, num_pages + 1)]

        # Open the text file. Use with to save self from grief.
        for url_ in url_list:
            print "Processing {}...".format(url_)
            r_new = rq.get(url_)
            soup_new = bsoup(r_new.text)
            for tr in soup_new.find_all('tr', align='center'):
                stack = []
                for td in tr.findAll('td'):
                    stack.append(td.text.replace('\n', '').replace('\t', '').strip())
                acct.write(", ".join(stack) + '\n')

Ответ 2

Как насчет этой ссылки? Https://www.traveloka.com/id-id/hotel/indonesia/horison-ultima-bandung-2000000081026?spec=26-05-2019.27-05-2019.1.1.HOTEL.2000000081026.Horison %20Ultima %20Bandung.2 & prevSearchId = 1634474608622074440 & loginPromo = 1 & contexts =% 7B% 7D "?

Сейчас я пытаюсь очистить несколько страниц, но когда я нажимаю ссылку на "страницу 2", общий URL-адрес НЕ меняется.