虫是一件很有趣的事情,就像黑客一样,和服务器对抗,服务器维护代码防止爬虫,我们通过各种bug解决爬虫困难,真实有趣!今天给大家带来一串代码,针对网页中的表格爬取,表格页码变化,而链接url不变的情况1
首先给出爬取的原文链接:https://d.qianzhan.com/yuanqu/
#导入所需库文件 import requests import pandas as pd import csv
上面三个库文件是本次爬虫所需的主要库,requests库向网站发送请求,请求成功则返回响应状态码为200,否则为400或者404,pandas库可以用来直接抓取表格数据,csv库用来将文件保存在本地csv文件内。
#这里爬取的表格为广东省的数据表格 areas = ['广东省'] #写入链接url urls = ['https://d.qianzhan.com/yuanqu/?p={}'.format(str)for str in areas] x = 0 for url in urls: #打开csv文件,在第一行写入标题 with open('前瞻.csv', 'a', newline='', encoding='utf-8-sig') as csvfile: w = csv.writer(csvfile) # 写入标题或称之为变量 w.writerow(['序号', '园区名称', '省份', '城市', '占地面积', '企业数', '详情']) # 对表格的全部页数进行抓取 for i in range(1, 33): # 跳页 # 在网页源代码找到页码的属性,这里页码在属性page上 data = { 'page': i } # 对网站发送请求,获得响应 s = requests.session() d = s.get(url, params=data) # 抓取html表格 tb = pd.read_html(d.text)[1] # 将抓取来的表格填入csv文件内 tb.to_csv(r'前瞻.csv', mode='a', encoding='utf_8_sig', header=0, index=0) # 每抓取玩一个省份,打印出抓取结果,给用户更好体验 print(areas[x], "已经抓取完成!请到本地文档中查看抓取结果!") x = x+1 # 全部抓取完成,则打印'全部抓取完毕!' print('全部抓取完毕!')
最终成功抓取到所有表格的内容,并存入了csv文件内,大家有问题可以下方留言讨论!
某网站读取表格里面的内容,简单处理后写入CSV文件。需要留意:查找某些字符是否存在,查找其位置,按照位置读取字符串内容,Python真的蛮灵活的。后续还会做两个文件的比较,以及文件内容的删除。让已实现的功能具有普适性,抽取函数供不同场景使用,这才有软件工程的思想。
实践Python
fileName = "SplitNo";
nowTime = datetime.datetime.now().strftime('%Y-%m-%d-%H-%M-%S')
filePath = fileName + nowTime + ".csv";
csvFile = open(filePath, 'w', newline='', encoding='utf-8')
writer = csv.writer(csvFile,dialect='excel')
head = ["页数","序号","编号", "产品名称", "原始文本"]
writer.writerow(head)
startPage = 1;
totalPage = 1260;
wait.until(EC.presence_of_element_located((By.ID, "content")))
browser.find_element_by_id("page").clear()
browser.find_element_by_id("page").send_keys(str(startPage));
browser.find_elements_by_xpath('//input[@src="images/dataanniu_11.gif"]')[0].click();
time.sleep(3)
n = startPage;
while n < totalPage:
wait.until(EC.presence_of_element_located((By.ID, "content")))
content = browser.find_element_by_id("content");
oneThanOneLine = False;
for attr in content.find_elements_by_tag_name("a"):
text = str(attr.get_attribute('innerHTML'))
text = text.replace('\r', '').replace('\n', '').replace('\t', '')
print(str(text) + "查询位置:" + (str)(text.find(".")))
if text.find(".") != -1:
csvRow = []
csvRow.append(str(n))
pos = findPos(text)
if pos != -1:
name = text[0:pos-1]
notext = text[pos:-1]
csvRow.append(name.split(".")[0])
csvRow.append(notext.split(" ")[0])
if name.__len__() > 1:
csvRow.append(name.split(".")[1])
csvRow.append(text)
writer.writerow(csvRow)
preText = text
oneThanOneLine = False
else:
preText = preText + text;
#p = re.compile(r'[<](.*?)[>]', re.S)
# matches = re.findall(cleanr, preText)\
#for match in matches:
# print(match)
cleanr = re.compile('<.*?>')
preText = re.sub(cleanr, '', preText)
print(preText)
oneThanOneLine = True
n = n + 1
wait.until(EC.presence_of_element_located((By.ID, "page")))
browser.find_element_by_id("page").clear()
browser.find_element_by_id("page").send_keys(str(n))
browser.find_elements_by_xpath('//input[@src="images/xxxx.gif"]')[0].click()
print("已经切换到新一页:" + str(n))
csvFile.close()
browser.close()
碰到的问题:
1、TypeError: expected string or bytes-like object
使用场景:content = browser.find_element_by_id("content");
tdList = re.findall(r'<td[^>]*>(.*?)</td>', str(content.get_attribute('innerHTML')), re.I | re.M)
if tdList:
for item in tdList:
print(item)
使用函数:re.findall(pattern,string,flag)
pattern匹配的是字符串,需要把第二个参数转化为string类型就可以。
2、对循环列表的最后一个元素进行特别处理
使用场景:aTag = attr.find_elements_by_tag_name("a")
if aTag.__len__()>1:
for aText in aTag:
if aTag.__len__() - 1 == aTag.index(aText):
print(aText )
3、超时跳转使用wait元素比较靠谱些
wait.until(EC.presence_of_element_located((By.ID, "content")))
print(str(n) + "img[@src='images/dataanniu_07.gif'])")
content = browser.find_element_by_id("content");
content.find_elements_by_xpath('//img[@src="images/dataanniu_07.gif"]')[0].click();'''
4、查询某字符串里面的HTML字符
p = re.compile(r'[<](.*?)[>]', re.S)
matches = re.findall(p, preText)
for match in matches:
print(match)
5、清除某字符串里面的HTML字符
cleanr = re.compile('<.*?>')
preText = re.sub(cleanr, '', preText)
6、记录程序执行时间
import datetime
startTime = datetime.datetime.now()
endTime = datetime.datetime.now()
print(endTime - startTime).seconds
7、等待元素的方法
隐式等待:(WebDriver类下的)implicitly_wait(X),在X时间内,页面加载完成,进行下一步操作。首先Implicit Waits默认是等待时间是0,同时隐性等待是对driver起作用,所以只要设置一次即可,比强制等待更智能
缺点:非要加载到整个页面才能执行代码,这样影响代码的执行效率。一般情况下,我们想要的结果是只需加载到了我要定位的元素就执行代码,不需要等待整个页面的完全加载出来再执行代码。
Sleep显式等待:最简单的一种办法就是强制等待sleep(X),强制让浏览器等待X秒,不管当前操作是否完成,是否可以进行下一步操作,都必须等X秒的时间。
缺点是不能准确把握需要等待的时间;优点是使用简单,可以在调试时使用。
WebDriverWait显示等待:无需等待整个页面加载完成,只需加载到你要定位的元素就可以执行代码。
优点:代码执行效率快。是最智能的设置元素等待的方式。
缺点:需要导入webdriver下的expected_conditions、WebDriverWait、By三个包;写等待时间的代码稍显复杂。
python的matplotlib作图很强大,本文教你用6种不同方式解决将多种数据曲线画到一起。
今天,老板又要一个数据报表,小明选择用 python来实现。“用matplotlib用来可视化。并且必须用不同颜色标志每个数据曲线,曲线这些颜色也应该在Python里自动选择。”
"Python大大,你能给我一个方法,在同一个图中为不同的地块添加不同的颜色吗?",小明把这个问题抛给了Python大大。大大低头片刻,然后胸有成足的抬起头,说,“可以,给你6个办法来实现!!”
烦恼如何用python可视化多条数据曲线吗?本文提供6种解法
利用Matplotlib的默认方式来执行此操作。
例如:
import matplotlib.pyplot as plt import numpy as np x = np.arange(10) plt.plot(x, x) plt.plot(x, 2 * x) plt.plot(x, 3 * x) plt.plot(x, 4 * x) plt.show()
而且,正如您可能已经知道的那样,您可以轻松添加图例:
import matplotlib.pyplot as plt import numpy as np x = np.arange(10) plt.plot(x, x) plt.plot(x, 2 * x) plt.plot(x, 3 * x) plt.plot(x, 4 * x) plt.legend(['y = x', 'y = 2x', 'y = 3x', 'y = 4x'], loc='upper left') plt.show()
如果要控制将循环的颜色:
import matplotlib.pyplot as plt import numpy as np x = np.arange(10) plt.gca().set_color_cycle(['red', 'green', 'blue', 'yellow']) plt.plot(x, x) plt.plot(x, 2 * x) plt.plot(x, 3 * x) plt.plot(x, 4 * x) plt.legend(['y = x', 'y = 2x', 'y = 3x', 'y = 4x'], loc='upper left') plt.show()
希望有所帮助!如果您对matplotlib不熟悉。请关注微信python_dada学习。
首先,如果你想要在一个图上上绘制很多数据曲线,可以:
1. 将它们放在不同的图上(考虑在一个图上使用一些子图),或
2. 使用颜色以外的其他东西(即标记样式或线条粗细)来区分它们。
否则,你将陷入一个非常混乱的境地!
除此之外,许多人在不同程度上都是色盲,区分众多微妙不同的颜色对于更多的人来说比你可能意识到的要困难。
话虽如此,如果你真的想在一个轴上放20条线,并且有20种相对不同的颜色,这是一种方法:
import matplotlib.pyplot as plt import numpy as np num_plots = 20 # Have a look at the colormaps here and decide which one you'd like: # http://matplotlib.org/1.2.1/examples/pylab_examples/show_colormaps.html colormap = plt.cm.gist_ncar plt.gca().set_color_cycle([colormap(i) for i in np.linspace(0, 0.9, num_plots)]) # Plot several different functions... x = np.arange(10) labels = [] for i in range(1, num_plots + 1): plt.plot(x, i * x + 5 * i) labels.append(r'$y = %ix + %i$' % (i, 5*i)) # I'm basically just demonstrating several different legend options here... plt.legend(labels, ncol=4, loc='upper center', bbox_to_anchor=[0.5, 1.1], columnspacing=1.0, labelspacing=0.0, handletextpad=0.0, handlelength=1.5, fancybox=True, shadow=True) plt.show()
请注意,对于最后一个示例,在较新版本的matplotlib中,set_color_cycle已弃用,因此该行应该plt.gca().set_prop_cycle(plt.cycler('color', plt.cm.jet(np.linspace(0, 1, num_plots))))只是plt.cm.YOUR_PREFERED_COLOR_MAP根据您的需要进行更改。 -
如果您不知道要绘制的绘图的数量,可以在绘制它们直接从绘图中检索数字后更改颜色.lines,使用此解决方案:
一些随机数据
import matplotlib.pyplot as plt import numpy as np fig1 = plt.figure() ax1 = fig1.add_subplot(111) for i in range(1,15): ax1.plot(np.array([1,5])*i,label=i)
您需要的代码段:
colormap = plt.cm.gist_ncar #nipy_spectral, Set1,Paired colors = [colormap(i) for i in np.linspace(0, 1,len(ax1.lines))] for i,j in enumerate(ax1.lines): j.set_color(colors[i]) ax1.legend(loc=2)
结果如下:
我想对上一篇文章中给出的最后一个循环答案提供一个小的改进(该帖子是正确的,仍然应该被接受)。标记最后一个示例时所隐含的假设是plt.label(LIST)将标签号X放入LIST与第X 个时间对应的行中plot。我之前遇到过这种方法的问题。根据matplotlibs文档()构建图例和自定义标签的推荐方法是让人有一种温暖的感觉以及您认为他们所做的确切情节:
...
# Plot several different functions... labels = [] plotHandles = [] for i in range(1, num_plots + 1): x, = plt.plot(some x vector, some y vector) #need the ',' per ** below plotHandles.append(x) labels.append(some label) plt.legend(plotHandles, labels, 'upper left',ncol=1) **:
图(axes)中的每个plot()figure都有自己的颜色循环 - 如果不为每个绘图强制使用不同的颜色,则所有绘图都共享相同的颜色顺序。
只有当我们伸展 "自动"意味着什么时,才能自动实现每个绘图中的不同颜色。
必须使用不同的颜色识别每个绘图,这些颜色应该由[Matplotlib]自动生成。
但是...... Matplotlib会自动为每条不同的曲线生成不同的颜色
In [10]: import numpy as np ...: import matplotlib.pyplot as plt In [11]: plt.plot((0,1), (0,1), (1,2), (1,0)); Out[11]:
你能给我一个方法,在同一个图中为不同的地块添加不同的颜色吗?
它是有道理的,因为每个绘图(每个axes在Matplotlib的用语中)都有自己的color_cycle(或者更确切地说,在2018年,它的prop_cycle),每个plot(axes)以相同的顺序重用相同的颜色。
In [12]: fig, axes = plt.subplots(2,3) In [13]: for ax in axes.flatten(): ...: ax.plot((0,1), (0,1))
如果这是原始问题的含义,一种可能性是为每个图明确命名不同的颜色。
如果在循环中生成绘图(通常发生),我们必须有一个额外的循环变量来覆盖Matplotlib 自动选择的颜色。
In [14]: fig, axes = plt.subplots(2,3) In [15]: for ax, short_color_name in zip(axes.flatten(), 'brgkyc'): ...: ax.plot((0,1), (0,1), short_color_name)
另一种可能性是实例化循环器对象
from cycler import cycler my_cycler = cycler('color', ['k', 'r']) * cycler('linewidth', [1., 1.5, 2.]) actual_cycler = my_cycler() fig, axes = plt.subplots(2,3) for ax in axes.flat: ax.plot((0,1), (0,1), **next(actual_cycler))
请注意,type(my_cycler)是cycler.Cycler,但是type(actual_cycler)是itertools.cycle。
本文以python的matplotlib作图为例,用6种方法解决了同时绘制不同数据曲线的问题。
不仅仅体现了python可视化能力的强大,也对拓宽大家的思路做了一定的尝试。希望大家喜欢。
*请认真填写需求信息,我们会在24小时内与您取得联系。