excel抓取网页动态数据( 爬取代码解析需要的包有numpypandas,,等代码)

优采云 发布时间: 2022-04-04 22:08

  excel抓取网页动态数据(

爬取代码解析需要的包有numpypandas,,等代码)

  

  

  

  标签位置明确了,说下爬取的基本思路:

  先获取30条记录的链接,然后依次爬取信息,最后打开下一页,重复。

  这是第一次爬取(有100页),一旦出现异常,可以先保存爬取的。

  二、代码分析

  需要的包有numpy、pandas、BeautifulSoup、re、urllib等。

  代码分析如下:

  1、getbsobj 函数

  def getbsobj(url):

try:

html = urlopen(url,timeout=3)

except (HTTPError,socket.timeout):

return None

return BeautifulSoup(html,'html.parser')

  定义一个返回 bs 对象的函数,包括一些异常处理。

  2、getLinksList 函数

  def getLinksList(url,n):

'''

:param url: 链接

:param n: 第n页

:return: 链接列表

'''

ls = []

bsobj=getbsobj(url+'/pg%d'%n)

if not bsobj:

print('该页打不开')

return None

while True:

aTagList = bsobj.find('ul', {'class': 'listContent'}).findAll('a', {'class': 'img'})

if len(aTagList)>0:

print('打开成功')

break

else:

print('进入休眠')

time.sleep(60)

bsobj=getbsobj(url+'/pg%d'%n)

for aTag in aTagList:

if 'href' in aTag.attrs:

ls.append(aTag['href'])

return ls

  定义函数获取30条交易记录链接,并以列表的形式返回。

  该链接位于 ul 标签下的 a 标签中。

  中间有个圈。原因是有时候网页可以打开,但是交易记录没有显示。这时候需要再次尝试打开,直到出现交易记录。如果没有开启,可能是因为访问过于频繁,所以在无法开启的时候,会进入休眠60秒。

  3、getInfo 函数

  infoArray = []

  一条记录的信息是通过一维列表保存的,infoArray是一个二维列表,保存了所有获取到的记录的信息。

  tags = bsobj.find('div',{'class':'introContent'}).findAll('li')

  获取收录基本属性和事务属性内容的标记列表。

  info = list()

info.append(bsobj.head.title.get_text().split()[0])

  info 是保存记录的所有信息的临时列表。

  此处添加的是社区名称。

  for tag in tags:

info.append(tag.get_text().strip()[4:])

  这里添加的是基础属性和交易属性的内容

  ul = bsobj.find('ul',{'class':'record_list'})

info.append(ul.li.span.get_text().strip())

text = ul.li.p.get_text().strip()

a = re.search(r'\d+元/平',text)

if a ==None:

info.append('无')

else:

info.append(a.group()[:-3])

b = re.search(r'\d+-\d+-\d+', text)

if b == None:

info.append(text)

else:

info.append(b.group())

  这里添加的是交易金额、单价和交易日期,因为和上面的属性不一样,需要单独处理。

  infoArray.append(info)

  添加记录

  arr = np.array(infoArray)

  将最终的 infoArray 转换为矩阵 arr 并返回它。

  4、checkid 函数

  检查动态爬取时是否获取到id。如果已经获取到,则说明上次运行的最新记录已经被爬取,此时无需继续爬取。

  def checkid(ls,id):

'''

:param ls: 链接列表

:param id: 成交id

:return: bool

'''

links = []

tag = False

for lk in ls:

if lk[-17:-5]!=str(id):

links.append(lk)

else:break

if len(links)!=len(ls):

tag = True

ls = links

return tag,ls

  在这里,检查列表中的每个链接。如果 id 与上次保存的 id 相同,则该链接及其后续链接都被丢弃,并返回一个 bool 值和一个已处理的列表。

  5、getIndex 函数

  用于获取保存到 Excel 时所需的属性标签

  def getIndex(url):

cols = ['小区名字']

ls = getLinksList(url, 1)

bs = getbsobj(ls[0])

tags = bs.find('div', {'class': 'introContent'}).findAll('li')

for tag in tags:

cols.append(tag.span.get_text().strip())

cols += ['成交额(万元)','单价(元/平)','日期']

new_id = ls[0][-17:-5]

return cols,new_id

  6、下载功能

  主功能

  def download(url,start,end):

  从起始页开始,爬到结束页(包括结束页)

  cols,new_id = getIndex(url)

  获取最新记录的属性列表和id号

  ls = getLinksList(url,i)

  获取链接列表

  tag,ls = checkid(ls,id)

  检查*敏*感*词*

  arr=getInfo(ls)

  获取数据矩阵

  df_new = pd.DataFrame(arr,columns=cols)

