目录css
本篇为技术篇,,会讲解各类爬虫库的使用,至于库的安装在安装篇已经介绍了html
这种状况是网页没有设置编码,获取不到,因此使用了默认的编码,这个时候中文就会出现乱码的状况python
只须要多加一行代码便可git
response.encoding='gb2312'
免费的代理我试着不行,暂时不研究了,写一下付费的代理是怎么使用的github
我购买的是讯代理,购买以后先在白名单里面添加本身的IP,而后点击生成APIweb
选择订单,选择一个城市,而后生成jsonmongodb
接下来使用Python获取代理IP,我是获取了以后存到数据库了chrome
import pyodbc import json import requests import sys import time headers = { 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac 0S X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko)Chrome/52.0.2743.116 Safari/537.36'} conn = pyodbc.connect('DRIVER={SQL Server};SERVER=192.168.3.8,1433;DATABASE=VaeDB;UID=sa;PWD=test123') cursor = conn.cursor() r = requests.get('http://apXXXXXXXXXXXXXXXXXXXXX40300', headers=headers) print(r.text) jsonobj = json.loads(str(r.text)) datetime=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) cursor.execute( 'update ProxyIP set IP=?,UpdateDate=? where Id=1', (jsonobj['RESULT'][0]['ip']+':'+jsonobj['RESULT'][0]['port'],datetime)) conn.commit() sys.exit()
怎么使用代理,这个分为好几个状况,我使用的是Selenium,就写这个,requests的用到再补充数据库
conn = pyodbc.connect( 'DRIVER={SQL Server};SERVER=111.108.8.2,1433;DATABASE=VaeDB;UID=sa;PWD=testxxxx') cursor = conn.cursor() cursor.execute(""" select IP from dbo.ProxyIP """ ) data = cursor.fetchone() proxyip=str(data[0]) chrome_options=webdriver.ChromeOptions() chrome_options.add_argument('--proxy-server=http://'+ proxyip) browser = webdriver.Chrome(chrome_options=chrome_options)
我使用BeautifulSoup爬取了好几万的数据了,对于普通的网站,BeautifulSoup真的很好用json
#BeautifulSoup初始化能够自动更正HTML格式,补全没有闭合的元素 print (soup.prettify())#以标准的缩进格式输出 print(soup.title)#标题 print(soup.title.string)#标题里面的内容 print(soup.title.name)#title的节点名称,就是title print(soup.p)#第一个p元素的内容 print(soup.p.attrs)#第一个p元素的全部属性和值 print(soup.p['class'])#第一个p元素class属性的值 print(soup.p['name'])#第一个p元素name属性的值 print(soup.p.b.string)#第一个p标签下的b标签的文本内容 print(soup.p.contents)#第一个p元素下的全部子节点,不包括孙子节点 #第一个p元素全部的子节点 print(soup.p.descendants) for i,child in enumerate(soup.p.descendants): print(i,child) print(soup.p.parent)#第一个p元素的父节点 #第一个p元素全部的父节点 print(soup.p.parents) print(list(enumerate(soup.p.parents))) print(soup.p.next_sibling)#第一个p元素的下一个兄弟节点,注意有回车的时候要写两个next_sibling print(list(enumerate(soup.p.next_siblings)))#第一个p元素后面的全部兄弟节点 print(soup.p.previous_sibling)#第一个p元素的上一个兄弟节点 print(list(enumerate(soup.p.previous_siblings)))#第一个p元素前面的全部兄弟节点 ######################################################### #下面这些是比较经常使用的,上面的了解一下便可 # 判断某个标签是否有属性,例如img标签有一个alt属性,有时候img没有alt属性,我就能够判断一下,不然出错 if img.attrs.get('alt'): soup.find(id='text-7').find_all(name='li') #根据文本查找到该标签 # 例以下面的,根据Description查找含有Description的第一个p元素 test = soup.find(lambda e: e.name == 'p' and 'Description' in e.text) # 其实若是是直接子元素的话,也可使用parent,可是这个不多用,适用状况很少 test= soup.find(text=re.compile('Description')).parent #查找某个属性为包含的标签 #标签的属性有不少值,例如img标签的alt属性,有item和img两个值,能够经过以下查找 noscript.find_all('img',attrs={'alt':re.compile('item')}) #判断属性里面是否有某个值 if 'Datasheet' in img['alt']: #替换全部的br换行符号 html = get_one_page(url) return html.replace('<br>', '').replace('<br />', '').replace('<br/>', '') #去除最后一个逗号 datasheet_url.rstrip(',') #去除关键字和空格,只要后面的内容 #例如 Function : Sensitive Gate Silicon Controlled Rectifiers #获得的就是Sensitive Gate Silicon Controlled Rectifiers return re.sub(keywords+'.*?[\s]:.*?[\s]', '', child.find(text=re.compile(keywords)).string) #返回某个符号以前的字符 import re text="K6X4008C1F-BF55 ( 32-SOP, 55ns, LL )" b=re.search('^[^\(]*(?=\()',text,re.M) if b: print(b.group(0)) print(len(b.group(0))) else: print('没有') #关键地方是,这里是匹配的( 括号须要\来转义一下 ^[^\(]*(?=\() #若是是逗号,能够写 ^[^,]*(?=,) #若是是单词,好比我想匹配Vae这个单词,以下 text='XuSong Vae hahaha' text2='VV Vae hahaha' b=re.search('^[^Vae]*(?=Vae)',text,re.M) #这个例子很重要,text是能够正则出XuSong的,可是下面的VV就正则不出来了,由于^是后面的Vae的任意一个单词,只要前面包含就不行,VV包含了V,因此就不行了,我尝试着给Vae加括号,也不行.而后我就想了一个办法,把Vae替换成逗号之类的符号不就能够了,只要是一个字符就行,以下 text='XuSong Vae hahaha' text2='VV Vae hahaha' b=re.search('^[^,]*(?=,)',text.replace('Vae',','),re.M) #一段HTML元素中去除a标签,可是保留a标签的值 return re.sub('(<\/?a.*?>)', '', description_element) #有时候想获取一段HTML元素内容,由于有的排版在,好比ul和li元素,排版是在的,若是使用text就是一串文本,换行都没了,能够这样 str(child.find(class_='ul2')) #获取到这段HTML元素以后,使用str函数变成字符串便可 #下一个兄弟元素最好使用find_next_sibling() #等待验证,和next_sibling比较一下再说 验证完毕,我来说一下find_next_sibling()和next_sibling的区别 若是想要后面的元素的话,写find_next_sibling() 若是想要后面的内容的话,写next_sibling 例如 <a>111</a><p>222</p> 想要获取p元素应该使用find_next_sibling() <a>111</a>我是文本 想要获取 我是文本 应该使用next_sibling #Python爬虫数据插入到MongoDB import pymongo client = pymongo.MongoClient("mongodb://admin:test123@192.168.3.80:27017/") db = client.datasheetcafe collection = db.datasheetcafe collection.insert_one(message)
在爬取一个新网站的时候,我发现网站上的网页数据全都是动态加载的,浏览器加载以后数据才会显示,这个时候BeautifulSoup就没用了,彻底获取不到HTML节点
这种状况,可使用Selenium进行动态加载,我使用这个已经爬取了近200万的数据
#有不显示浏览器的,可是我选择了Chrome浏览器 browser = webdriver.Chrome() #先获取url,再选择元素 browser.get(url) div = browser.find_element_by_css_selector('.information') #find_element_by_css_selector这个东西是css选择器,若是选择一个就使用这个,想要选择一堆就加个s,使用find_elements_by_css_selector #后面的类就是. id就是# 标签名就直接写,以下 table = browser.find_element_by_css_selector('#part-specs') table.find_elements_by_css_selector('tr') # 获取属性的值 tr.get_attribute('class') #对了,下面这个获取的可不是HTML元素,是一个WebElement元素 table = browser.find_element_by_css_selector('#part-specs') #因此若是你想要HTML元素这样写 table = browser.find_element_by_css_selector('#part-specs').get_attribute('outerHTML') #获取里面的文本值就这样写 browser.find_element_by_css_selector('.part-number').text #至于怎么判断元素是否存在的,我写了if可是没有,因此我利用try catch帮助解决 try: button=browser.find_element_by_css_selector('#show-secondary-part-list') button.click() except Exception as e: print('没有这个元素')
有时候Selenium加载一个网页时间过长了,因此必须设定一个超时时间
browser = webdriver.Chrome() browser.set_page_load_timeout(20) browser.set_script_timeout(20) try: browser.get(address) except TimeoutException: browser.execute_script('window.stop()') div = browser.find_element_by_css_selector('.information') ....
先设定加载时间为20秒,若是20都没加载出来,就算了,直接中止加载,爬取网页内容吧,若是一个HTML元素都没抓取到,空白页面,那就try catch跳过这个网页
默认使用Chrome是加载出来的,也能够隐藏Chrome浏览器,那个无界面PhantomJS已经被淘汰了
chrome_options=webdriver.ChromeOptions() # chrome_options.add_argument('--headless') 若是想不弹出chrome浏览器就开启这两行,那个PantomJS啥的已通过期了 # chrome_options.add_argument('--disable-gpu') chrome_options.add_argument('--proxy-server=http://'+ proxyip) chrome_options.add_experimental_option('excludeSwitches', ['enable-automation']) #这一行是为了防止网站识别出我是selenium,参考:https://zhuanlan.zhihu.com/p/65077940 browser = webdriver.Chrome(chrome_options=chrome_options)
个人爬虫爬了一段时间就中止了,selenium控制的浏览器要么变成了空白页,要么访问失败,最可怕的是页面卡着不动了,这个时候只能重启爬虫程序了,因此我把爬虫发布成exe了,我使用Windows自带的计划任务,隔一段时间就启动exe爬虫,而后问题来了
我必须关闭exe的弹窗,否则加载愈来愈多的exe,内存会崩的,因而我采用了Python多进程
一个进程去爬虫,一个进程去计时,若是计时10分钟,就退出exe
可是没有执行,不管我使用sys.exit()仍是os._exit()都没法退出exe,至今不知道为何
没办法只好采起了另一种方法,杀进程
import os os.system('taskkill /im conhost.exe /F') # 这两个不能同时执行,我写了两个py,发布两个exe执行 os.system('taskkill /im chromedriver.exe /F') os.system('taskkill /im chrome.exe /F')
我把控制台和Chrome全杀了.......这样Windows计划任务会重启exe,而后过10分钟我再全杀了.....
对了,Win10的计划任务也搞了我很久,就是不成功,详情见Windows计划任务
暂留......
scrapy startproject tutorial
scrapy genspider quotes quotes.toscrape.com
scrapy crawl quotes
爬虫小Demo应该不会再更新了,我爬取的东西不可能写出来了,仅仅介绍技术,授人以渔吧
import requests import re headers = {'User-Agent' : 'Mozilla/5.0 (Macintosh; Intel Mac 0S X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko)Chrome/52.0.2743.116 Safari/537.36'} r =requests.get("https://www.zhihu.com/explore", headers=headers) pattern = re.compile('explore-feed.*?question_link.*?>(.*?)</a>', re.S) titles = re.findall(pattern,r.text) print(titles)
讲解:headers里面有浏览器标识,不加这个知乎会禁止抓取
import requests import re headers = {'User-Agent' : 'Mozilla/5.0 (Macintosh; Intel Mac 0S X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko)Chrome/52.0.2743.116 Safari/537.36'} r =requests.get("https://avatars0.githubusercontent.com/u/13572737?s=460&v=4", headers=headers) with open('Vae.jpg','wb') as f: f.write(r.content)
这个不只能够爬取图片,爬取视频,音频,也是这样的
==注意:爬取图片的时候,不写headers会报错,找不到源==
下面是把图片保存到制定位置的代码,多了一个判断文件夹是否存在,不存在就建立文件夹的操做,我是根据图片的连接截取做为文件夹的名称的,使用建立文件夹的os须要导入os
import os def get_allpath(imgurl): info=imgurl[imgurl.index('uploads'):] infos=info.split('/') return infos[0]+"\\"+infos[1]+infos[2]+"\\"+infos[3] def get_path(imgurl): info=imgurl[imgurl.index('uploads'):] infos=info.split('/') return infos[0]+"\\"+infos[1]+infos[2] def create_makedirs(dirpath): if not os.path.exists(dirpath): os.makedirs(dirpath) def get_image(child, path): for img in child.find_all(name='img'): imgurl = img.attrs.get('data-lazy-src') if imgurl: if 'gif' in imgurl: create_makedirs(path+get_path(imgurl)) r = requests.get(imgurl,headers=headers) with open(path+get_allpath(imgurl), 'wb') as f: f.write(r.content) #最后我在调用的时候,直接输入放到哪里的路径便可 path = 'D:\\datasheetcafe\\' get_image(child, path)
其实和爬取图片是同样的,只不过换了url而已,这里以爬取个人哔哩哔哩视频为例
如图是个人哔哩哔哩发的一个视频,点击F12,而后在NetWork里面找到视频的那个请求,通常是最大Size的那个
点进去,看到的那一串就是视频地址
复制视频地址到python爬虫里面,改一下存储为.mp4
import requests import re headers = {'User-Agent' : 'Mozilla/5.0 (Macintosh; Intel Mac 0S X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko)Chrome/52.0.2743.116 Safari/537.36'} r =requests.get("https://113-219-141-2.ksyungslb.com/upos-sz-mirrorks32u.acgvideo.com/upgcxcode/63/76/19157663/19157663-1-48.mp4?e=ig8euxZM2rNcNbKVhwdVhoMMhwdVhwdEto8g5X10ugNcXBlqNxHxNEVE5XREto8KqJZHUa6m5J0SqE85tZvEuENvNC8xNEVE9EKE9IMvXBvE2ENvNCImNEVEK9GVqJIwqa80WXIekXRE9IMvXBvEuENvNCImNEVEua6m2jIxux0CkF6s2JZv5x0DQJZY2F8SkXKE9IB5QK==&deadline=1562826409&gen=playurl&nbs=1&oi=1947754487&os=ks3u&platform=pc&trid=28dcba5166d84f6f8b078fccbdd41f2e&uipk=5&upsig=cae257a7f3504f28137a3036304288df&uparams=e,deadline,gen,nbs,oi,os,platform,trid,uipk&mid=32059965&ksy_gslb_referer=https%3A%2F%2Fwww.bilibili.com%2Fvideo%2Fav11592898", headers=headers) with open('Vae.mp4','wb') as f: f.write(r.content)
这个网站是这样的,他的信息是js动态加上去的,并且必须登陆以后才能看到数据
因此我使用BeautifulSoup在线爬不行,我不会
使用了Selenium登陆了,也动态加载页面了,数据也出来了,可是这个网站特别的不规则,
都没有class,我很差找规律,也是不会写......
大佬给我提出个办法,由于这个网站的页面很少,也就20几个,让我直接保存到本地,而后读取本地的html爬虫,这样就可使用BeautifulSoup了,不错哦
我直接在网页上按下了ctrl+s,保存到了本地.........
注意啊!! ctrl+s保存的网页仍是没有数据的啊,仍是须要js加载的啊......我忙活了半天,白忙活了
大佬得知此事以后,痛心疾首,说我早就和你说了,复制DOM就能够了,你不听 🐷
对此我只能说,我是🐷,我是🐷,我是🐷
正确的作法是,选择这该死的DOM,右键,复制HTML,这样他的数据啥的,全都有
我是一个一个复制了,而后保存到个人本地html了
若是是不少的话,成百上千的网页,这样就不适合手动了,可使用Selenium加载以后保存到本地
我不会放出全部的,写写重点
首先要安装一个爬本地HTML的包
pip install requests-file
from requests_file import FileAdapter def get_one_page(file_name): s = requests.Session() s.mount('file://', FileAdapter()) html = s.get(f'file:///D:/'+file_name+'.html') soup = BeautifulSoup(html, 'lxml') ...省略...