网页表格抓取( 【soup】新三板soup()进阶版(一))

优采云 发布时间: 2021-10-24 03:15

  网页表格抓取(

【soup】新三板soup()进阶版(一))

  爬取最多的数据分析是表类型。需要专注于掌握。

  本文介绍四种方法:

  一、find_all 方法 (tr, td)

  进行如下操作:

  1、检查网页元素,观察

  右键单击表单并选择“检查”。在弹出的“开发者工具”中,我们可以看到页面上的每个元素以及其中收录的内容。

  

  可以看到每一行都是一个tr标签,每个内容都在tr下的td标签中。(可以做练习,但实际情况往往没有那么简单,这个页面的所有数据都显示在一个页面上。其实很多数据往往分布在多个不同的页面上,需要调整结果总数显示在每个页面上,或者遍历所有来捕获完整的数据。)

  可以看到表格属性:table

  2、连接获取网页内容,使用BeautifulSoup处理html数据

  # 导入BeautifulSoup、urllib(request、urlopen)

from bs4 import BeautifulSoup as bs

import urllib

import urllib.request

from urllib.request import urlopen

import csv

urpage="https://www.fasttrack.co.uk/league-tables/tech-track-100/league-table/"

page = urlopen(urpage)

soup=bs(page,"html.parser")

  可以使用print(soup)查看是否正确获取汤

  

  如果打印出来,可以看到我们要查找的表中的th(表头)有8列。它们是等级、公司、位置等。

  3、 遍历汤中的所有元素并将它们存储在变量中

  存储可以使用空列表+设置标题+循环追加元素的方法

  循环的结构很简单,主要部分如下(通过两个find_all,第一个tr list进行for循环,第二个td分截截取):

  results=table.find_all('tr')

for result in results:

data=result.find_all("td")

loca=data[2].getText()

······

rows.append([rank, company, loca, yearend, anual_sales, sales, staff, comments])

  完成如下:

  ## 空列表加表头

rows=[]

rows.append(["rank","company","loca","yearend","anual_sales","sales","staff","comments"])

## 循环存储

table=soup.find("table")

results=table.find_all('tr')

for result in results:

data=result.find_all("td")

if len(data)==0:

continue

rank=data[0].getText()

company=data[1].getText()

## 如需使用纯公司名,需处理成

## company=data[1].find("span",attrs={"class":"company-name"}).getText()

loca=data[2].getText()

yearend=data[3].getText()

anual_sales=data[4].getText()

sales=data[5].getText()

## 处理sales中符号

sales = sales.strip('*').strip('+').replace(',','')

staff=data[6].getText()

comments=data[7].getText()

rows.append([rank, company, loca, yearend, anual_sales, sales, staff, comments])

print(rows)

  4、保存到csv

  with open('techtrack100.csv','w', newline='',encoding="utf-8") as f_output:

csv_output = csv.writer(f_output)

csv_output.writerows(rows)

  二、pandas 库中的 read_html 方法(表类型)

  只需不到十行代码,约一分钟就能将4000多家A股上市公司的209页信息一网打尽。与正则表达式、xpath等常规方法相比,省心省力多了。

  参数:io 可以是目标 URL,match 是要匹配的正则表达式,flavor 是解析器,header 是指定的行标题,encoding 是要读取的编码格式。只有设置正确才能正确提取表格,否则会出现乱码。

  %s 代表页数;a:代表A股,用h代替a,代表港股;用xsb替换a,代表新的第三块板。

  import pandas as pd

import csv

for i in range(1,178): # 爬取全部177页数据

url = 'http://s.askci.com/stock/a/?reportTime=2017-12-31&pageNum=%s' % (str(i))

tb = pd.read_html(url)[3] #经观察发现所需表格是网页中第4个表格,故为[3]

tb.to_csv(r'C:\Users\xxx\Desktop\1.csv', mode='a', encoding='utf_8_sig', header=1, index=0)

print('第'+str(i)+'页抓取完成')

  完整的高级版本代码:

  # 网页提取函数

def get_one_page(i):

try:

headers = {

'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36'

}

paras = {

'reportTime': '2019-12-31',

#可以改报告日期,比如2018-6-30获得的就是该季度的信息

'pageNum': i #页码

}

url = 'http://s.askci.com/stock/a/?' + urlencode(paras)

response = requests.get(url,headers = headers)

if response.status_code == 200:

return response.text

return None

except:

print('爬取失败')

# beatutiful soup解析然后提取表格

def parse_one_page(html):

soup = BeautifulSoup(html,'lxml')

content = soup.select('#myTable04')[0] #[0]将返回的list改为bs4类型

tbl = pd.read_html(content.prettify(),header = 0)[0]

# prettify()优化代码,[0]从pd.read_html返回的list中提取出DataFrame

tbl.rename(columns = {'序号':'serial_number', '股票代码':'stock_code', '股票简称':'stock_abbre', '公司名称':'company_name', '省份':'province', '城市':'city', '主营业务收入(201712)':'main_bussiness_income', '净利润(201712)':'net_profit', '员工人数':'employees', '上市日期':'listing_date', '招股书':'zhaogushu', '公司财报':'financial_report', '行业分类':'industry_classification', '产品类型':'industry_type', '主营业务':'main_business'},inplace = True)

print(tbl)

# return tbl

# rename将表格15列的中文名改为英文名,便于存储到mysql及后期进行数据分析

# tbl = pd.DataFrame(tbl,dtype = 'object') #dtype可统一修改列格式为文本

tbl.to_csv(r'C:\Users\xxx\Desktop\2.csv', mode='a',encoding='utf_8_sig', header=1, index=0)

# 主函数

def main(page):

for i in range(1,page): # page表示提取页数

html = get_one_page(i)

parse_one_page(html)

# 单进程

if __name__ == '__main__':

main(200) #共提取n页

  快速方便,但缺点是无法读取单元格中的href链接。

  三、selenium(可以被JavaScript动态抓取的表)

  思路(Selenium基本是“可见,可爬取”):一次爬取所有td节点单元内容,按照表列数划分列表内容

  1、 爬取所有td节点,按照表列数拆分成表

  from selenium import webdriver

browser = webdriver.Firefox()

browser.get('http://data.eastmoney.com/bbsj/202009/yjbb.html')

element=browser.find_element_by_xpath('//div[@id="dataview"]')

# 提取表格内容td

td_content = element.find_elements_by_tag_name("td") # 进一步定位到表格内容所在的td节点

lst = [] # 存储为list

for td in td_content:

lst.append(td.text)

print(lst) # 输出表格内容

import pandas as pd

# 确定表格列数

col = len(element.find_elements_by_css_selector('tr:nth-child(1) td'))

# 通过定位一行td的数量,可获得表格的列数,然后将list拆分为对应列数的子list

lst = [lst[i:i + col] for i in range(0, len(lst), col)]

# list转为dataframe

df_table = pd.DataFrame(lst)

# 添加url列

# 原网页中打开"详细"链接可以查看更详细的数据,这里我们把url提取出来,方便后期查看

lst_link = []

links = element.find_elements_by_xpath("//a[contains(text(),'详细')]")

for link in links:

url = link.get_attribute('href')

lst_link.append(url)

lst_link = pd.Series(lst_link)

df_table['url'] = lst_link

print(df_table.head()) # 查看DataFrame

  四、分析 URL JavaScript 请求

  看

  参考:

  (这位“老农民工”博主写了很多优秀的文章)

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线