Как улучшить и ограничить результаты BeautifulSoup

#python #web-scraping #beautifulsoup

Вопрос:

Так что я застрял здесь. Я врач, поэтому мои знания и навыки программирования близки к нулю, и, скорее всего, в этом проблема. Я пытаюсь изучить некоторые основы Python, и для меня лучший способ — это делать что-то.

В рамках проекта:

  • соскоблите изображения с обложек нескольких книг

Некоторые из используемых ссылок:

 http://coleccaoargonauta.blogspot.com/2011/09/1-perdidos-na-estratosfera.html
http://coleccaoargonauta.blogspot.com/2011/09/n-2-o-estranho-mundo-de-kilsona.html
http://coleccaoargonauta.blogspot.com/2011/09/n-3-ultima-cidade-da-terra.html
http://coleccaoargonauta.blogspot.com/2011/09/n-4-nave-sideral.html
http://coleccaoargonauta.blogspot.com/2011/09/n-5-o-universo-vivo.html
 

Эта структура сайта испорчена.
Ссылки расположены внутри div с классом:»запись после заголовка-заголовок«, который, в свою очередь, имеет два или более div класса «разделитель«, которые могут содержать содержимое или быть пустыми.
Что я могу сказать до сих пор, так это то, что в 95% случаев мне нужны последние две ссылки в первых двух DIV класса «разделитель«. И для этого этапа этого достаточно.

Мой код пока таков::

 #intro
r=requests.get(url)
soup = BeautifulSoup(r.content, 'lxml')

#select the first teo 'separator' divs
separador = soup.select("div.separator")[:2]

#we need a title for each page - for debugging and later used to rename images      
titulo = soup.find_all("h3", {"class": "post-title entry-title"})[0]
m = titulo.string
print (m)

#the find all links loop
for div in separador:
  imagens = div.find_all('a')
  for link in imagens:
    print (link['href'], 'n')
 

Что я могу сделать прямо сейчас:

  • Я могу распечатать правильный URL-адрес, а затем использовать wget для загрузки и переименования файлов. Однако мне нужны только две последние ссылки из результатов, и это единственное, чего не хватает в моем google-fu. Я думаю, что проблема в том, как BeautifulSoup экспортирует результаты (набор результатов), и в моем недостатке знаний в таких вещах, как списки. Если первый «разделитель» содержит одну ссылку, а вторые две ссылки, я получаю список из двух элементов (а второй элемент-две ссылки), следовательно, он не может быть разрезан.

Пример вывода

 2-O Estranho Mundo de Kilsona.jpg
http://3.bp.blogspot.com/-tAyl2wdRT1g/UPfbGczmv2I/AAAAAAAAB0M/mP71TRQIg3c/s1600/2 - O Estranho Mundo de Kilsona.jpg 

http://4.bp.blogspot.com/-D0cUIP8PkEU/UPfbByjSuII/AAAAAAAAB0E/LP6kbIEJ_eI/s1600/Argonauta002.jpg 

http://3.bp.blogspot.com/-tAyl2wdRT1g/UPfbGczmv2I/AAAAAAAAB0M/mP71TRQIg3c/s1600/2 - O Estranho Mundo de Kilsona.jpg 
 

Но я хотел, чтобы это было

 2-O Estranho Mundo de Kilsona.jpg

http://4.bp.blogspot.com/-D0cUIP8PkEU/UPfbByjSuII/AAAAAAAAB0E/LP6kbIEJ_eI/s1600/Argonauta002.jpg 

http://3.bp.blogspot.com/-tAyl2wdRT1g/UPfbGczmv2I/AAAAAAAAB0M/mP71TRQIg3c/s1600/2 - O Estranho Mundo de Kilsona.jpg 
 

Кто-нибудь может пролить свет на это?

Комментарии:

1. Поскольку imagens это всего лишь список python, вы можете использовать нарезку imagens[-2:] , чтобы выбрать последние две записи.

Ответ №1:

Проблема связана с тем, что строка imagens = div.find_all('a') вызывается в цикле. Это создает list lists проблему . Поэтому нам нужно найти способ объединить их в единый список. Я делаю это ниже с помощью строки merged_list = [] [merged_list.extend(list) for list in imagens] .

Отсюда я затем создаю новый список только со ссылками, а затем дедуплицирую список, вызывая using set (a set -полезная структура данных, которую можно использовать, когда вам не нужны дублированные данные). Затем я превращаю его обратно в а list , и он возвращается к вашему коду.

 import requests
from bs4 import BeautifulSoup

link1 = "http://coleccaoargonauta.blogspot.com/2011/09/1-perdidos-na-estratosfera.html"
link2 = "http://coleccaoargonauta.blogspot.com/2011/09/n-2-o-estranho-mundo-de-kilsona.html"
link3 = "http://coleccaoargonauta.blogspot.com/2011/09/n-3-ultima-cidade-da-terra.html"
link4 = "http://coleccaoargonauta.blogspot.com/2011/09/n-4-nave-sideral.html"
link5 = "http://coleccaoargonauta.blogspot.com/2011/09/n-5-o-universo-vivo.html"


#intro
r=requests.get(link2)
soup = BeautifulSoup(r.content, 'lxml')

#select the first teo 'separator' divs
separador = soup.select("div.separator")[:2]

#we need a title for each page - for debugging and later used to rename images      
titulo = soup.find_all("h3", {"class": "post-title entry-title"})[0]
m = titulo.string
print (m)

imagens = [div.find_all('a') for div in separador]
merged_list = []
[merged_list.extend(list) for list in imagens]
link_list = [link['href'] for link in merged_list]
deduped_list = list(set(link_list))
for link in deduped_list:
    print(link, 'n')
 

Комментарии:

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

Ответ №2:

Вы можете использовать селекторы CSS для извлечения изображения непосредственно из div с помощью разделителя классов (ссылка на документы).

Я также использую понимание списка вместо цикла for.

Ниже приведен пример работы для URL-адреса из вашего списка.

 
import requests
from bs4 import BeautifulSoup

#intro
url = "http://coleccaoargonauta.blogspot.com/2011/09/1-perdidos-na-estratosfera.html"
r=requests.get(url)
soup = BeautifulSoup(r.content, 'lxml')


#we need a title for each page - for debugging and later used to rename images      
titulo = soup.find_all("h3", {"class": "post-title entry-title"})[0]
m = titulo.string
print (m)

#find all links
links = [link['href'] for link in soup.select('.separator a')]
print(links)
 

Комментарии:

1. Закройте, но ваш код дает мне src изображений, а не (по крайней мере, всегда) связанную ссылку.

2. @NunoRodrigues извини за это! хотя вы хотели получить ссылки на img, изменили код в моем ответе)

3. Это более или менее то, чего я хочу. Я объединю ваше решение с трюком с выравниванием от SkinnyPigeon и посмотрю, что из этого выйдет.