本帖最后由 pinhai 于 2020-3-1 18:18 编辑
根据https://www.52pojie.cn/thread-1117192-1-1.html的需求,编写了抓取http://jsjtw.sh.gov.cn/zjw/zhsgqyxypj/index.html网站所有的在沪建筑业(施工)企业信用评分结果 。
主要涉及了多线程爬取,多线程csv写入,xls写入,边下边存等问题,代码如下,请高手指点指点,可否继续提高 效率。ps,该网站设计的有问题,每次请求返回的是一个大table,数据比较大,下载较慢,所以想到了多线程。
[Python] 纯文本查看 复制代码 import requests
import time
from bs4 import BeautifulSoup
#from openpyxl import load_workbook
import threading
import queue
#import sys
import csv
#写了2个写入函数,xls版本写入较慢,csv版本写入较快,推荐csv
headers={
'Host': 'ciac.zjw.sh.gov.cn',
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:73.0) Gecko/20100101 Firefox/73.0',
'Accept': 'application/json, text/javascript, */*; q=0.01',
'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
'Accept-Encoding': 'gzip, deflate, br',
'X-Requested-With': 'XMLHttpRequest',
'Connection': 'keep-alive',
'Referer': 'https://ciac.zjw.sh.gov.cn/SHCreditInfoInterWeb/CreditBookAnounce/QyCreditReportIndex',
'Cookie': 'AlteonP=AJJ5Q6XdHKyfbYBZT9nwKQ$$',
}
q = queue.Queue(maxsize=10000)#存放数据的队列
pages=queue.Queue(maxsize=10000)#存放页码的队列
lock = threading.Lock()
pagestoget=50#这里改为需要抓取的总页数
g=0#已抓取页数
def main():
wb = load_workbook("e:\\12.xlsx")
for i in range(1,pagestoget+1):
pages.put(i)
t_obj = []
w_obj=[]
for i in range(1,11)#10个抓取进程
t=threading.Thread(target=getdata)
t_obj.append(t)
for t in t_obj:
t.start()
#for t in t_obj:
# t.join() #这里没有join的原因是希望边抓边存,提高效率
time.sleep(2)
for i in range(1,5):#4个写入进程
#w=threading.Thread(target=writing,args=(wb,))#xls版本
w=threading.Thread(target=writingCSV,args=(wb,))#csv版本
w_obj.append(w)
for w in w_obj:
w.start()
for w in w_obj:
w.join() #这里join的原因是等待都存完了,结束主线程
print('搞定')
def writing(wb):#xls版本
while(1):
global g
if g==pagestoget:
break
print("数据队列大小:"+str(q.qsize()))
data=q.get()
listtemp=[]
lock.acquire()
#print("start writing")
for i in data :
listtemp.append(i.text)
if (data.index(i)+1)%5==0:#每5个换行1次
#print(listtemp)
ws = wb["Sheet1"]
ws.append(listtemp)
listtemp=[]
lock.release()
wb.save("e:\\12.xlsx")
g=g+1
def writingCSV(wb):#csv版本
while(1):
global g
if g==pagestoget:#判断是否抓完,否则一直检测队列中是否有数据
break
print("数据队列大小:"+str(q.qsize()))
if(q.qsize()):
data=q.get()
else:
time.sleep(1)#如果抓的慢,存的快,就等一等
continue
listtemp=[]
lock.acquire()#锁
with open('e:\\test.csv','a+',newline='',encoding='utf-8-sig')as f:
fwriter=csv.writer(f)
for i in data :
listtemp.append(i.text)
if (data.index(i)+1)%5==0:#每5个换行1次
fwriter.writerow(listtemp)
listtemp=[]
lock.release()#解锁
g=g+1
def getdata():
while(pages.qsize()):
page=pages.get()
url='https://ciac.zjw.sh.gov.cn/SHCreditInfoInterWeb/CreditBookAnounce/GetQyCreditReportAll?page='+str(page)+'&qyNam=&qyzjCode='#构造网址
#print(url)
try:
response=requests.get(url,headers=headers).json()['resultdata'].split('<div')[0].split('</thead>')[1]#获取所需数据
print(str(page)+"get ok")
except:
print("page"+str(page)+"error,jump")
pages.put(page)
continue
soup = BeautifulSoup(response,"html.parser")#beautifulsoup解析数据,是个50位的大list
data=soup.find_all('td')
q.put(data)#存入队列
if __name__=='__main__':
main()
|