1、爬蟲入門html
網絡爬蟲(又被稱爲網頁蜘蛛,網絡機器人,在FOAF社區中間,更常常的稱爲網頁追逐者),是一種按照必定的規則,自動地抓取萬維網信息的程序或者腳本。python
運用python3.6中的urllib.requestmysql
1.快速爬取一個網頁 web
(1)get請求方式 sql
#!/usr/bin/env python # -*- coding: UTF-8 -*- # Author:Du Fei import urllib.request # keywd = "python" keywd ="百度" #解決中文編碼問題 keywd=urllib.request.quote(keywd) url = "http://www.baidu.com/s?wd=" +keywd req =urllib.request.Request(url) #urlopen將網頁存到內存 data =urllib.request.urlopen(req).read() fh=open("F:/python/data/douban/2.html","wb") fh.write(data) fh.close()
(2)post請求方式數據庫
#!/usr/bin/env python # -*- coding: UTF-8 -*- # Author:Du Fei #post請求 #登陸模擬 import urllib.request import urllib.parse url ="http://www.iqianyue.com/mypost/" #對字段相應設置 mydata=urllib.parse.urlencode({ "name":"ceo@iqiaa.com", "pass":"123ssd" }).encode("utf-8") req =urllib.request.Request(url,mydata) data =urllib.request.urlopen(req).read() fh =open("F:/python/data/douban/2_1.html","wb") fh.write(data) fh.close()
2.模擬瀏覽器訪問瀏覽器
應用場景:有些網頁爲了防止別人惡意採集其信息因此進行了一些反爬蟲的設置,而咱們又想進行爬取。
解決方法:設置一些Headers
信息(User-Agent
),模擬成瀏覽器去訪問這些網站。服務器
爬取淘寶高清圖片微信
#!/usr/bin/env python # -*- coding: UTF-8 -*- # Author:Du Fei import urllib.request import re keyname="連衣裙" #編碼 key=urllib.request.quote(keyname) #User-Agent :Mozilla/5.0 (Windows NT 10.0; …) Gecko/20100101 Firefox/60.0 #假裝成火狐瀏覽器 headers=("User-Agent","Mozilla /5.0 (Windows NT 10.0; Win64; x6;rv:60.0) Gecko/20100101 Firefox/60.0") #建立opener對象 opener = urllib.request.build_opener() #添加報頭 opener.addheaders=[headers] #將opener添加爲全局 urllib.request.install_opener(opener) for i in range(0,1): #構造網址 url ="https://s.taobao.com/list?spm=a217m.8316598.313651-static.30.3f8533d5oZ7vEf&q="+key+"&cat=50344007&style=grid&seller_type=taobao&bcoffset=12&s=" +str(i*60) data = urllib.request.urlopen(url).read().decode("utf-8", "ingnore") #定義正則 pat = 'pic_url":"//(.*?)"' #圖片網址 image_list=re.compile(pat).findall(data) print(image_list) for j in range(0,len(image_list)): thisimg = image_list[j] thisimg_url ="http://" +thisimg file="F:/python/data/douban/img/" +str(i)+str(j)+".jpg" urllib.request.urlretrieve(thisimg_url,filename=file)
爬取CSDN數據cookie
#!/usr/bin/env python # -*- coding: UTF-8 -*- # Author:Du Fei import urllib.request import re url ="http://blog.csdn.net/" #假裝成瀏覽器 #User-Agent用戶代理 headers=("User-Agent","Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36") #建立opener對象 opener = urllib.request.build_opener() #添加報頭 opener.addheaders=[headers] #將opener添加爲全局 urllib.request.install_opener(opener) #獲取url數據 data =urllib.request.urlopen(url).read().decode("utf-8","ingnore") pat ='<a href="(.*?)" target="_blank" data-track' result=re.compile(pat).findall(data) for i in range(0,len(result)): file = "F:/python/data/douban/csdn/" + str(i) + ".html" urllib.request.urlretrieve(result[i],filename=file) print("第"+str(i)+"爬取成功")
3.異常處理
爬蟲在爬取網站上的數據常見的錯誤:URLError和HTTPError
腳本中加入異常處理機制使爬蟲腳本更穩健。
爬取新浪新聞首頁
#!/usr/bin/env python # -*- coding: UTF-8 -*- # Author:Du Fei """ 需求:將新浪新聞首頁(http://news.sina.com.cn/)全部新聞都爬取到本地 思路:先爬首頁,經過正則獲取全部新聞連接,而後依次爬取新聞,並存儲到本地 """ import urllib.request import urllib.error import re #獲取首頁 #urlopen將網頁存到內存 data =urllib.request.urlopen("http://news.sina.com.cn/").read() #獲取的數據編碼 data2=data.decode("utf-8","ignore") pat ='<a href="(http://news.sina.com.cn/.*?)"' allurl=re.compile(pat).findall(data2) for i in range(0,len(allurl)): try: print("第"+str(i)+"次爬取") this_url=allurl[i] file="F:/python/data/douban/sinanews/" +str(i) + ".html" #網頁下載到本地 urllib.request.urlretrieve(this_url,file) print("---------------成功--------------") except urllib.error.URLError as e: if hasattr(e,"code"): print(e.code) if hasattr(e,"reason"): print(e.reason)
4.代理服務器
(1)使用代理服務器的通常格式
#!/usr/bin/env python # -*- coding: UTF-8 -*- # Author:Du Fei #西祠免費代理IP #http://www.xicidaili.com/ #183.167.217.152 63000 import urllib.request import urllib.error #代理服務器 def use_proxy(url,proxy_addr): try: #代理IP proxy=urllib.request.ProxyHandler({"http":proxy_addr}) #建立opener對象 opener=urllib.request.build_opener(proxy,urllib.request.HTTPHandler) #將opener添加爲全局 urllib.request.install_opener(opener) data=urllib.request.urlopen(url).read().decode("utf-8","ignore") return data except urllib.error.URLError as e: if hasattr(e, "code"): print(e.code) if hasattr(e, "reason"): print(e.reason) proxy_addr="221.228.17.172:8181" url="http://www.baidu.com" data =use_proxy(url,proxy_addr) print(len(data))
(2)微信爬蟲
所謂微信爬蟲,及自動獲取微信的相關文章信息的一種爬蟲。微信對我 們的限制是不少的,因此,咱們須要採起一些手段解決這些限制,主要 包括假裝瀏覽器、使用代理IP等方式
#http://weixin.sogou.com/ import re import urllib.request import time import urllib.error import urllib.request #自定義函數,功能爲使用代理服務器爬一個網址 def use_proxy(proxy_addr,url): #創建異常處理機制 try: req=urllib.request.Request(url) # 添加報頭 req.add_header('User-Agent', 'Mozilla /5.0 (Windows NT 10.0; Win64; x6;rv:60.0) Gecko/20100101 Firefox/60.0') proxy= urllib.request.ProxyHandler({'http':proxy_addr}) # 建立opener對象 opener = urllib.request.build_opener(proxy, urllib.request.HTTPHandler) # 將opener添加爲全局 urllib.request.install_opener(opener) # 獲取req數據 data = urllib.request.urlopen(req).read() return data except urllib.error.URLError as e: if hasattr(e,"code"): print(e.code) if hasattr(e,"reason"): print(e.reason) #若爲URLError異常,延時10秒執行 time.sleep(10) except Exception as e: print("exception:"+str(e)) #若爲Exception異常,延時1秒執行 time.sleep(1) #設置關鍵詞 key="Python" #設置代理服務器,該代理服務器有可能失效,讀者須要換成新的有效代理服務器 # proxy="127.0.0.1:8888" proxy="221.228.17.172:8181" #爬多少頁 for i in range(0,10): key=urllib.request.quote(key) thispageurl="http://weixin.sogou.com/weixin?type=2&query="+key+"&page="+str(i) #a="http://blog.csdn.net" thispagedata=use_proxy(proxy,thispageurl) print(len(str(thispagedata))) pat1='<a href="(.*?)"' rs1=re.compile(pat1,re.S).findall(str(thispagedata)) if(len(rs1)==0): print("這次("+str(i)+"頁)沒成功") continue for j in range(0,len(rs1)): thisurl=rs1[j] thisurl=thisurl.replace("amp;","") file="F:/python/data/weixin/第"+str(i)+"頁第"+str(j)+"篇文章.html" thisdata=use_proxy(proxy,thisurl) try: fh=open(file,"wb") fh.write(thisdata) fh.close() print("第"+str(i)+"頁第"+str(j)+"篇文章成功") except Exception as e: print(e) print("第"+str(i)+"頁第"+str(j)+"篇文章失敗")
5.多線程爬蟲
多線程,即程序中的某些程序段並行執行,合理地設置多線程,可讓爬蟲效率更高。
(1)普通爬蟲(爬取糗事百科)
#!/usr/bin/env python # -*- coding: UTF-8 -*- # Author:Du Fei import urllib.request import re import urllib.error headers=("User-Agent","Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36") opener = urllib.request.build_opener() opener.addheaders=[headers] urllib.request.install_opener(opener) for i in range(1,2): try: #https://www.qiushibaike.com/8hr/page/1/ url="https://www.qiushibaike.com/8hr/page/"+str(i) pagedata=urllib.request.urlopen(url).read().decode("utf-8","ignore") #<div class="content"><span></span></div> pat ='<div class="content">.*?<span>(.*?)</span>.*?</div>' #可能有多行 re.S datalist=re.compile(pat,re.S).findall(pagedata) for j in range(0,len(datalist)): print("第"+str(i)+"頁第"+str(j)+"個段子的內容是:") print(datalist[j]) except urllib.error.URLError as e: if hasattr(e, "code"): print(e.code) if hasattr(e, "reason"): print(e.reason) except Exception as e: print(e) print("第" + str(i) + "頁第" + str(j) + "篇文章失敗")
(2)多線程爬蟲(爬取糗事百科)
#!/usr/bin/env python # -*- coding: UTF-8 -*- # Author:Du Fei import urllib.request import re import urllib.error import threading headers=("User-Agent","Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36") opener = urllib.request.build_opener() opener.addheaders=[headers] urllib.request.install_opener(opener) class One(threading.Thread): #初始化 def __init__(self): #初始化線程 threading.Thread.__init__(self) #線程要作的事情 def run(self): #奇數頁 for i in range(1,36,2): try: # https://www.qiushibaike.com/8hr/page/1/ url = "https://www.qiushibaike.com/8hr/page/" + str(i) pagedata = urllib.request.urlopen(url).read().decode("utf-8", "ignore") # <div class="content"><span></span></div> pat = '<div class="content">.*?<span>(.*?)</span>.*?</div>' # 可能有多行 re.S datalist = re.compile(pat, re.S).findall(pagedata) for j in range(0, len(datalist)): print("第" + str(i) + "頁第" + str(j) + "個段子的內容是:") print(datalist[j]) except urllib.error.URLError as e: if hasattr(e, "code"): print(e.code) if hasattr(e, "reason"): print(e.reason) class Two(threading.Thread): #初始化 def __init__(self): #初始化線程 threading.Thread.__init__(self) #線程要作的事情 def run(self): #偶數頁 for i in range(0,36,2): try: # https://www.qiushibaike.com/8hr/page/1/ url = "https://www.qiushibaike.com/8hr/page/" + str(i) pagedata = urllib.request.urlopen(url).read().decode("utf-8", "ignore") # <div class="content"><span></span></div> pat = '<div class="content">.*?<span>(.*?)</span>.*?</div>' # 可能有多行 re.S datalist = re.compile(pat, re.S).findall(pagedata) for j in range(0, len(datalist)): print("第" + str(i) + "頁第" + str(j) + "個段子的內容是:") print(datalist[j]) except urllib.error.URLError as e: if hasattr(e, "code"): print(e.code) if hasattr(e, "reason"): print(e.reason) one =One() one.start() two=Two() two.start()
2、Scrapy框架
實戰
1.自動模擬登錄豆瓣
(1).douban.py
# -*- coding: utf-8 -*- import scrapy from scrapy.http import Request,FormRequest import urllib.request class DbSpider(scrapy.Spider): name = "db" allowed_domains = ["douban.com"] header={"User-Agent:":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.22 Safari/537.36 SE 2.X MetaSr 1.0"} ''' start_urls = ( 'http://www.douban.com/', ) ''' def start_requests(self): return [Request("https://accounts.douban.com/login",callback=self.parse,meta={"cookiejar":1})] def parse(self, response): captcha=response.xpath("//img[@id='captcha_image']/@src").extract() url="https://accounts.douban.com/login" if len(captcha)>0: print("此時驗證碼") #半自動化驗證碼 #驗證碼下載到本地地址 localpath="F:/python/data/db/captcha.png" urllib.request.urlretrieve(captcha[0],filename=localpath) print("請查看本地驗證碼圖片並輸入驗證碼") captcha_value=input() data={ "form_email": "aaa@163.com", "form_password": "abded", "captcha-solution":captcha_value, "redir":"https://www.douban.com/people/233455/", } else: print("此時沒有驗證碼") data={ "form_email": "aaa@163.com", "form_password": "abded", "redir":"https://www.douban.com/people/233455/", } print("登錄中……") return [FormRequest.from_response(response, meta={"cookiejar": response.meta["cookiejar"]}, headers=self.header, formdata=data, callback=self.next, )] def next(self, response): print("此時已經登錄完成並爬取了我的中心的數據") title = response.xpath("/html/head/title/text()").extract() # note = response.xpath("//div[@class='note']/text()").extract() print(title[0]) # print(note[0])
(2).setting.py
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36'
2.爬取噹噹網數據入Linux中的mysql
(1)items.py
import scrapy class DangdangItem(scrapy.Item): # define the fields for your item here like: # name = scrapy.Field() title= scrapy.Field() link =scrapy.Field() comment=scrapy.Field()
(2)dd.py
# -*- coding: utf-8 -*- import scrapy from dangdang.items import DangdangItem from scrapy.http import Request class DdSpider(scrapy.Spider): name = 'dd' allowed_domains = ['dangdang.com'] start_urls = ['http://dangdang.com/'] def parse(self, response): item=DangdangItem() item["title"]=response.xpath("//a[@name='itemlist-picture']/@title").extract() item["link"]=response.xpath("//a[@name='itemlist-picture']/@href").extract() item["comment"]=response.xpath("//a[@class='search_comment_num']/text()").extract() yield item for i in range(2,5): url="http://category.dangdang.com/pg"+str(i)+"-cp01.54.00.00.00.00.html" yield Request(url,callback=self.parse)
(3)pipelines.py
# -*- coding: utf-8 -*- # Define your item pipelines here # # Don't forget to add your pipeline to the ITEM_PIPELINES setting # See: https://doc.scrapy.org/en/latest/topics/item-pipeline.html import pymysql class DangdangPipeline(object): def process_item(self, item, spider): #鏈接數據庫 conn = pymysql.connect(host='XXXX', port=3306, user='root', passwd='XXX', db='XX', charset='utf8') print(conn) # 建立操做的遊標 cursor = conn.cursor() # 設置字符編碼及自動提交 cursor.execute('set names utf8') # 固定格式 for i in range(0,len(item["title"])): title=item["title"][i] link=item["link"][i] comment=item["comment"][i] # print(title) # print(link) # print(comment) sql = "insert into boods(title,link,comment) values(%s,%s,%s)" cursor.execute(sql, (title, link, comment)) cursor.close() conn.close() return item
(4)setting.py中添加
ROBOTSTXT_OBEY = False ITEM_PIPELINES = { 'dangdang.pipelines.DangdangPipeline': 300, }
3.爬取京東商城商品信息(自動爬取)
建立一個crawl爬蟲,爬取京東的商品信息,而且寫入數據庫中。
(1)建立scrapy項目
scrapy startproject jingdong
(2)常見自動爬取文件
scrapy genspider -t crawl jd jd.com
(3)items.py
# -*- coding: utf-8 -*- # Define here the models for your scraped items # # See documentation in: # https://doc.scrapy.org/en/latest/topics/items.html import scrapy class JingdongItem(scrapy.Item): # define the fields for your item here like: # name = scrapy.Field() #商品id id = scrapy.Field() #商品名 title = scrapy.Field() #商品所在商店名 shop = scrapy.Field() # 商品所在商店連接 shoplink = scrapy.Field() #商品價格 price = scrapy.Field() #商品好評 comment = scrapy.Field()
(4)jd.py
# -*- coding: utf-8 -*- import scrapy from scrapy.linkextractors import LinkExtractor from scrapy.spiders import CrawlSpider, Rule from jingdong.items import JingdongItem import re import urllib.request #自動爬蟲 class JdSpider(CrawlSpider): name = 'jd' allowed_domains = ['jd.com'] start_urls = ['http://jd.com/'] rules = ( Rule(LinkExtractor(allow=''), callback='parse_item', follow=True), ) def parse_item(self, response): try: #實例化容器 i = JingdongItem() #獲取當前頁 thisurl = response.url pat ="item.jd.com/(.*?).html" #在thisurl中查找有沒有pat這樣格式的表達式 x=re.search(pat,thisurl) if(x): #獲取商品的id thisid=re.compile(pat).findall(thisurl)[0] #標題 title=response.xpath("//div[@id='spec-n1']/img[@id='spec-img']/@alt").extract() #商家 shop=response.xpath("//div[@class='name']/a/text()").extract() #商家鏈接 shoplink=response.xpath("//div[@class='name']/a/@href").extract() #價格url priceurl ="https://c0.3.cn/stock?skuId="+str(thisid)+"&area=1_72_2799_0&venderId=1000000904&cat=9987,653,655&buyNum=1&choseSuitSkuIds=&extraParam={%22originid%22:%221%22}&ch=1&fqsp=0&pduid=248862164&pdpin=&detailedAdd=null&callback=jQuery6703843" #好評url commenturl ="https://club.jd.com/comment/productCommentSummaries.action?referenceIds="+str(thisid)+"&callback=jQuery1884180&_=1533995028715" #將價格網頁存到內存 pricedata=urllib.request.urlopen(priceurl).read().decode("utf-8","ignore") # 將好評網頁存到內存 commentdata=urllib.request.urlopen(commenturl).read().decode("utf-8","ignore") pricepat='"p":"(.*?)"' commentpat='"GoodRateShow":(.*?),' price=re.compile(pricepat).findall(pricedata) comment = re.compile(commentpat).findall(commentdata) #爬取每一個字段都有值得商品信息 if(len(title) and len(shop) and len(shoplink) and len(price) and len(comment)): i["id"] =thisid i["title"] =title i["shop"] =shop i["shoplink"]=shoplink i["price"]=price i["comment"]=comment else: pass else: pass return i except Exception as e: print(e)
(5)pipelines.py
# -*- coding: utf-8 -*- # Define your item pipelines here # # Don't forget to add your pipeline to the ITEM_PIPELINES setting # See: https://doc.scrapy.org/en/latest/topics/item-pipeline.html import pymysql # class JingdongPipeline(object): # def process_item(self, item, spider): # print(item["id"]) # print(item["title"][0]) # print(item["shop"][0]) # print(item["shoplink"][0]) # print(item["price"][0]) # print(item["comment"][0]) # print("-----------------") # return item class JingdongPipeline(object): def process_item(self, item, spider): #鏈接數據庫 conn = pymysql.connect(host='xxxxx', port=3306, user='root', passwd='xxxx', db='xxxx', charset='utf8') print(conn) # 建立操做的遊標 cursor = conn.cursor() # 設置字符編碼及自動提交 cursor.execute('set names utf8') # 固定格式 id=item["id"] title=item["title"][0] shop=item["shop"][0] shoplink=item["shoplink"][0] price=item["price"][0] comment=item["comment"][0] sql = "insert into jd(id,title,shop,shoplink,price,comment) values(%s,%s,%s,%s,%s,%s)" cursor.execute(sql,(id,title,shop,shoplink,price,comment)) cursor.close() conn.close() return item
(6)settings.py
# -*- coding: utf-8 -*- # Scrapy settings for jingdong project # # For simplicity, this file contains only settings considered important or # commonly used. You can find more settings consulting the documentation: # # https://doc.scrapy.org/en/latest/topics/settings.html # https://doc.scrapy.org/en/latest/topics/downloader-middleware.html # https://doc.scrapy.org/en/latest/topics/spider-middleware.html BOT_NAME = 'jingdong' SPIDER_MODULES = ['jingdong.spiders'] NEWSPIDER_MODULE = 'jingdong.spiders' # Crawl responsibly by identifying yourself (and your website) on the user-agent #USER_AGENT = 'jingdong (+http://www.yourdomain.com)' # Obey robots.txt rules ROBOTSTXT_OBEY = True # Configure maximum concurrent requests performed by Scrapy (default: 16) #CONCURRENT_REQUESTS = 32 # Configure a delay for requests for the same website (default: 0) # See https://doc.scrapy.org/en/latest/topics/settings.html#download-delay # See also autothrottle settings and docs #DOWNLOAD_DELAY = 3 # The download delay setting will honor only one of: #CONCURRENT_REQUESTS_PER_DOMAIN = 16 #CONCURRENT_REQUESTS_PER_IP = 16 # Disable cookies (enabled by default) #COOKIES_ENABLED = False # Disable Telnet Console (enabled by default) #TELNETCONSOLE_ENABLED = False # Override the default request headers: #DEFAULT_REQUEST_HEADERS = { # 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', # 'Accept-Language': 'en', #} # Enable or disable spider middlewares # See https://doc.scrapy.org/en/latest/topics/spider-middleware.html #SPIDER_MIDDLEWARES = { # 'jingdong.middlewares.JingdongSpiderMiddleware': 543, #} # Enable or disable downloader middlewares # See https://doc.scrapy.org/en/latest/topics/downloader-middleware.html #DOWNLOADER_MIDDLEWARES = { # 'jingdong.middlewares.JingdongDownloaderMiddleware': 543, #} # Enable or disable extensions # See https://doc.scrapy.org/en/latest/topics/extensions.html #EXTENSIONS = { # 'scrapy.extensions.telnet.TelnetConsole': None, #} # Configure item pipelines # See https://doc.scrapy.org/en/latest/topics/item-pipeline.html ITEM_PIPELINES = { 'jingdong.pipelines.JingdongPipeline': 300, } # Enable and configure the AutoThrottle extension (disabled by default) # See https://doc.scrapy.org/en/latest/topics/autothrottle.html #AUTOTHROTTLE_ENABLED = True # The initial download delay #AUTOTHROTTLE_START_DELAY = 5 # The maximum download delay to be set in case of high latencies #AUTOTHROTTLE_MAX_DELAY = 60 # The average number of requests Scrapy should be sending in parallel to # each remote server #AUTOTHROTTLE_TARGET_CONCURRENCY = 1.0 # Enable showing throttling stats for every response received: #AUTOTHROTTLE_DEBUG = False # Enable and configure HTTP caching (disabled by default) # See https://doc.scrapy.org/en/latest/topics/downloader-middleware.html#httpcache-middleware-settings #HTTPCACHE_ENABLED = True #HTTPCACHE_EXPIRATION_SECS = 0 #HTTPCACHE_DIR = 'httpcache' #HTTPCACHE_IGNORE_HTTP_CODES = [] #HTTPCACHE_STORAGE = 'scrapy.extensions.httpcache.FilesystemCacheStorage'
自主學習Python數據分析與數據挖掘中爬蟲入門總結。
參考網上教程:https://www.hellobi.com/