我想在网页https://www.quora.com/topic/Stack-Overflow-4/all_questions下抓取例如前200个问题的标题。我尝试了以下代码:
import requests
from bs4 import BeautifulSoup
url = "https://www.quora.com/topic/Stack-Overflow-4/all_questions"
print("url")
print(url)
r = requests.get(url) # HTTP request
print("r")
print(r)
html_doc = r.text # Extracts the html
print("html_doc")
print(html_doc)
soup = BeautifulSoup(html_doc, 'lxml') # Create a BeautifulSoup object
print("soup")
print(soup)
它给了我一个文本https://pastebin.com/9dSPzAyX。如果我们搜索href='/
,我们可以看到html确实包含一些问题的标题。但是,问题在于数量不够。实际上在网页上,用户需要手动向下滚动以触发额外的负载。
有人知道我如何模仿程序“向下滚动”以加载页面的更多内容吗?
答案 0 :(得分:0)
网页上的无限滚动基于Javascript功能。因此,要找出我们需要访问的URL和使用什么参数,我们需要彻底研究页面内部的JS代码,或者最好检查一下您向下滚动页面时浏览器的请求。我们可以使用开发人员工具研究请求。 See example for quora
向下滚动越多,生成的请求越多。因此,现在您的请求将针对该URL而不是普通URL进行,但请记住发送正确的标题和播放负载。
其他更简单的解决方案是使用硒
答案 1 :(得分:0)
我建议使用selenium而不是bs。
selenium可以控制浏览器和解析。例如向下滚动,单击按钮等……
此示例用于向下滚动以获取instagram中的所有喜欢的用户。
https://stackoverflow.com/a/54882356/5611675
答案 2 :(得分:0)
如果仅在“向下滚动”时加载内容,则可能意味着该页面正在使用Javascript动态加载内容。
您可以尝试使用诸如PhantomJS之类的Web客户端来加载页面并在其中执行javascript,并通过注入诸如document.body.scrollTop = sY;
(Simulate scroll event using Javascript)之类的JS来模拟滚动。
答案 3 :(得分:0)
找不到使用请求的响应。但是您可以使用Selenium。首先在第一次加载时打印出问题的数量,然后发送End键以模拟向下滚动。发送结束键后,您会看到问题数量从20个增加到40个。
我使用driver。隐式等待5秒钟再重新加载DOM,以防脚本在加载DOM之前快速加载。您可以通过将EC与硒一起使用来改善。
此页面每卷加载20个问题。因此,如果您想抓取100个问题,则需要发送5次“结束”键。
要使用下面的代码,您需要安装chromedriver。 http://chromedriver.chromium.org/downloads
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
CHROMEDRIVER_PATH = ""
CHROME_PATH = ""
WINDOW_SIZE = "1920,1080"
chrome_options = Options()
# chrome_options.add_argument("--headless")
chrome_options.add_argument("--window-size=%s" % WINDOW_SIZE)
chrome_options.binary_location = CHROME_PATH
prefs = {'profile.managed_default_content_settings.images':2}
chrome_options.add_experimental_option("prefs", prefs)
url = "https://www.quora.com/topic/Stack-Overflow-4/all_questions"
def scrape(url, times):
if not url.startswith('http'):
raise Exception('URLs need to start with "http"')
driver = webdriver.Chrome(
executable_path=CHROMEDRIVER_PATH,
chrome_options=chrome_options
)
driver.get(url)
counter = 1
while counter <= times:
q_list = driver.find_element_by_class_name('TopicAllQuestionsList')
questions = [x for x in q_list.find_elements_by_xpath('//div[@class="pagedlist_item"]')]
q_len = len(questions)
print(q_len)
html = driver.find_element_by_tag_name('html')
html.send_keys(Keys.END)
wait = WebDriverWait(driver, 5)
time.sleep(5)
questions2 = [x for x in q_list.find_elements_by_xpath('//div[@class="pagedlist_item"]')]
print(len(questions2))
counter += 1
driver.close()
if __name__ == '__main__':
scrape(url, 5)