扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
方法/步骤
创新互联建站,专注为中小企业提供官网建设、营销型网站制作、响应式网站设计、展示型网站建设、网站制作等服务,帮助中小企业通过网站体现价值、有效益。帮助企业快速建站、解决网站建设与网站营销推广问题。
在做爬取数据之前,你需要下载安装两个东西,一个是urllib,另外一个是python-docx。
请点击输入图片描述
然后在python的编辑器中输入import选项,提供这两个库的服务
请点击输入图片描述
urllib主要负责抓取网页的数据,单纯的抓取网页数据其实很简单,输入如图所示的命令,后面带链接即可。
请点击输入图片描述
抓取下来了,还不算,必须要进行读取,否则无效。
请点击输入图片描述
5
接下来就是抓码了,不转码是完成不了保存的,将读取的函数read转码。再随便标记一个比如XA。
请点击输入图片描述
6
最后再输入三句,第一句的意思是新建一个空白的word文档。
第二句的意思是在文档中添加正文段落,将变量XA抓取下来的东西导进去。
第三句的意思是保存文档docx,名字在括号里面。
请点击输入图片描述
7
这个爬下来的是源代码,如果还需要筛选的话需要自己去添加各种正则表达式。
关于知乎验证码登陆的问题,用到了Python上一个重要的图片处理库PIL,如果不行,就把图片存到本地,手动输入。
通过对知乎登陆是的抓包,可以发现登陆知乎,需要post三个参数,一个是账号,一个是密码,一个是xrsf。
这个xrsf隐藏在表单里面,每次登陆的时候,应该是服务器随机产生一个字符串。所有,要模拟登陆的时候,必须要拿到xrsf。
用chrome (或者火狐 httpfox 抓包分析)的结果:
所以,必须要拿到xsrf的数值,注意这是一个动态变化的参数,每次都不一样。
拿到xsrf,下面就可以模拟登陆了。
使用requests库的session对象,建立一个会话的好处是,可以把同一个用户的不同请求联系起来,直到会话结束都会自动处理cookies。
注意:cookies 是当前目录的一个文件,这个文件保存了知乎的cookie,如果是第一个登陆,那么当然是没有这个文件的,不能通过cookie文件来登陆。必须要输入密码。
这是登陆的函数,通过login函数来登陆,post 自己的账号,密码和xrsf 到知乎登陆认证的页面上去,然后得到cookie,将cookie保存到当前目录下的文件里面。下次登陆的时候,直接读取这个cookie文件。
这是cookie文件的内容
以下是源码:
运行结果:
反爬虫最基本的策略:
爬虫策略:
这两个都是在http协议的报文段的检查,同样爬虫端可以很方便的设置这些字段的值,来欺骗服务器。
反爬虫进阶策略:
1.像知乎一样,在登录的表单里面放入一个隐藏字段,里面会有一个随机数,每次都不一样,这样除非你的爬虫脚本能够解析这个随机数,否则下次爬的时候就不行了。
2.记录访问的ip,统计访问次数,如果次数太高,可以认为这个ip有问题。
爬虫进阶策略:
1.像这篇文章提到的,爬虫也可以先解析一下隐藏字段的值,然后再进行模拟登录。
2.爬虫可以使用ip代理池的方式,来避免被发现。同时,也可以爬一会休息一会的方式来降低频率。另外,服务器根据ip访问次数来进行反爬,再ipv6没有全面普及的时代,这个策略会很容易造成误伤。(这个是我个人的理解)。
通过Cookie限制进行反爬虫:
和Headers校验的反爬虫机制类似,当用户向目标网站发送请求时,会再请求数据中携带Cookie,网站通过校验请求信息是否存在Cookie,以及校验Cookie的值来判定发起访问请求的到底是真实的用户还是爬虫,第一次打开网页会生成一个随机cookie,如果再次打开网页这个Cookie不存在,那么再次设置,第三次打开仍然不存在,这就非常有可能是爬虫在工作了。
反爬虫进进阶策略:
1.数据投毒,服务器在自己的页面上放置很多隐藏的url,这些url存在于html文件文件里面,但是通过css或者js使他们不会被显示在用户看到的页面上面。(确保用户点击不到)。那么,爬虫在爬取网页的时候,很用可能取访问这个url,服务器可以100%的认为这是爬虫干的,然后可以返回给他一些错误的数据,或者是拒绝响应。
爬虫进进阶策略:
1.各个网站虽然需要反爬虫,但是不能够把百度,谷歌这样的搜索引擎的爬虫给干了(干了的话,你的网站在百度都说搜不到!)。这样爬虫应该就可以冒充是百度的爬虫去爬。(但是ip也许可能被识破,因为你的ip并不是百度的ip)
反爬虫进进进阶策略:
给个验证码,让你输入以后才能登录,登录之后,才能访问。
爬虫进进进阶策略:
图像识别,机器学习,识别验证码。不过这个应该比较难,或者说成本比较高。
参考资料:
廖雪峰的python教程
静觅的python教程
requests库官方文档
segmentfault上面有一个人的关于知乎爬虫的博客,找不到链接了
本来是想爬取之后作最佳羁绊组合推算,但是遇到知识点无法消化(知识图谱),所以暂时先不组合了,实力有限
库的安装
1.requests #爬取棋子数据
2.json #棋子数据为js动态,需使用json解析
3.BeautifulSoup
实战前先新建个lol文件夹作为工作目录,并创建子目录data,用于存放数据。
1.爬取数据,新建个py文件,用于爬取云顶数据,命名为data.py
1.1定义个req函数,方便读取。//需设定编码格式,否则会出现乱码
def Re_data(url):
re = requests.get(url)
re.encoding = 'gbk'
data = json.loads(re.text)
return data['data']
1.2定义个Get函数,用于读取数据并使用保存函数进行保存数据,保存格式为json。
def Get_data():
# 获取数据并保存至data目录
base_url = ''
chess = Re_data(base_url + 'chess.js')
race = Re_data(base_url + 'race.js')
job = Re_data(base_url + 'job.js')
equip = Re_data(base_url + 'equip.js')
Save_data(chess,race,job,equip)
1.3定义save函数实现读取的数据进行文件保存,保存目录为工作目录下的data文件夹。
def Save_data(t_chess,t_race,t_job,t_equip):
with open('./data/chess.json','w') as f:
json.dump(t_chess,f,indent='\t')
with open('./data/race.json','w') as f:
json.dump(t_race,f,indent='\t')
with open('./data/job.json','w') as f:
json.dump(t_job,f,indent='\t')
with open('./data/equip.json','w') as f:
json.dump(t_equip,f,indent='\t')
1.4定义主函数main跑起来
if __name__ == '__main__':
start = time.time()
Get_data()
print('运行时间:' + str(time.time() - start) + '秒')
至此,数据爬取完成。
2.种族和职业进行组合。
2.1未完成 //未完成,使用穷举方法进行组合会出现内存不够导致组合失败(for循环嵌套导致数组内存超限)
//待学习,使用知识图谱建立组合优选,可参考:
期间遇到的问题:
1.爬取棋子数据时为动态js加载,需通过json模块的loads方法获取
2.3层for循环嵌套数据量大,导致计算失败,需优化计算方法。
一、爬取我们所需要的一线链接
channel_extract.py
这里的一线链接也就是我们所说的大类链接:
from bs4 import BeautifulSoupimport requests
start_url = ''host_url = ''def get_channel_urls(url):
wb_data = requests.get(url)
soup = BeautifulSoup(wb_data.text, 'lxml')
links = soup.select('.fenlei dt a') #print(links)
for link in links:
page_url = host_url + link.get('href')
print(page_url)#get_channel_urls(start_url)channel_urls = '''
'''123456789101112131415161718192021222324252627282930313233343536
那么拿我爬取的58同城为例就是爬取了二手市场所有品类的链接,也就是我说的大类链接;
找到这些链接的共同特征,用函数将其输出,并作为多行文本储存起来。
二、获取我们所需要的详情页面的链接和详情信息
page_parsing.py
1、说说我们的数据库:
先看代码:
#引入库文件from bs4 import BeautifulSoupimport requestsimport pymongo #python操作MongoDB的库import reimport time#链接和建立数据库client = pymongo.MongoClient('localhost', 27017)
ceshi = client['ceshi'] #建ceshi数据库ganji_url_list = ceshi['ganji_url_list'] #建立表文件ganji_url_info = ceshi['ganji_url_info']123456789101112
2、判断页面结构是否和我们想要的页面结构相匹配,比如有时候会有404页面;
3、从页面中提取我们想要的链接,也就是每个详情页面的链接;
这里我们要说的是一个方法就是:
item_link = link.get('href').split('?')[0]12
这里的这个link什么类型的,这个get方法又是什么鬼?
后来我发现了这个类型是
class 'bs4.element.Tab1
如果我们想要单独获取某个属性,可以这样,例如我们获取它的 class 叫什么
print soup.p['class']
#['title']12
还可以这样,利用get方法,传入属性的名称,二者是等价的
print soup.p.get('class')#['title']12
下面我来贴上代码:
#爬取所有商品的详情页面链接:def get_type_links(channel, num):
list_view = '{0}o{1}/'.format(channel, str(num)) #print(list_view)
wb_data = requests.get(list_view)
soup = BeautifulSoup(wb_data.text, 'lxml')
linkOn = soup.select('.pageBox') #判断是否为我们所需页面的标志;
#如果爬下来的select链接为这样:div.pageBox ul li:nth-child(1) a span 这里的:nth-child(1)要删掉
#print(linkOn)
if linkOn:
link = soup.select('.zz .zz-til a')
link_2 = soup.select('.js-item a')
link = link + link_2 #print(len(link))
for linkc in link:
linkc = linkc.get('href')
ganji_url_list.insert_one({'url': linkc})
print(linkc) else: pass1234567891011121314151617181920
4、爬取详情页中我们所需要的信息
我来贴一段代码:
#爬取赶集网详情页链接:def get_url_info_ganji(url):
time.sleep(1)
wb_data = requests.get(url)
soup = BeautifulSoup(wb_data.text, 'lxml') try:
title = soup.select('head title')[0].text
timec = soup.select('.pr-5')[0].text.strip()
type = soup.select('.det-infor li span a')[0].text
price = soup.select('.det-infor li i')[0].text
place = soup.select('.det-infor li a')[1:]
placeb = [] for placec in place:
placeb.append(placec.text)
tag = soup.select('.second-dt-bewrite ul li')[0].text
tag = ''.join(tag.split()) #print(time.split())
data = { 'url' : url, 'title' : title, 'time' : timec.split(), 'type' : type, 'price' : price, 'place' : placeb, 'new' : tag
}
ganji_url_info.insert_one(data) #向数据库中插入一条数据;
print(data) except IndexError: pass123456789101112131415161718192021222324252627282930
四、我们的主函数怎么写?
main.py
看代码:
#先从别的文件中引入函数和数据:from multiprocessing import Poolfrom page_parsing import get_type_links,get_url_info_ganji,ganji_url_listfrom channel_extract import channel_urls#爬取所有链接的函数:def get_all_links_from(channel):
for i in range(1,100):
get_type_links(channel,i)#后执行这个函数用来爬取所有详情页的文件:if __name__ == '__main__':# pool = Pool()# # pool = Pool()# pool.map(get_url_info_ganji, [url['url'] for url in ganji_url_list.find()])# pool.close()# pool.join()#先执行下面的这个函数,用来爬取所有的链接:if __name__ == '__main__':
pool = Pool()
pool = Pool()
pool.map(get_all_links_from,channel_urls.split())
pool.close()
pool.join()1234567891011121314151617181920212223242526
五、计数程序
count.py
用来显示爬取数据的数目;
import timefrom page_parsing import ganji_url_list,ganji_url_infowhile True: # print(ganji_url_list.find().count())
# time.sleep(5)
print(ganji_url_info.find().count())
time.sleep(5)
我们在一些没有反爬虫机制的生物网站上,可以利用Python做一些“省力”的事情,比方说ID的转换
我们以uniprot为例,进入它的转换页面 传送门 ,页面:
这里介绍下 urllib 这个Python库,该库功能非常强大,可以爬取动态网页
根据这个思路,我们看看该网站的网页结构:
url 为ID转换的网址,params是你要爬取的内容,存储为字典形式,那么字典的键值代表HTML表单(form)里面 name 的内容:
比方说 from:
字典的键值与form的name标签的内容对应
to也是一样的:
至于 "format": "tab" 是指我们把爬下来的网页转换为 tab 格式
当然,这招适用于表单提交的爬虫,如果爬取的内容过多,不妨写个函数:
参考: 传送门
在if 里只需要yield "" + item_url.attrs['href']
然后Lsit(最好改可名,在python规范里,函数命名是全小写,而list又是保留字,比如改为display_hrefs)只需要循环输出getUrl的结果就好:
def getUrl(url: str):
....html = urlopen(url)
....for item_url in BeautifulSoup((html.read()).find ('div' , class_='AAA').findAll ("a"):
........if 'href' in item_url.attrs:
............yield "" + item_url.attrs['href']
def display_hrefs(url: str):
....for href in getUrl(url):
........print(href)
if __name__ == '__main__':
....display_hrefs("")
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流