#python #web-scraping #beautifulsoup
#python #Очистка веб-страниц #beautifulsoup
Вопрос:
Я очищаю и загружаю ссылки с веб-сайта, и веб-сайт обновляется новыми ссылками каждый день. Мне бы хотелось, чтобы при каждом запуске моего кода он только очищал / загружал обновленные ссылки с момента последнего запуска программы, а не повторял весь код заново.
Я попытался добавить ранее очищенные ссылки в пустой список и выполнить остальную часть кода (который загружает и переименовывает файл), только если очищенная ссылка не найдена в списке. Но, похоже, это работает не так, как хотелось бы, потому что каждый раз, когда я запускаю код, он запускается «с 0» и перезаписывает ранее загруженные файлы.
Есть ли другой подход, который я должен попробовать?
Вот мой код (также открыт для общих предложений о том, как это очистить и улучшить)
import praw
import requests
from bs4 import BeautifulSoup
import urllib.request
from difflib import get_close_matches
import os
period = '2018 Q4'
url = 'https://old.reddit.com/r/test/comments/b71ug1/testpostr23432432/'
headers = {'User-Agent': 'Mozilla/5.0'}
page = requests.get(url, headers=headers)
#set soup
soup = BeautifulSoup(page.text, 'html.parser')
table = soup.find_all('table')[0]
#create list of desired file names from existing directory names
candidates = os.listdir('/Users/test/Desktop/Test')
#set directory to download scraped files to
downloads_folder = '/Users/test/Desktop/Python/project/downloaded_files/'
#create empty list of names
scraped_name_list = []
#scrape site for names and links
for anchor in table.findAll('a'):
try:
if not anchor:
continue
name = anchor.text
letter_link = anchor['href']
#if name doesn't exist in list of names: append it to the list, download it, and rename it
if name not in scraped_name_list:
#append it to name list
scraped_name_list.append(name)
#download it
urllib.request.urlretrieve(letter_link, '/Users/test/Desktop/Python/project/downloaded_files/' period " " name '.pdf')
#rename it
best_options = get_close_matches(name, candidates, n=1, cutoff=.33)
try:
if best_options:
name = (downloads_folder period " " name ".pdf")
os.rename(name, downloads_folder period " " best_options[0] ".pdf")
except:
pass
except:
pass
#else skip it
else:
pass
Ответ №1:
каждый раз, когда вы запускаете это, оно воссоздается scraped_name_list
как новый пустой список. что вам нужно сделать, это сохранить список в конце выполнения, а затем попытаться импортировать его при любом другом запуске. pickle
библиотека отлично подходит для этого.
вместо определения scraped_name_list = []
попробуйте что-то вроде этого
try:
with open('/path/to/your/stuff/scraped_name_list.lst', 'rb') as f:
scraped_name_list = pickle.load(f)
except IOError:
scraped_name_list = []
при этом будет предпринята попытка открыть ваш список, но если это первый запуск (то есть список еще не существует), он начнется с пустого списка. затем в конце вашего кода вам просто нужно сохранить файл, чтобы его можно было использовать при любом другом запуске:
with open('/path/to/your/stuff/scraped_name_list.lst', 'wb') as f:
pickle.dump(scraped_name_list, f)
Комментарии:
1. Понятно, я поиграю с этим. Является ли это рекомендуемым способом достижения того, к чему я стремлюсь, или есть более простой способ, который, возможно, не предполагает создания списка?
2. @MSD вам нужно будет запомнить, какой контент вы уже очистили тем или иным способом, так что обойти это не так уж и сложно. приведенный выше метод является самым простым, но есть также такие опции, как сохранение в базе данных. несмотря ни на что, вам придется удалить эти данные обратно.
3. спасибо, и это имеет смысл. Извините, если это глупый вопрос, но при первом запуске он, похоже, работает так, как ожидалось, с
scraped_name_list.lst'
созданием. Но при последующем запуске я получаюUnicodeDecodeError: 'utf-8' codec can't decode byte 0x80 in position 0: invalid start byte
. Полный путьwith open('/Users/test/Desktop/scraped_name_list.lst', 'wb') as f: pickle.dump(scraped_name_list, f)
. Нужно ли мне использовать другое расширение / тип файла? Если это имеет значение, я на macOS 10.14.5.4. На самом деле, я думаю, что я понял это. Изменение
'r'
на'rb'
, похоже, делает свое дело.5. @MSD упс. да, я пропустил
b
. сейчас редактирую свой ответ.