如何解决使用 Requests-HTML 时如何减少抓取时间?
我目前使用 Requests-HTML 0.10.0 版和 Selenium 3.141.0。我的项目是抓取本网站 https://openreview.net/group?id=ICLR.cc/2021/Conference 上所有文章的评分。要打开网站的每个页面(网站有 53 个页面,每个页面有 50 篇文章),我使用 Selenium。接下来,为了在每个页面上打开文章,我使用 Requests-HTML。我的问题是如何减少打开每篇文章并获得评分所用的时间。在本例中,我使用 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('Keywords: ','')
abstract = abstract.strip().replace('\t',' ').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
异步获取每篇文章,但您正在等待它并使用标准的 for
循环。据我了解,这意味着您没有从 async 中获得任何优势;您仍在一次处理每一页(这说明您的处理时间很长)。
我建议使用 asyncio 将 for
循环转换为建议的 in this article 自身的并行版本。确保您设置了任务限制,这样您就不会尝试一次加载所有文章;这也将有助于您使用 RAM。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。