距离上次接单爬取数据已经有将近2年时间了,一方面是没有去刻意找单子,另一个方面这个行业变得越来越专业化,同时价格也越来越低让人咂舌,但最重要的原因是工作和学习的东西太多,有点忙不过来。但是最近这个单子是老客户,给出的价格也还可以接受,所以经过考虑还是把单子接下来了,其实工作未开始就已经能够预见其中的难点是应对验证码的反爬,因为数据量不是很大我还是采用了最拙略的办法,亲自拿起鼠标操作验证码验证,但结果搞得我有点有些不爽,所以在接下来会再写一篇用python破解百度旋转验证码的技术博客,用以表示爬虫工程师的愤怒!言归正传,直接开干!
通过本次实践你将会学到以下技术:
python文件读写(r表示读,w表示写,b表示以二进制编码读写,a表示追加写入) | with open(file,'rb') as f: page = f.read() |
文件目录遍历方法os.listdir() | for each in os.listdir(path): file = os.path.join(path,each) print(file) |
windows和Linux下chromedriver的配置 | |
selenium驱动本地已打开的chrome页面进行单步调试 | 见2.数据采集代码 |
xpath提取页面数据 | 见3.数据解析代码 |
pandas清洗数据 | 见4.数据清洗 |
文件移动模块shutil的使用 | 见3.数据解析代码 |
1、整体爬取思路分解:
1>.通过selenium打开目标网站,通过提供的企业名称列表一个一个放到搜索框中进行搜索,并把结果页面通过.html保存到本地。
2>.对采集到的html数据进行解析,并存入Excel。
3>.对上一步中提取的数据进行格式转换、去重、垃圾字符清除,得到部分最终数据。
4>.对采集失败的数据进行过滤提取,并重新采集也就是重复以上三个步骤。
5>.数据合并,将多次采集和清洗的数据合并到一起,得到最终数据,一手交数据一手收款。
6>.休养恢复
2.数据采集代码
# coding=utf-8
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from lxml import etree
import time
#这部分是selenium单步调试启动本地chrome页面并指定端口与临时数据存放目录的,配合下面的注释使用
'''/opt/google/chrome/google-chrome --no-sandbox --remote-debugging-port=9222 --user-data-dir="/tmp/userdata" &'''
# 读取包含企业名称的excel并将其转换为列表
def read_excel():
df = pd.read_excel("company_name.xlsx")
name_list = df["企业名称"].to_numpy().tolist()
return name_list
# 采集入口
def main():
companys = read_excel()
# chrome_options = Options()
chrome_driver = r'/home/ttk/桌面/chrome/chromedriver'
# chrome_options.add_experimental_option("debuggerAddress", "127.0.0.1:9222")
# b = webdriver.Chrome(chrome_driver, options=chrome_options)
b = webdriver.Chrome(chrome_driver)
b.get('https://aiqicha.baidu.com/company_detail_46022060497321')
try:
# 用于记录采集到的位置,失败后方便下次自动从上次的位置开始
with open("number.txt") as f:
i = int(f.read())
except Exception as e:
i=0
while True:
print(i)
company = companys[i]
element = b.find_element_by_id("aqc-header-search-input")
element.clear()
element.send_keys(company)
time.sleep(1)
# print(b.window_handles)
b.find_element_by_class_name("search-btn").click()
time.sleep(3)
################################## 以下代码区间段是避开页面元素不能点击的情况,可以尝
#试用click()点击替换
html_ = etree.HTML(b.page_source)
try:
new_url = html_.xpath('(//h3[@class="title"]/a/@href)[1]')[0]
except Exception as e:
b.quit()
i+=1
with open("number.txt", 'w') as f:
f.write(str(i))
print(new_url)
with open("url.txt",'a') as n:
n.write(new_url+"\n")
b.get('https://aiqicha.baidu.com%s'%new_url)
####################################
time.sleep(3)
html = b.page_source
with open("./failed/%s_%d.html"%(company,i),"wb") as f:
f.write(html.encode("utf-8"))
i+=1
with open("number.txt",'w') as f:
f.write(str(i))
if __name__=="__main__":
while True:
try:
main()
except Exception as e:
print(e)
time.sleep(5)
3.数据解析代码
# coding=utf-8
import os
import pandas as pd
from lxml import etree
import shutil
def parse():
base = os.getcwd()
path = os.path.join(base,"data") #待解析数据在data目录下
dist = os.path.join(base,"error") #解析失败数据移动到error进行后续重采
print(path)
dic_list = []
for each in os.listdir(path):
file = os.path.join(path,each)
print(each)
with open(file,'rb') as f:
page = f.read()
hml = etree.HTML(page)
try:
trs = hml.xpath('//div[@id="basic-business"]/table//tr')
except Exception as e:
print(e)
shutil.move(file,dist)
continue
title = each.strip(".html").split("_")
dic={"序号":int(title[1]),"企业名称":title[0]}
for tr in trs:
tr_index = tr.xpath(".//td")
text = []
i=1
for eve in tr_index:
if i%2==1:
key = eve.xpath("string(.)") # 提取当前节点下所有子节点中的文本数据
elif i%2==0:
if key.strip() =="法定代表人":
value = eve.xpath('./div[2]/a[1]/text()|./div[2]/p/text()')[0]
elif key.strip() in ("执行事物合伙人","执行事务合伙人","负责人","投资人"):
key="法定代表人"
value = eve.xpath('./div[2]/p/text()|./div[2]/a[1]/text()')[0]
else:
value = eve.xpath("string(.)")
dic.update({key.strip():value.lstrip()})
i+=1
dic_list.append(dic)
df = pd.DataFrame(dic_list)
df.sort_values(by="序号",inplace=True,ascending=True)
df.to_excel("total.xlsx",index=False)
if __name__ == '__main__':
parse()
4.数据清洗
# coding=utf-8
import pandas as pd
def clean_data():
df = pd.read_excel("total.xlsx")
need= df.loc[:,["法定代表人","企业名称","经营状态","注册资本","所属行业","统一社会信用代码","工商注册号","组织机构代码","成立日期","行政区划","经营范围","核准日期"]]
print(need.shape)
need.dropna(how="all",inplace=True) # 删除空行
# print(need)
need.loc[:, "姓名"] = need["法定代表人"].str.strip().str.strip('"')
need.loc[:,"经营状态"] = need["经营状态"].str.strip()
need.loc[:,"注册资本(万元)"] = need["注册资本"].str.strip().str.replace("万","")
need.loc[:,"成立年份"] = need["成立日期"].str.split("-",expand=True)[0]
need.loc[need["经营状态"].isin(["吊销","注销"])==True,"终止年份"] = need["核准日期"]
print(need.shape)
need.dropna(subset=["经营状态","注册资本","所属行业","统一社会信用代码","工商注册号","组织机构代码","成立日期","行政区划","经营范围"],inplace=True) # 删除空行
print(need.shape)
result = need.loc[:,['姓名','企业名称','注册资本(万元)',"经营状态",'所属行业','成立年份','终止年份','行政区划','统一社会信用代码','工商注册号','组织机构代码',"经营范围"]]
result.to_excel("result_total.xlsx",index=False)
if __name__=="__main__":
clean_data()
5.验证码截图(下次写这个的python解决方案)