我正在尝试学习一些基本的网页抓取。我最初设置scrapy并注意到它有点令人生畏,所以我决定在进行爬行之前首先使用beautifulsoup进行一些单页抓取练习。我的项目想法是刮掉下表并将信息输出到excel文件。
该表位于维基百科上的此页面: http://en.wikipedia.org/wiki/List_of_largest_corporate_profits_and_losses
我得到的输出非常成功!但是,我不确定我的代码是非常“pythonic”。我有点粗暴地强迫我使用一些正则表达式来获取数据,我觉得有一种更简单,更快捷的方法来获取表格数据并删除一些遍布整个区域的一些讨厌的u'Name'格式和图像链接表。在将来,我想知道除了我的hacky方式之外,刮除表格和删除格式的标准方法是什么。
具体来说,在表格的第3列中,我们看到有一个国家的国旗图像以及我关心的信息(国家名称)。因此,我不能只做细胞[3] ] .find(文本=真)。我通过只获取单元格3中的所有标签然后使用正则表达式来获取标题中包含的国家/地区名称来解决这个问题:
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()
答案 0 :(得分:2)
这是怎么回事:
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的一些事情。
好的,在桌子上使用了美化()之后,您会注意到格式运行得相当好,并且您在csv的每一行上所需的每一位数据都会分成<tr>
个标记。
使用row.findAll(tag =&#39; tr&#39;,text = True)我所做的就是将所有数据(尚未过滤)分成一系列行。 soup.findAll将列出指定标记的每个实例。在这种情况下,表格中包含每个<tr\>
。
我们只希望表格文本不是格式化附带的任何额外垃圾,因此text = True只获取表格单元格中显示的文本。
我已将此嵌套在列表理解中,该列表理解将搜索返回的任何数据转换为字符串(删除u&#39; foo&#39;)并将行中的每个元素分隔为&#39; &#39;使用所需的csv格式进行jive并添加一些if if来过滤掉像括号一样的剩余垃圾。