【问题标题】:Python: how to fill out a web form and get the resulting page sourcePython:如何填写网络表单并获取生成的页面源
【发布时间】:2020-03-01 23:02:33
【问题描述】:

我正在尝试编写一个python 脚本,它将抓取http://www.fakenewsai.com/ 并告诉我一篇新闻文章是否是假新闻。我希望脚本将给定的新闻文章输入网站的url 输入字段并点击submit 按钮。然后,我想对网站进行抓取,以确定该文章是“假”新闻还是“真实”新闻,与网站上显示的一样。

我使用seleniumChromeDriver 成功地完成了这项工作,但是脚本非常慢(> 2 分钟)并且没有在Heroku 上运行(使用flask)。作为参考,这是我使用的代码:

from selenium import webdriver
import time

def fakeNews(url):
  if url.__contains__("https://"):
    url = url[8:-1]
  if url.__contains__("http://"):
    url = url[7:-1]
  browser = webdriver.Chrome("static/chromedriver.exe")
  browser.get("http://www.fakenewsai.com")
  element = browser.find_element_by_id("url")
  element.send_keys(url)
  button = browser.find_element_by_id("submit")
  button.click()
  time.sleep(1)
  site = "" + browser.page_source
  result = ""
  if(site[site.index("opacity: 1")-10] == "e"):
    result = "Fake News"
  else:
    result = "Real News"
  browser.quit()
  return result

print(fakeNews('https://www.nytimes.com/2019/11/02/opinion/sunday/instagram-social-media.html'))

我尝试使用其他python 库来复制此代码,例如mechanicalsouppyppeteerscrapy。但是,作为python 的初学者,我并没有取得多大的成功。我希望有人可以通过解决方案为我指明正确的方向。

【问题讨论】:

  • 您能澄清一下您在这里遇到的问题吗?据我了解-您的脚本运行正常,但是在部署到 Heroku 期间遇到了问题?我在我的计算机上运行了您的代码示例,它在 7 秒内运行,所以我不确定这需要 2 多分钟。代码在哪里似乎“暂停”时间最长?
  • 在本地,脚本大约需要 30 秒才能运行我网站上的一个标题(使用 flask 创建)。但是,当脚本针对一页上的 20 个标题集合运行时,需要 2-5 分钟。
  • 在 Heroku 上,我收到以下错误:The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application.
  • 那么你的脚本长度在这里是有意义的。每个标题 30 秒乘以 20 个标题总共是 10 分钟,所以 2-5 分钟是抢断。如果你想提高性能,你可以重写你的脚本,不要每次都启动一个新的 Chromedriver 实例。相反,您可以只初始化一个 Chromedriver,然后针对单个实例运行您的标题脚本。似乎下面的其他一些用户对您有一些想法。

标签: python python-3.x selenium web-scraping automation


【解决方案1】:

出于所述目的,在我看来,分析网站、了解其功能然后自动化浏览器行为而不是用户行为会更简单。

在网站上尝试在浏览器上按 F12,打开“网络”选项卡,在输入框中粘贴 URL,然后单击“提交”,您会看到它发送 HTTP OPTIONS 请求,然后向 URL 发送 POST 请求.然后服务器返回一个 JSON 响应作为结果。

因此,您可以使用 Python 的请求模块 (docs) 自动执行 POST 请求,而不是使用非常复杂的代码来模拟点击和抓取结果。

您可以在此基础上构建一个非常简单的示例:

import json
import requests


def fake_news():
    url = 'https://us-central1-fake-news-ai.cloudfunctions.net/detect/'
    payload = {'url': 'https://www.nytimes.com/'}
    headers = {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate, br', 'Accept-Language': 'en-US,en;q=0.5',
               'Connection': 'keep-alive', 'Content-Length': '103', 'Content-type': 'application/json; charset=utf-8',
               'DNT': '1', 'Host': 'us-central1-fake-news-ai.cloudfunctions.net', 'Origin': 'http://www.fakenewsai.com',
               'Referer': 'http://www.fakenewsai.com/', 'TE': 'Trailers',
               'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:70.0) Gecko/20100101 Firefox/70.0'}

    response_json = requests.post(url, data=json.dumps(payload), headers=headers).text
    response = json.loads(response_json)
    is_fake = int(response['fake'])

    if is_fake == 0:
        print("Not fake")
    elif is_fake == 1:
        print("Fake")
    else:
        print("Invalid response from server")


if __name__ == "__main__":
    fake_news()

PS:与网站所有者联系以讨论将他或她的基础架构用于您的项目是公平的。

【讨论】:

  • 对 requests 库的好建议。听起来 Selenium 对于用户的需求来说太慢了。
  • 非常感谢。这正是我想要的。
【解决方案2】:

主要的减速发生在启动 chrome 浏览器并找到第一个 URL 时。 请注意,您正在为每个请求启动一个浏览器。 您可以在初始化步骤中启动浏览器,并且只执行每个请求的自动化部分。 这将大大提高性能。

【讨论】:

  • 感谢您的回复;我会试一试,让你知道它是否有效。此外,由于此脚本将在网站上运行,我想知道是否有一种方法可以在不打开用户计算机上的 Chrome 窗口的情况下运行它(使用 selenium 或其他方法)。
  • Chrome 驱动支持一个选项 --headless,它不会打开浏览器。但是在后台,浏览器进程被创建,并且需要类似的时间。
  • 感谢您的帮助。我可以使用另一种更快的方法(除了selenium)吗?这种方法确实提高了一点速度,但每篇文章仍然需要大约 3-5 秒。我有一个新闻提要页面,它运行加载前 20 个 Google 新闻头条的脚本,因此运行需要 1 多分钟,使该功能几乎无法使用。
  • 1 分钟的 Selenium 脚本非常快。 UI 自动化通常是一个缓慢而笨重的过程,我通常使用单次执行需要 10-15 分钟的测试用例。这只是渲染浏览器和模拟真实用户操作的本质——这需要时间,就像需要真实用户时间一样。如果您想要更快的解决方案,请不要使用 UI 测试。 Python 中的Requests 库在这里可能会更好。
  • 哦,好的。我仍然是 python 的初学者,所以我不知道如何进行这个项目。 @favic 的解决方案对我来说效果更好。感谢您的帮助。
猜你喜欢
  • 2012-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-09
  • 2016-09-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多