Python请求并没有给我与浏览器相同的HTML

时间:2015-04-21 13:25:31

标签: python browser python-requests

我正在使用Python请求抓取Wikia页面。但是有一个问题:请求请求不会给我相同的HTML ,因为我的浏览器使用相同的页面。

为了进行比较,here's the page Firefox gets mehere's the page requests fetches(下载它们进行查看 - 抱歉,没有简单的方法可以直观地从其他网站托管一些HTML)。

您会注意到一些差异(super unfriendly diff)。有一些小东西,比如beinig以不同的顺序排序等等,但也有一些非常非常大的东西。最重要的是缺少最后六个<img>以及整个导航和页脚部分。即使在原始HTML中,它看起来像页面突然切断。

为什么会发生这种情况,有没有办法解决这个问题?我已经想到了很多东西,其中没有一个是富有成效的:

  • 请求标头干扰?不,我尝试将浏览器发送的标头User-Agent和所有,1:1复制到请求请求中,但没有任何改变。
  • 加载HTML后JavaScript加载内容?罗。即使已禁用JS,Firefox也能为我提供良好的解决方案。页。
  • 呃......好吧......还有什么呢?

如果您知道这种情况可能发生的方式以及解决问题的方法,那就太棒了。谢谢!

6 个答案:

答案 0 :(得分:5)

我遇到了类似的问题:

  • 与Python和浏览器相同的标题
  • JavaScript绝对排除了原因

要解决此问题,我最终更换了 urllib.request requests 库。

基本上,我更换了:

import requests

session = requests.Session()
r = session.get(URL)

使用:

import urllib.request

r = urllib.request.urlopen(URL)

然后它奏效了。

也许其中一个图书馆在幕后做了一些奇怪的事情?不确定这是否是你的选择。

答案 1 :(得分:2)

我建议您不要向您的请求发送正确的标头(或发送错误的标头)。这就是你获得不同内容的原因。以下是带标头的HTTP请求示例:

url = 'https://www.google.co.il/search?q=eminem+twitter'
user_agent = 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.101 Safari/537.36'

# header variable
headers = { 'User-Agent' : user_agent }

# creating request
req = urllib2.Request(url, None, headers)

# getting html
html = urllib2.urlopen(req).read()

如果您确定要发送正确的标题,但仍然会得到不同的HTML。您可以尝试使用selenium。它允许您直接使用浏览器(如果您的机器没有GUI,则使用phantomjs)。使用selenium,您只需直接从浏览器中获取HTML。

答案 2 :(得分:0)

我看到的很多差异告诉我内容仍然存在,它只是以不同的顺序呈现,有时间距不同。

您可能会根据多种不同的内容收到不同的内容:

  • 您的标题
  • 您的用户代理
  • 时间!
  • Web应用程序决定在页面上呈现元素的顺序,受随机属性顺序限制,因为元素可能会从未排序的数据源中提取。

如果你可以在Diff的顶部包含所有标题,那么我们可以更好地理解它。

我怀疑应用程序选择不渲染某些图像,因为它们没有针对它认为的某种机器人/移动设备(Python请求)进行优化

仔细观察差异,似乎两个请求中都加载了所有,只是格式不同。

答案 3 :(得分:0)

我在申请页面时遇到了类似的问题。然后我注意到我使用的URL需要'http'作为URL的前缀,但我在前面加上'https'。我的请求网址看起来像https://example.com。因此,请将网址设为http://example.com。希望它能解决问题。

答案 4 :(得分:0)

也许请求和浏览器使用不同的方式来呈现来自WEB服务器的原始数据,而上例中的diff仅适用于呈现的html。

我发现,当html损坏时,不同的浏览器(例如Chrome和Safari,在解析时使用不同的方法进行修复。因此,也许与Requests和Firefox是同一个想法。

在Requests和Firefox中,我建议对原始数据进行比较,即套接字中的字节流。请求可以使用响应对象的.raw属性来获取套接字中的原始数据。 (http://docs.python-requests.org/en/master/user/quickstart/)如果双方的原始数据相同并且HTML中存在一些损坏的代码,则可能是由于解析损坏的html时Request和浏览器的自动修复策略不同所致。

答案 5 :(得分:0)

(也许我最近的经验会有所帮助)

我在Amazon上遇到了刮刮的相同问题:我的本地计算机能够处理所有页面,但是当我在Google Cloud实例上移动项目时,对于某些我刮刮的物品的行为发生了改变。

先前的实现

在我的本地计算机上,我正在使用请求库,如下所示:

page = requests.get(url_page, headers=self.headers)
page=page.content

根据我的本地浏览器在班级中指定的标头

headers = {
    "User-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36 OPR/67.0.3575.137"}

但是在Google Cloud实例上使用此设置后,页面显示不完整

新实施

以下实现涉及没有标题的 urllib

req = urllib.request.Request(
                    url_page,
                    data=None
                )
f = urllib.request.urlopen(req)
page = f.read().decode('utf-8')
self.page = page

此解决方案可在两台计算机上使用;在进行此尝试之前,我还尝试使用相同的标头,但问题并未解决,因此我假定存在问题(可能是因为我不正确地标识为另一个客户端)而删除了标头。

因此,我的代码可以正常工作,并且我仍然可以使用 beautifulsoup 处理页面的内容,就像在我的类中实现的以下方法一样,目的是从中提取文本页面的特定部分。

 def find_data(self, div_id):
    soup = BeautifulSoup(self.page, features = "lxml")
    text = soup.select("#"+div_id)[0].get_text()

    text = text.strip()
    text = str(text)
    text = text.replace('"', "")
    return text