#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 и посмотрю, что из этого выйдет.