一、说明
本周我不得不为客户抓取一个网站。我意识到我做得如此自然和迅速,分享它会很有用,这样你也可以掌握这门艺术。【免责声明:本文展示了我的抓取做法,如果您有更多相关做法请在评论中分享】
二、计划策略
2.1 策划
- 确定您的目标:一个简单的 html 网站
- 在 Python 中设计抓取方案
- 跑起代码,让魔术运转
您需要多少时间来抓取网站?从业者需要~10分钟为一个简单的html网站准备Python脚本。
2.2 第一部分:找到你的目标(一个网站)
就我而言,我需要从 SWIFT 代码(或法国 BIC 代码)中收集银行名称。该网站 http://bank-code.net/country/FRANCE-%28FR%29.html 有一个4000+ SWIFT代码的列表以及相关的银行名称。问题是它们每页仅显示 15 个结果。浏览所有页面并一次复制粘贴 15 个结果不是一种选择。刮擦在这项任务中派上了用场。
首先,使用Chrome“检查”选项来确定您需要获取的html部分。将鼠标移动到检查窗口中的不同项目上(右侧),然后跟踪代码突出显示的网站部分(左侧)。选择项目后,在检查窗口中,使用“复制/复制元素”并将 html 代码粘贴到 python 编码工具中。
右侧是谷歌浏览器的“检查窗口”,您在使用右键单击/检查时获得
就我而言,具有 15 个 SWIFT 代码的所需项目是一个“表”
<table class="table table-hover table-bordered" id="tableID" style="margin-bottom: 10px;">
</table>
2.3 第二部分:在 Python 中设计抓取方案
a)scrape第一页
import requests
url = "http://bank-code.net/country/FRANCE-%28FR%29/"
page = requests.get(url)
就是这样,3行代码和Python已经收到了网页。现在,您需要正确解析html并检索所需的项目。
记住所需的 html :
<table class="table table-hover table-bordered" id="tableID" style="margin-bottom: 10px;">
</table>
它是一个“table”元素,id为“tableID”。它有一个id属性的事实很好,因为这个网页上没有其他html元素可以有这个id。这意味着如果我在 html 中查找此 id,除了所需的元素之外,我找不到任何其他内容。它节省了时间。
让我们在 Python 中正确地做到这一点
import bs4
soup = bs4.BeautifulSoup(page.content, 'lxml')
table = soup.find(name='table', attrs={'id':'tableID'})
所以现在我们得到了所需的 html 元素。但是我们仍然需要获取 html 中的 SWIFT 代码,然后将其存储在 Python 中。我选择把它存放在熊猫里。数据帧对象,但只有一个列表列表也可以解决。
为此,请返回Chrome检查窗口,分析html树的结构,并注意您必须转到哪个元素。就我而言,所需的数据位于“tbody”元素中。每个银行及其SWIFT代码都包含在一个“tr”元素中,每个“tr”元素有多个“td”元素。“td”元素包含我正在寻找的数据。
html 树可以描述如下:table, tbody, tr, td
我在一行中做到了,如下所示:
result = pd.DataFrame([[td.text for td in row.findAll('td')] for row in table.tbody.findAll('tr')])
b) 准备自动化
现在我们已经抓取了第一个网页,我们需要考虑如何抓取我们尚未看到的新网页。我这样做的方法是复制人类行为:存储一页的结果,然后转到下一页。现在让我们专注于下一个网页。
在页面底部,有一个菜单,允许您进入 swift 代码表的特定页面。让我们检查检查器窗口中的“下一页”按钮。
“>”符号将引导我们进入下一页
这给出了以下 html 元素:
<a href="//bank-code.net/country/FRANCE-%28FR%29/15" data-ci-pagination-page="2" rel="next">></a>
现在在 Python 中获取 url 很简单:
"http:" + soup.find('a', attrs={'rel':'next'}).get('href')
我们快到了。
到目前为止,我们已经:
- 开发了一页表格的抓取 - 确定了下一页
的 url 链接
我们只需要做一个循环,然后运行代码。我建议遵循以下两种最佳实践:
1. 登陆新网页时打印出来:知道您的代码处于流程的哪个阶段(抓取代码可以运行数小时)
2.定期保存结果:避免在出现错误时丢失所有抓取的内容
只要我不知道何时停止抓取,我就会使用惯用的“while True:”语法循环。我在每一步打印出计数器值。而且我也在每一步将结果保存在csv文件中。这实际上可能会浪费时间,例如,更好的方法是每 10 或 20 步存储一次数据。但我追求快速实施。
三、完整代码
代码是这样的:
import os, bs4, requests
import pandas as pd
PATH = os.path.join("C:\\","Users","xxx","Documents","py") # you need to change to your local path
res = pd.DataFrame()
url = "http://bank-code.net/country/FRANCE-%28FR%29/"
counter = 0
def table_to_df(table):
return pd.DataFrame([[td.text for td in row.findAll('td')] for row in table.tbody.findAll('tr')])
def next_page(soup):
return "http:" + soup.find('a', attrs={'rel':'next'}).get('href')
while True:
print(counter)
page = requests.get(url)
soup = bs4.BeautifulSoup(page.content, 'lxml')
table = soup.find(name='table', attrs={'id':'tableID'})
res = res.append(table_to_df(table))
res.to_csv(os.path.join(os.path.join(PATH,"table.csv")), index=None, sep=';', encoding='iso-8859–1')
url = next_page(soup)
counter += 1
完整的代码(只有26行)可以在这里找到:https://github.com/FelixChop/MediumArticles/blob/master/Scraping_SWIFT_codes_Bank_names.py