我正在尝试学习一些基本的网络抓取。我最初设置了 scrapy 并发现它有点令人畏惧,所以我决定在开始爬行之前首先使用 beautifulsoup 进行一些单页抓取练习。我的项目想法是抓取下表并将信息输出到 Excel 文件。
该表位于维基百科的此页面: http://en.wikipedia.org/wiki/List_of_largest_corporate_profits_and_losses
我得到的输出非常成功!但是,我不确定我的代码是否非常“Pythonic”。我有点暴力地使用一些正则表达式来获取数据,我觉得肯定有一种更简单、更快的方法来获取表数据并删除一些讨厌的 u'Name' 格式和图像链接。 table 。将来,我想知道除了我的黑客方法之外,抓取表格和删除格式的标准方法是什么。
具体来说,在表格的第3列中,我们看到有一个国家国旗的图像以及我关心的信息(国家名称)。因此,我不能只做单元格[3 ].find(文本=True)。我通过仅获取单元格 3 中的所有 a 标签,然后使用正则表达式仅获取标题中包含的国家/地区名称来解决此问题:
for j,cell in enumerate(cells):
if j%3 == 0:
text = (cell.findAll('a'))
感谢并抱歉发了这么长的帖子!
from bs4 import BeautifulSoup
import urllib2
import re
wiki = "http://en.wikipedia.org/wiki/List_of_largest_corporate_profits_and_losses"
header = {'User-Agent': 'Mozilla/5.0'} #Needed to prevent 403 error on Wikipedia
req = urllib2.Request(wiki,headers=header)
page = urllib2.urlopen(req)
soup = BeautifulSoup(page)
table = soup.find("table", { "class" : "wikitable sortable" })
f = open('output.csv', 'w')
num = []; company = []; industry = []; country = []; year = []; reportdate = [];
earnings = []; usdinflation = []; usdrealearnings = []; cunts = [];
for i,row in enumerate(table.findAll("tr")):
cells = row.findAll("td")
if len(cells) == 9:
num.append(cells[0].find(text=True))
company.append(cells[1].findAll(text=True))
industry.append(cells[2].find(text=True))
country.append(cells[3].find(text=True))
year.append(cells[4].find(text=True))
reportdate.append(cells[5].find(text=True))
earnings.append(cells[6].find(text=True))
usdinflation.append(cells[7].find(text=True))
usdrealearnings.append(cells[8].find(text=True))
for j,cell in enumerate(cells):
if j%3 == 0:
text = (cell.findAll('a'))
newstring = re.search(r'(title="\w+\s\w+")|(title="\w+")',str(text))
if not(newstring is None):
newstring2 = re.search(r'("\w+")|("\w+\s\w+")',newstring.group())
cunts.append(newstring2.group())
for i in range(len(num)):
s = str(company[i])
newstring = re.search(r'\w+\s|\w+\w+', s).group();
write_to_file = str(num[i])+ "," + newstring + "," + str(industry[i]) + "," + cunts[i].encode('utf-8') + ","+ str(year[i]) + ","+ str(reportdate[i])+ ","+ earnings[i].encode('utf-8') + "," + str(usdinflation[i]) + "," + str(usdrealearnings[i]) + "\n";
f.write(write_to_file)
f.close()
最佳答案
这个怎么样:
from bs4 import BeautifulSoup
import urllib2
import re
wiki = "http://en.wikipedia.org/wiki/List_of_largest_corporate_profits_and_losses"
header = {'User-Agent': 'Mozilla/5.0'} #Needed to prevent 403 error on Wikipedia
req = urllib2.Request(wiki,headers=header)
page = urllib2.urlopen(req)
soup = BeautifulSoup(page)
table = soup.find("table", { "class" : "wikitable sortable" })
f = open('output.csv', 'w')
for row in table.findAll('tr'):
f.write(','.join(''.join([str(i).replace(',','') for i in row.findAll('td',text=True) if i[0]!='&']).split('\n')[1:-1])+'\n')
f.close()
输出到文件:
#,Company,Industry,Country,Year,Report Date,Earnings (Billion),USD Inflation to December 2012[1],USD "Real" Earnings (Billion)
1,ExxonMobil,Oil and gas,United States,2008,31 December 2008,$45.22[2],9.40%,$49.50
2,ExxonMobil,Oil and gas,United States,2006,31 December 2006,$39.5[2],13.95%,$45.01
3,ExxonMobil,Oil and gas,United States,2007,31 December 2007,$40.61[2],9.50%,$44.47
4,ExxonMobil,Oil and gas,United States,2005,31 December 2005,$36.13[3],16.85%,$42.22
5,ExxonMobil,Oil and gas,United States,2011,31 December 2011,$41.06[4],1.90%,$41.84
6,Apple,Consumer electronics,United States,2012,29 September 2012,$41.73 [5],-0.63%,$41.47
-,Industrial & Commercial Bank of China,Banking,China,2012,31 December 2012,RMB 238.7[6],-,$38.07
7,Nestlé,Food processing,Switzerland,2010,31 December 2010,$37.88[7],4.92%,$39.74
.....and so on
解释一下~
关于 Python,需要记住一些事情。
- 使 u'foo' str(u'foo') 删除 unicode 文字表示法
- 不要低估在列表推导式中使用 if/else 语句或比较 (!=) 的值(value)。这是过滤掉垃圾的 killer 级方法,而无需编写其他部分的代码。
好吧,在表上使用 prettify() 后,您会发现格式做得相当好,并且 csv 的每一行上所需的每一位数据都被分成 <tr>
。标签。
使用 row.findAll(tag='tr', text=True) 我所做的是将所有数据(尚未过滤)拆分为行列表。 soup.findAll 将列出指定标签的每个实例。在这种情况下,每个 <tr\>
包含在表中。
我们只想要表格文本,而不是格式带来的任何额外垃圾,因此 text=True 只获取表格单元格中显示的文本。
我将其嵌套在列表理解中,该列表理解将搜索返回的任何数据转换为字符串(删除 u'foo'),并用 ',' 分隔行中的每个元素,以使用所需的 csv 格式进行 jive并添加了一些 if 要求来过滤掉任何剩余的垃圾,例如括号。
关于python - 使用 beautiful soup 的基本网页抓取 : scrape a table,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23420533/