我正在尝试根据我正在参加的 Python 培训课程进行网络抓取。我已经安装了 BeautifulSoup,它似乎运行良好。该网站是https://pixelford.com/blog/,当我从 URL 中删除“/blog/”时,代码运行正常。但是当我添加“/blog/”时,我收到 400 错误,即使我知道该 URL 有效,因为我可以导航到该网站:
import requests
from bs4 import BeautifulSoup
url = "https://pixelford.com/blog/"
response = requests.get(url)
print(response)
html = response.content
soup = BeautifulSoup(html, 'html.parser')
a_tags = soup.find_all('a', class_="entry_title_link")
for a_tag in a_tags:
print(a_tag.get_text())
titles = list(map(lambda a_tag: a_tag.get_text(), a_tags))
print(titles)
我试图从 URL 中抓取博客标题列表并将它们放入列表中,但是 python 只返回一个空列表。
当你发出一个
requests.get
请求时,除了URL之外没有传递任何参数,它包括一些额外的基本信息,例如(取自Fiddler):
GET http://pixelford.com/blog/ HTTP/1.1
Host: pixelford.com
User-Agent: python-requests/2.28.0
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive
特别注意用户代理 (UA) 字符串,它清楚地表明 python 脚本使用
requests
发出请求。
服务器很可能被配置为阻止具有类似 UA 字符串的请求。我们可以通过在 Web 浏览器中使用自定义 UA 来进一步检查这一点,例如在 FireFox 中,您可以导航到
about:config
并指定一个:
钥匙 | 价值 |
---|---|
general.useragent.override | python-请求/2.28.0 |
这导致:
您可以通过在代码中指定自己的 UA 字符串来解决这个问题:
>>> requests.get("https://pixelford.com/blog/")
<Response [400]>
>>> requests.get("https://pixelford.com/blog/", headers={'User-Agent': 'Mozilla/5.0'})
<Response [200]>
在这里用自定义UA的最后一个请求,我们可以看到请求成功了。作为参考,原始请求现在包含:
GET http://pixelford.com/blog/ HTTP/1.1
Host: pixelford.com
User-Agent: Mozilla/5.0
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive
值得注意的是,站点依赖 UA 字符串是相当普遍的,例如试图衡量请求者可能具有哪些功能以及要提供哪些内容,Stack Overflow 就是这样做的,而且确实很有可能发送请求使用 Stack Overflow 根本不会排除的 UA 字符串,例如,一个空白的 UA: