【发布时间】:2019-05-30 10:34:14
【问题描述】:
问题:
不知道 google fu 是否再次让我失望,但我无法从 url 列表中下载 csvs。我使用requests 和bs4 来收集网址(最终列表是正确的) - 请参阅下面的流程以获取更多信息。
然后我按照此处给出的答案之一使用urllib 下载:Trying to download data from URL with CSV File,以及其他一些用于下载 csvs 的 stackoverflow python 答案。
目前我被困在一个
HTTP 错误 404:未找到
(下面的堆栈跟踪来自上次尝试传递 User-Agent)
----> 9 f = urllib.request.urlopen(req)
10 print(f.read().decode('utf-8'))
#other lines
--> 650 raise HTTPError(req.full_url, code, msg, hdrs, fp)
651
652 class HTTPRedirectHandler(BaseHandler):
HTTPError: HTTP Error 404: Not Found
我在这里尝试了添加 User-Agent: Web Scraping using Python giving HTTP Error 404: Not Found 的解决方案,尽管我预计会出现 403 而不是 404 错误代码 - 但似乎适用于许多 OP。
这仍然失败并出现同样的错误。我很确定我可以通过简单地使用 selenium 并将 csv url 传递给 .get 来解决这个问题,但我想知道我是否可以单独使用请求来解决这个问题。
大纲:
我访问了这个页面:
我获取所有每月版本的链接,例如Patients Registered at a GP Practice May 2019,然后我访问每个页面并获取其中的所有 csv 链接。
我循环尝试下载文件的 filename:download_url 对的最终字典。
问题:
谁能看到我做错了什么或者如何解决这个问题,这样我就可以在不求助于 selenium 的情况下下载文件?我也不确定实现这一点的最有效方法 - 也许实际上根本不需要 urllib,只需要请求就足够了吗?
Python:
没有用户代理:
import requests
from bs4 import BeautifulSoup as bs
import urllib
base = 'https://digital.nhs.uk/'
all_files = []
with requests.Session() as s:
r = s.get('https://digital.nhs.uk/data-and-information/publications/statistical/patients-registered-at-a-gp-practice')
soup = bs(r.content, 'lxml')
links = [base + item['href'] for item in soup.select('.cta__button')]
for link in links:
r = s.get(link)
soup = bs(r.content, 'lxml')
file_links = {item.text.strip().split('\n')[0]:base + item['href'] for item in soup.select('[href$=".csv"]')}
if file_links:
all_files.append(file_links) #ignore empty dicts as for some months there is no data yet
else:
print('no data : ' + link)
all_files = {k: v for d in all_files for k, v in d.items()} #flatten list of dicts to single dict
path = r'C:\Users\User\Desktop'
for k,v in all_files.items():
#print(k,v)
print(v)
response = urllib.request.urlopen(v)
html = response.read()
with open(path + '\\' + k + '.csv', 'wb') as f:
f.write(html)
break #as only need one test case
添加用户代理进行测试:
req = urllib.request.Request(
v,
data=None,
headers={
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.47 Safari/537.36'
}
)
f = urllib.request.urlopen(req)
print(f.read().decode('utf-8'))
【问题讨论】:
-
使用 Fiddler 之类的工具来检查您发出的请求是否 (a) 正确(您是否以某种方式修改了文件名?)并且 (b) 与您对同一文件发出的请求相匹配通过浏览器。我不认为
User-Agent标头在这种情况下是相关的。我选择了files.digital.nhs.uk/0D/65E837/…(“在 GP 诊所注册的患者 - 2019 年 5 月:单岁(GP 诊所 - 男性)”),并且能够通过 Fiddlers Replay 下载除Host之外的每个标题> 补发和编辑 -
@Rob 谢谢。我也不认为用户代理是给定错误代码的相关部分,但想展示我的努力。我会看看开发工具是否捕获了我可以使用的任何东西。我通过将文件名粘贴到浏览器中进行了检查,并且下载正常。
-
但没有检查连接! @Rob
标签: python-3.x csv web-scraping python-requests