Я пытаюсь очистить данные с этой веб-страницы и всех последующих 900 страниц: https://hansard.par Parliament.uk/search/Contributions?endDate=2019-07-11&page=1&searchTerm=%22climate+change%22&startDate = 1800-01-01 & partial = True

Важно, чтобы скребок не предназначался для ссылки на страницы, а скорее перебирал число "page =" в URL. Это связано с тем, что представленные данные динамически загружаются на исходную веб-страницу, на которую указывают ссылки на страницы.

Я пытался написать что-то, что перебирает номера страниц в URL через «последний» класс нумерации страниц ul, чтобы найти последнюю страницу, но я не уверен, как настроить таргетинг на определенную часть URL, сохраняя при этом поисковый запрос одинаков для каждого результата

r = requests.get(url_pagination)
soup = BeautifulSoup(r.content, "html.parser")

page_url = "https://hansard.parliament.uk/search/Contributions?endDate=2019-07-11&page={}" + "&searchTerm=%22climate+change%22&startDate=1800-01-01&partial=True"
last_page = soup.find('ul', class_='pagination').find('li', class_='last').a['href'].split('=')[1]
dept_page_url = [page_url.format(i) for i in range(1, int(last_page)+1)]

print(dept_page_url)

В идеале я хотел бы очистить только имя из класса "secondTitle" и второй безымянный div, который содержит дату для каждой строки.

Я получаю сообщение об ошибке: ValueError: недопустимый литерал для int () с основанием 10: '2019-07-11 & searchTerm'

0
Oliverater 11 Июл 2019 в 18:51

2 ответа

Лучший ответ

Вы можете попробовать этот сценарий, но будьте осторожны, он идет от страницы 1 до последней страницы 966:

import requests
from bs4 import BeautifulSoup

next_page_url = 'https://hansard.parliament.uk/search/Contributions?endDate=2019-07-11&page=1&searchTerm=%22climate+change%22&startDate=1800-01-01&partial=True'

# this goes to page '966'
while True:
    print('Scrapping {} ...'.format(next_page_url))
    r = requests.get(next_page_url)

    soup = BeautifulSoup(r.content, "html.parser")
    for secondary_title, date in zip(soup.select('.secondaryTitle'), soup.select('.secondaryTitle + *')):
        print('{: >20} - {}'.format(date.get_text(strip=True), secondary_title.get_text(strip=True)))

    next_link = soup.select_one('a:has(span:contains(Next))')
    if next_link:
        next_page_url = 'https://hansard.parliament.uk' + next_link['href'] + '&partial=True'
    else:
        break

Печать:

Scrapping https://hansard.parliament.uk/search/Contributions?endDate=2019-07-11&page=1&searchTerm=%22climate+change%22&startDate=1800-01-01&partial=True ...
     17 January 2007 - Ian Pearson
    21 December 2017 - Baroness Vere of Norbiton
          2 May 2019 - Lord Parekh
     4 February 2013 - Baroness Hanham
    21 December 2017 - Baroness Walmsley
     9 February 2010 - Colin Challen
     6 February 2002 - Baroness Farrington of Ribbleton
       24 April 2007 - Barry Gardiner
     17 January 2007 - Rob Marris
        7 March 2002 - The Parliamentary Under-Secretary of State, Department for Environment, Food and Rural Affairs (Lord Whitty)
     27 October 1999 - Mr. Tom Brake  (Carshalton and Wallington)
     9 February 2004 - Baroness Miller of Chilthorne Domer
        7 March 2002 - The Secretary of State for Environment, Food and Rural Affairs (Margaret Beckett)
    27 February 2007 - 
      8 October 2008 - Baroness Andrews
       24 March 2011 - Lord Henley
    21 December 2017 - Lord Krebs
    21 December 2017 - Baroness Young of Old Scone
        16 June 2009 - Mark Lazarowicz
        14 July 2006 - Lord Rooker
Scrapping https://hansard.parliament.uk/search/Contributions?endDate=2019-07-11&searchTerm=%22climate+change%22&startDate=1800-01-01&page=2&partial=True ...
     12 October 2006 - Lord Barker of Battle
     29 January 2009 - Lord Giddens


... and so on.
1
Andrej Kesely 11 Июл 2019 в 16:44

Ваша ошибка в том, что вы используете неправильный номер из вашего сплита. Вы хотите -1. Заметим :

last_page = soup.find('ul', class_='pagination').find('li', class_='last').a['href']
print(last_page)
print(last_page.split('=')[1])
print(last_page.split('=')[-1])

Дает:

/search/Contributions?endDate=2019-07-11&searchTerm=%22climate+change%22&startDate=1800-01-01&page=966

Когда разделить и использовать 1

2019-07-11&searchTerm

Против -1

966

Чтобы получить информацию с каждой страницы, которую вы хотите, я бы сделал то же самое, что и другой ответ, с точки зрения селекторов CSS и архивирования. Некоторые другие циклические конструкции ниже и использование Session для эффективности, учитывая количество запросов.


Вы можете сделать первоначальный запрос и извлечь количество страниц, а затем выполнить цикл для них. Используйте объект Session для эффективности повторного использования соединения.

import requests
from bs4 import BeautifulSoup as bs

def make_soup(s, page):
    page_url = "https://hansard.parliament.uk/search/Contributions?endDate=2019-07-11&page={}&searchTerm=%22climate+change%22&startDate=1800-01-01&partial=True"
    r = s.get(page_url.format(page))
    soup = bs(r.content, 'lxml')
    return soup

with requests.Session() as s:
    soup = make_soup(s, 1)
    pages = int(soup.select_one('.last a')['href'].split('page=')[1])
    for page in range(2, pages + 1):
        soup = make_soup(s, page)
        #do something with soup 

Вы можете зацикливаться, пока класс last не перестанет появляться

import requests
from bs4 import BeautifulSoup as bs

present = True
page = 1
#results = {}

def make_soup(s, page):
    page_url = "https://hansard.parliament.uk/search/Contributions?endDate=2019-07-11&page={}&searchTerm=%22climate+change%22&startDate=1800-01-01&partial=True"
    r = s.get(page_url.format(page))
    soup = bs(r.content, 'lxml')
    return soup

with requests.Session() as s:
    while present:
        soup = make_soup(s, page)
        present = len(soup.select('.last')) > 0
        #results[page] = soup.select_one('.pagination-total').text
        #extract info
        page+=1
1
QHarr 11 Июл 2019 в 19:49