df = df.append(df_new,ignore_index=True)

  转换为 DataFrame 格式。

  df_old = pd.read_excel('链家成交数据.xlsx')

df_old = df.append(df_old, ignore_index=True)

df_old.to_excel('链家成交数据.xlsx')

  另存为 Excel。

  三、输出结果

  

  

  四、完整代码

  from bs4 import BeautifulSoup

from urllib.request import urlopen

from urllib.error import HTTPError

import pandas as pd

import numpy as np

import re

import socket,time

url = 'https://bj.lianjia.com/chengjiao'

def getbsobj(url):

try:

html = urlopen(url,timeout=3)

except (HTTPError,socket.timeout):

return None

return BeautifulSoup(html,'html.parser')

def getLinksList(url,n):

'''

:param url: 链接

:param n: 第n页

:return: 链接列表

'''

ls = []

bsobj=getbsobj(url+'/pg%d'%n)

if not bsobj:

print('该页打不开')

return None

while True:

aTagList = bsobj.find('ul', {'class': 'listContent'}).findAll('a', {'class': 'img'})

if len(aTagList)>0:

print('打开成功')

break

else:

print('进入休眠')

time.sleep(60)

bsobj=getbsobj(url+'/pg%d'%n)

for aTag in aTagList:

if 'href' in aTag.attrs:

ls.append(aTag['href'])

return ls

def getInfo(ls):

'''

:param ls:链接列表

:return: 数组

'''

infoArray = []

i = 1

for lk in ls:

print('正在获取第%d条信息'%i)

bsobj = getbsobj(lk)

if not bsobj:continue

tags = bsobj.find('div',{'class':'introContent'}).findAll('li')

info = list()

info.append(bsobj.head.title.get_text().split()[0])

for tag in tags:

info.append(tag.get_text().strip()[4:])

ul = bsobj.find('ul',{'class':'record_list'})

info.append(ul.li.span.get_text().strip())

text = ul.li.p.get_text().strip()

a = re.search(r'\d+元/平',text)

if a ==None:

info.append('无')

else:

info.append(a.group()[:-3])

b = re.search(r'\d+-\d+-\d+', text)

if b == None:

info.append(text)

else:

info.append(b.group())

infoArray.append(info)

i += 1

print('-'*20)

arr = np.array(infoArray)

return arr

def checkid(ls,id):

'''

:param ls: 链接列表

:param id: 成交id

:return: bool

'''

links = []

tag = False

for lk in ls:

if lk[-17:-5]!=str(id):

links.append(lk)

else:break

if len(links)!=len(ls):

tag = True

ls = links

return tag,ls

def getIndex(url):

cols = ['小区名字']

ls = getLinksList(url, 1)

bs = getbsobj(ls[0])

tags = bs.find('div', {'class': 'introContent'}).findAll('li')

for tag in tags:

cols.append(tag.span.get_text().strip())

cols += ['成交额(万元)','单价(元/平)','日期']

new_id = ls[0][-17:-5]

return cols,new_id

def download(url,start,end):

i = start

fn = open('id.txt','r')

id = fn.readline()

fn.close()

cols,new_id = getIndex(url)

df = pd.DataFrame()

try:

while True:

print('正在获取第%d页链接'%i)

ls = getLinksList(url,i)

if not ls:

print(ls)

print(1)

break

#print(ls)

tag,ls = checkid(ls,id)

#print(ls)

arr=getInfo(ls)

df_new = pd.DataFrame(arr,columns=cols)

df = df.append(df_new,ignore_index=True)

if tag:

print(2)

break

i += 1

if i>end:

print(3)

break

except Exception as e:

print(e)

else:

df_old = pd.read_excel('链家成交数据.xlsx')

df_old = df.append(df_old, ignore_index=True)

df_old.to_excel('链家成交数据.xlsx')

fn = open('id.txt', 'w')

fn.write(new_id)

fn.close()

print('程序执行完毕!')

if __name__ == '__main__':

download(url,1,20)

  第一次爬取时,需要对上面的代码稍作修改,在try后面加一个finally,保存爬取的内容,防止异常造成的丢失。以上代码可用于后续爬取。据观察,链家数据每天更新3到16页,所以下载功能的参数取1和20。

  正常结束应该是先打印(2),再打印(程序执行完毕),如果一天更新21页,则先打印(3),再打印(程序执行完毕)完成),那么就需要修改参数再执行,当然也可以直接把参数20改成100,这样除非出现莫名其妙的异常,一般都能正常执行。

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线