首页 > 解决方案 > 无法使用 beautifulsoup 抓取日本网站

问题描述

我试图通过在线尝试一些简单的教程来抓取一个日本网站,但我无法从该网站获取信息。下面是我的代码:

import requests
wiki = "https://www.athome.co.jp/chintai/1001303243/?DOWN=2&BKLISTID=002LPC&sref=list_simple&bi=tatemono"
page = requests.get(wiki)
from bs4 import BeautifulSoup
soup = BeautifulSoup(page.text, 'lxml')
for i in soup.findAll('data payments'):
    print(i.text)

我想得到的是来自以下部分:

                <dl class="data payments">
                    <dt>賃料:&lt;/dt>
                    <dd><span class="num">7.3万円</span></dd>
                </dl>

我想打印我们的数据支付“租料”,价格为“7.3万円”。

预期(在字符串中):

“付款:租料7.3万円”

编辑:

import requests
wiki = "https://www.athome.co.jp/"
headers = requests.utils.default_headers()
headers.update({
    'User-Agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0',
})
page = requests.get(wiki,headers=headers)
from bs4 import BeautifulSoup
soup = BeautifulSoup(page.content, 'lxml')
print(soup.decode('utf-8', 'replace'))

标签: pythonhtmlbeautifulsouppython-requests

解决方案


在您最新版本的代码中,您对汤进行解码,您将无法使用BeautifulSoup 中的find和之类的函数。find_all但我们稍后会谈到它。

首先

拿到汤后,可以打印汤,会看到:(只显示关键部分)

<meta content="NOINDEX, NOFOLLOW" name="ROBOTS"/>
<meta content="0" http-equiv="expires"/>
<meta content="Tue, 01 Jan 1980 1:00:00 GMT" http-equiv="expires"/>
<meta content="10; url=/distil_r_captcha.html?requestId=2ac19293-8282-4602-8bf5-126d194a4827&amp;httpReferrer=%2Fchintai%2F1001303243%2F%3FDOWN%3D2%26BKLISTID%3D002LPC%26sref%3Dlist_simple%26bi%3Dtatemono" http-equiv="refresh"/>

这意味着您没有获得足够的元素,并且您被检测为爬虫。

find因此,@KunduK 的答案中缺少一些东西,与该功能无关。

主要部分

首先,你需要让你的 python 脚本不像爬虫。

标题

标头最常用于检测爬虫。在原始请求中,当您从请求中获取会话时,您可以使用以下命令检查标头:

>>> s = requests.session()
>>> print(s.headers)
{'User-Agent': 'python-requests/2.22.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive'}

可以看到这里的headers会告诉服务器你是爬虫程序,也就是python-requests/2.22.0.

因此,您需要修改User-Agent更新标头。

s = requests.session()
headers = {
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36',
}
s.headers.update(headers)

但是,在测试爬虫时,仍然被检测为爬虫。因此,我们需要在标题部分进一步挖掘。(但也可能是其他原因,例如 IP 拦截器或 Cookie 原因。我稍后会提到。)

在 Chrome 中,我们打开开发者工具,然后打开网站。(假装是第一次访问,最好先清除cookies。)清除cookies后,刷新页面。我们可以在开发者工具的网卡中看到,它显示了来自 Chrome 的大量请求。 Chrome 中的开发者工具

通过输入第一个属性,即https://www.athome.co.jp/,我们可以在右侧看到一个详细的表格,其中 Request Headers 是 Chrome 生成的用于请求目标站点服务器的 headers。 网卡详细页面

为了确保一切正常,您只需将此 Chrome 标头中的所有内容添加到您的爬虫中,它就无法再发现您是真正的 Chrome 或爬虫。(对于大多数网站,但我也发现一些网站使用 starnge 设置,要求在每个请求中都有一个特殊的标头。)

我已经挖出来了,添加后accept-language,网站的防爬虫功能会让你通过。

因此,您需要像这样更新标题。

headers = {
    'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8,zh-TW;q=0.7',
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36',
}
s.headers.update(headers)

曲奇饼

cookie的解释可以参考wiki。要获取cookie,有一个简单的方法。首先,初始化一个会话并更新标题,就像我上面提到的那样。二、请求获取页面https://www.athome.co.jp,一旦获取到页面,就会得到服务器下发的cookie。

s.get(url='https://www.athome.co.jp')

requests.session 的优点是会话将帮助您维护 cookie,因此您的下一个请求将自动使用此 cookie。

您可以使用以下方法检查您获得的 cookie:

print(s.cookies)

我的结果是:

<RequestsCookieJar[Cookie(version=0, name='athome_lab', value='ffba98ff.592d4d027d28b', port=None, port_specified=False, domain='www.athome.co.jp', domain_specified=False, domain_initial_dot=False, path='/', path_specified=True, secure=False, expires=1884177606, discard=False, comment=None, comment_url=None, rest={}, rfc2109=False)]>

您不需要解析此页面,因为您只需要 cookie 而不是内容。

获取内容

您可以只使用您获得的会话来请求您提到的wiki 页面。

wiki = "https://www.athome.co.jp/chintai/1001303243/?DOWN=2&BKLISTID=002LPC&sref=list_simple&bi=tatemono"
page = s.get(wiki)

现在,您想要的所有内容都将由服务器发布给您,您只需使用 BeautifulSoup 解析它们即可。

from bs4 import BeautifulSoup
soup = BeautifulSoup(page.content, 'html.parser')

得到你想要的内容后,就可以使用 BeautifulSoup 来获取目标元素了。

soup.find('dl', attrs={'class': 'data payments'})

你会得到的是:

<dl class="data payments">
<dt>賃料:&lt;/dt>
<dd><span class="num">7.3万円</span></dd>
</dl>

你可以从中提取你想要的信息。

target_content = soup.find('dl', attrs={'class': 'data payments'})
dt = target_content.find('dt').get_text()
dd = target_content.find('dd').get_text()

将其格式化为一行。

print('payment: {dt} is {dd}'.format(dt=dt[:-1], dd=dd))

一切都已完成。

概括

我将粘贴下面的代码。

# Import packages you want.
import requests
from bs4 import BeautifulSoup

# Initiate a session and update the headers.
s = requests.session()
headers = {
    'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8,zh-TW;q=0.7',
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36',
}
s.headers.update(headers)

# Get the homepage of the website and get cookies.
s.get(url='https://www.athome.co.jp')
"""
# You might need to use the following part to check if you have successfully obtained the cookies. 
# If not, you might be blocked by the anti-cralwer.
print(s.cookies)
"""
# Get the content from the page.
wiki = "https://www.athome.co.jp/chintai/1001303243/?DOWN=2&BKLISTID=002LPC&sref=list_simple&bi=tatemono"
page = s.get(wiki)

# Parse the webpage for getting the elements.
soup = BeautifulSoup(page.content, 'html.parser')
target_content = soup.find('dl', attrs={'class': 'data payments'})
dt = target_content.find('dt').get_text()
dd = target_content.find('dd').get_text()

# Print the result.
print('payment: {dt} is {dd}'.format(dt=dt[:-1], dd=dd))

在爬虫领域,还有很长的路要走。

你最好上网,并充分利用浏览器中的开发者工具

您可能需要确定内容是否由 JavaScript 加载,或者内容是否在 iframe 中。

此外,您可能会被检测为爬虫并被服务器阻止。反反爬虫技术只能通过更频繁的编码来获得。

我建议你从一个没有反爬虫功能的更简单的网站开始。


推荐阅读