如何在使用请求HTML时减少抓取时间



我目前使用的是请求HTML版本0.10.0和Selenium 3.141.0。我的项目是搜集这个网站上所有文章的评分https://openreview.net/group?id=ICLR.cc/2021/Conference.为了打开网站的每个页面(网站有53个页面,每个页面有50篇文章(,我使用Selenium。接下来,为了打开每一页上的文章,我使用RequestsHTML。我的问题是如何减少打开每篇文章并获得评分的时间。在这种情况下,我使用await r_inside.html.arender(sleep = 5, timeout=100),这意味着睡眠时间为5秒,超时为100秒。当我试图将睡眠时间减少到0.5秒时,会导致错误,这是因为它没有足够的时间来抓取网站。然而,如果我将睡眠时间保持在5秒,那么将需要6到13个小时才能刮完所有2600篇文章。此外,在等待了13个小时后,我可以抓取所有2600篇文章,但代码使用88 GB的RAM,我不喜欢,因为我需要将此代码发送给其他没有足够RAM运行的人。我的目的是减少抓取时间和RAM内存。下面是我使用的代码。

import csv
link = 'https://openreview.net/group?id=ICLR.cc/2021/Conference'
from requests_html import HTMLSession, AsyncHTMLSession
import time
from tqdm import tqdm
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
id_list = []
keyword_list = []
abstract_list = []
title_list = []
driver = webdriver.Chrome('./requests_html/chromedriver.exe')
driver.get('https://openreview.net/group?id=ICLR.cc/2021/Conference')
cond = EC.presence_of_element_located((By.XPATH, '//*[@id="all-submissions"]/nav/ul/li[13]/a'))
WebDriverWait(driver, 10).until(cond)

for page in tqdm(range(1, 54)):
text = ''
elems = driver.find_elements_by_xpath('//*[@id="all-submissions"]/ul/li')
for i, elem in enumerate(elems):
try:
# parse title
title = elem.find_element_by_xpath('./h4/a[1]')
link = title.get_attribute('href')
paper_id = link.split('=')[-1]
title = title.text.strip().replace('t', ' ').replace('n', ' ')
# show details
elem.find_element_by_xpath('./a').click()
time.sleep(0.2)
# parse keywords & abstract
items = elem.find_elements_by_xpath('.//li')
keyword = ''.join([x.text for x in items if 'Keywords' in x.text])
abstract = ''.join([x.text for x in items if 'Abstract' in x.text])
keyword = keyword.strip().replace('t', ' ').replace('n', ' ').replace('Keywords: ', '')
abstract = abstract.strip().replace('t', ' ').replace('n', ' ').replace('Abstract: ', '')
text += paper_id+'t'+title+'t'+link+'t'+keyword+'t'+abstract+'n'
title_list.append(title)
id_list.append(paper_id)
keyword_list.append(keyword)
abstract_list.append(abstract)
except Exception as e:
print(f'page {page}, # {i}:', e)
continue

# next page
try:
driver.find_element_by_xpath('//*[@id="all-submissions"]/nav/ul/li[13]/a').click()
time.sleep(2) # NOTE: increase sleep time if needed
except:
print('no next page, exit.')
break
csv_file = open('./requests_html/bb_website_scrap.csv','w', encoding="utf-8")
csv_writer = csv.writer(csv_file)
csv_writer.writerow(['Title','Keyword','Abstract','Link','Total Number of Reviews','Average Rating','Average Confidence'])
n = 0
for item in range(len(id_list)):
title = title_list[item]
keyword = keyword_list[item]
abstract = abstract_list[item]
id = id_list[item]
link_pdf = f'https://openreview.net/forum?id={id}'
print(id)
asession_inside = AsyncHTMLSession()
r_inside = await asession_inside.get(link_pdf)
print(type(r_inside))
await r_inside.html.arender(sleep = 5, timeout=100)
test_rating = r_inside.html.find('div.comment-level-odd div.note_contents span.note_content_value')
print(len(test_rating))
check_list = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9','10'}
total_rating_confidence = []
total_rating = []
total_confidence = []
for t in range(len(test_rating)):
if any(test_rating[t].text.split(':')[0] in s for s in check_list):
total_rating_confidence.append(test_rating[t].text.split(':')[0])
for r in range(len(total_rating_confidence)):
if (r % 2 == 0):
total_rating.append(int(total_rating_confidence[r]))
else:
total_confidence.append(int(total_rating_confidence[r]))
average_rating = sum(total_rating) / len(total_rating)
average_confidence = sum(total_confidence) / len(total_confidence)
csv_writer.writerow([title, keyword, abstract, link_pdf,len(total_rating),average_rating,average_confidence])
n = n + 1
print('Order {}',n)
csv_file.close()

我不是Python专家(事实上,我是一个等级初学者(,但简单的答案是更好的并行性&会话管理。

有用的答案有点复杂。

你要离开Chromium会话,这很可能会占用你所有的RAM。如果调用asession_inside.close(),您可能会看到RAM使用率的提高。

据我所知,你做的每件事都是连续的;您获取每一页并提取有关连续文章的数据。然后,您还可以查询序列中的每一篇文章。

您正在使用arender异步获取每一篇文章,但您正在等待它&使用标准CCD_ 4循环。据我所知,这意味着您没有从async中获得任何优势;您仍然在一次处理一个页面(这解释了您处理时间长的原因(。

我建议使用asyncio将for循环转换为本文中建议的并行版本。确保你设置了一个任务限制,这样你就不会试图一次加载所有的文章;这也将有助于您的RAM使用。

最新更新