python+request+lxml的几个例子

解析163新闻列表的例子: 

Python代码 

 收藏代码

  1. #!/usr/bin/python  
  2. # encoding=gbk  
  3.   
  4. # 我只是尝试遍历新闻而已,只有有很多链接博客,主题之类的没有操作  
  5. # 如果要实现,就自己判断url来分析到底是什么,然后做相应的处理  
  6.   
  7. import sys  
  8. import requests  
  9. import datetime  
  10. import time  
  11. import MySQLdb  
  12.   
  13. import chardet  
  14.   
  15. import lxml.html.soupparser as soupparser  
  16. import lxml.etree as etree  
  17.   
  18. start_datetime = datetime.datetime.now()  
  19.   
  20.   
  21. def parseFromWin1252(str):  
  22.     # 因为新闻有一些是乱码,编码是windows-1252,需要转换成GBK  
  23.     #print len(tt.decode("ISO-8859-1").encode("windows-1252").decode("GBK"))  
  24.     #print len(tt)  
  25.     try:  
  26.         return str.encode("windows-1252").decode("GBK")  
  27.     except UnicodeEncodeError:  
  28.         #print "UnicodeEncodeError"  
  29.         return str  
  30.     except UnicodeDecodeError:  
  31.         #print "UnicodeDecodeError"  
  32.         return str  
  33.   
  34.   
  35. def resolveAndSaveNewContentFromLink(link, linkTitle, cursor):  
  36.     # 打开一个链接,并得到里面的内容  
  37.     # 有两种情况无法得到,1.没有标题的,可能是一个主题的页面;2.报异常的,还没处理,所以无法拿到内容  
  38.     print u"处理:", link  
  39.     request = requests.get(link)  
  40.   
  41.     try:  
  42.         dom = soupparser.fromstring(request.content)  
  43.         body = dom[0]  
  44.         titles = body.xpath("//h1[@id='h1title']")  
  45.         if len(titles) > 0:  
  46.             #有标题  
  47.             title = parseFromWin1252(titles[0].text)  
  48.             print u"@TITLE:", request.encoding, title, link  
  49.             newContents = body.xpath("//div[@id='endText']//p")  
  50.   
  51.             alist = []  
  52.             for content in newContents:  
  53.                 if content.text != None:  
  54.                     alist.append(content.text)  
  55.   
  56.             text = parseFromWin1252("<br><br>".join(alist))  
  57.   
  58.             values = [link, title, text, "Success"]  
  59.             cursor.execute("insert into texts(url,title,text,statue) value(%s,%s,%s,%s)", values)  
  60.   
  61.         else:  
  62.             #无标题  
  63.             title = parseFromWin1252(linkTitle)  
  64.             print u"#NO_TITLE:", request.encoding, title, link  
  65.   
  66.             values = [link, title, "", "NO_TITLE"]  
  67.             cursor.execute("insert into texts(url,title,text,statue) value(%s,%s,%s,%s)", values)  
  68.     except TypeError:  
  69.         #报异常  
  70.         title = parseFromWin1252(linkTitle)  
  71.         print u"$TypeError:", request.encoding, title, link  
  72.   
  73.         values = [link, title, "", "TypeError"]  
  74.         cursor.execute("insert into texts(url,title,text,statue) value(%s,%s,%s,%s)", values)  
  75.   
  76.   
  77. #定义方法  
  78. def resolveAndSaveLinks(body, cursor):  
  79.     print u"解析html的Link"  
  80.     links = body.xpath("//ul[@class='mod-list main-list']//a")  
  81.   
  82.     print u"处理数据"  
  83.     count = 1;  
  84.     for item in links:  
  85.         # 有em标签的无法解析  
  86.         if item.text != None:  
  87.             values = [item.get("href"), item.text]  
  88.             cursor.execute("insert into links(url,text) value(%s,%s)", values)  
  89.             resolveAndSaveNewContentFromLink(item.get("href"), item.text, cursor)  
  90.             #time.sleep(100) #是否需要暂停,免得被封掉?  
  91.             print u"完成","<resolveAndSaveLinks>[%s:%s]" %(len(links), count)  
  92.             count = count + 1  
  93.             print "----------------------------------------------------------"  
  94.   
  95.     print u"保存数据完成,记录数[", len(links), "]"  
  96.   
  97.   
  98. def resolveAndSaveEmInLinks(body, cursor):  
  99.     print u"解析html的包含em元素的Link"  
  100.     ems = body.xpath("//ul[@class='mod-list main-list']//em")  
  101.   
  102.     print u"处理数据"  
  103.     count = 1;  
  104.     for item in ems:  
  105.         values = [item.getparent().get("href"), item.text]  
  106.         cursor.execute("insert into links(url,text) value(%s,%s)", values)  
  107.         resolveAndSaveNewContentFromLink(item.getparent().get("href"), item.text, cursor)  
  108.         #time.sleep(100) #是否需要暂停,免得被封掉?  
  109.         print u"完成","<resolveAndSaveEmInLinks>[%s:%s]" %(len(ems), count)  
  110.         count = count + 1  
  111.         print "----------------------------------------------------------"  
  112.   
  113.     print u"保存数据完成,记录数[", len(ems), "]"  
  114.   
  115.   
  116. def resolve():  
  117.     print u"打开链接"  
  118.     req = requests.get("http://news.163.com/")  
  119.     content = req.content  
  120.     dom = soupparser.fromstring(content)  
  121.     body = dom[1]  
  122.   
  123.     print u"链接数据库"  
  124.     conn = MySQLdb.connect(host="192.168.0.196", user="root", passwd="", db="python", charset="utf8")  
  125.     cursor = conn.cursor()  
  126.     cursor.execute("delete from links")  
  127.     cursor.execute("delete from texts")  
  128.   
  129.     #resolveAndSaveNewContentFromLink("http://auto.163.com/13/0929/02/99TGSGRJ00084TUR.html", u"测试", cursor)  
  130.     #if True:  
  131.     #    return  
  132.   
  133.     print u"解析并保存到数据库"  
  134.     #遍历不包含em标签的link  
  135.     resolveAndSaveLinks(body, cursor)  
  136.     #遍历包含em标签的link  
  137.     resolveAndSaveEmInLinks(body, cursor)  
  138.   
  139.     cursor.close()  
  140.     conn.close()  
  141.     print u"遍历完成"  
  142.   
  143. #开始调用  
  144. resolve()  
  145. end_datetime = datetime.datetime.now()  
  146. print u"耗时", (end_datetime - start_datetime).seconds, u"秒"  



遍历糗事百科的文章,只遍历导航上面的几个分类,热门,最新,等等 

Python代码 

 收藏代码

  1. #!/usr/bin/ScanningQiuShiBaiKe.py  
  2. # encoding=gbk  
  3.   
  4. import sys  
  5. import os  
  6. import MySQLdb  
  7. import requests  
  8. import datetime  
  9. import time  
  10. import lxml.html.soupparser as soupparser  
  11. import lxml.etree as etree  
  12.   
  13. currentPageId = "currentPageId"  
  14.   
  15.   
  16. def getImageFile(imgUrl): #文件下载,并写入本地硬盘,返回文件名  
  17.     local_filename = imgUrl.split('/')[-1]  
  18.     local_filename=  "/home/pandy/tmp/"+local_filename  
  19.     print u"下载文件成功: ", local_filename  
  20.     r = requests.get(imgUrl, stream=True) # here we need to set stream = True parameter  
  21.     with open(local_filename, 'wb') as f:  
  22.         for chunk in r.iter_content(chunk_size=1024):  
  23.             if chunk: # filter out keep-alive new chunks  
  24.                 f.write(chunk)  
  25.                 f.flush()  
  26.         f.close()  
  27.         return local_filename  
  28.     return None  
  29.   
  30.   
  31. def scannintArticle(cursor, type, url, article):   #处理一个主题的信息  
  32.     articleStr = etree.tostring(article)  
  33.     articleBody = soupparser.fromstring(articleStr)  
  34.     details = articleBody.xpath("//div[@class='detail']")  
  35.     authors = articleBody.xpath("//div[@class='author']")  
  36.     contents = articleBody.xpath("//div[@class='content']")  
  37.     thumbs = articleBody.xpath("//div[@class='thumb']")  
  38.   
  39.     values = [type, url]  
  40.     if len(details) > 0:  
  41.         detailStr = etree.tostring(details[0])  
  42.         detail = soupparser.fromstring(detailStr)  
  43.         values.append(detail.xpath("//a")[0].text)  
  44.         values.append(detail.xpath("//a")[0].get("href"))  
  45.     else:  
  46.         values.append("")  
  47.         values.append("")  
  48.   
  49.     if len(authors) > 0:  
  50.         authorStr = etree.tostring(authors[0])  
  51.         author = soupparser.fromstring(authorStr)  
  52.         values.append(author.xpath("//a")[0].text)  
  53.         values.append(author.xpath("//a")[0].get("href"))  
  54.     else:  
  55.         values.append("")  
  56.         values.append("")  
  57.   
  58.     if len(contents) > 0:  
  59.         contentStr = etree.tostring(contents[0])  
  60.         values.append(contents[0].text)  
  61.     else:  
  62.         values.append("")  
  63.         values.append("")  
  64.   
  65.     if len(thumbs) > 0:  
  66.         thumbStr = etree.tostring(thumbs[0])  
  67.         thumb = soupparser.fromstring(thumbStr)  
  68.         imgUrl = thumb.xpath("//img")[0].get("src")  
  69.         values.append(imgUrl)  
  70.   
  71.         #下载图片,先临时存放,然后在读取出来保存到数据库,并删除  
  72.         local_filename = getImageFile(imgUrl)  
  73.         f = open( local_filename , "rb" )  
  74.         b = f.read()  
  75.         f.close()  
  76.         os.remove(local_filename)  
  77.         values.append(MySQLdb.Binary(b))  
  78.     else:  
  79.         values.append("")  
  80.         values.append(None)  
  81.   
  82.   
  83.     values.append("Success")  
  84.     print values  
  85.     cursor.execute(  
  86.         "INSERT INTO qs_article ( type, url, detial_link, detail, user_link, user, content,img, img_content,status) VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)",  
  87.         values)  
  88.   
  89.   
  90. def scanning4typeArticle(cursor, type, url): #扫描一页  
  91.     request = requests.get(url)  
  92.     #print request.encoding  
  93.     print url  
  94.     #print len(request.content)  
  95.     #print request.content  
  96.     try:  
  97.         dom = soupparser.fromstring(request.content)  
  98.         body = dom[1]  
  99.         #查找一页下面的主题  
  100.         articleList = body.xpath("//div[@class='block untagged mb15 bs2']")  
  101.         for article in articleList:  
  102.             scannintArticle(cursor, type, url, article)  
  103.     except:  
  104.         print "Error"  
  105.         values = [type, url, '', '', '', '', '', '',None, "Error"]  
  106.         cursor.execute(  
  107.             "INSERT INTO qs_article ( type, url, detial_link, detail, user_link, user, content,img, img_content, status) VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)",  
  108.             values)  
  109.   
  110.   
  111. def scanning4type(cursor, type, url, subfix):   #得到分页数,然后一页一页的打开  
  112.     print u"开始扫描文章"  
  113.   
  114.     request = requests.get(url);  
  115.     dom = soupparser.fromstring(request.content)  
  116.     body = dom[0]  
  117.   
  118.     #得到底部分页的最大值  
  119.     pagebars = body.xpath("//div[@class='pagebar']/a")  
  120.     if len(pagebars) > 2:  
  121.         maxPageSize = int(pagebars[len(pagebars) - 2].text) + 1  
  122.         #一页一页的打开  
  123.         for i in range(1, maxPageSize):  
  124.             scanningUrl = "".join([url, subfix]).replace(currentPageId, str(i))  
  125.             scanning4typeArticle(cursor, type, scanningUrl)  
  126.   
  127.     print u"扫描文章完成"  
  128.   
  129.   
  130. def main(): # 主方法  
  131.   
  132.     #打开数据库  
  133.     conn = MySQLdb.connect(host="192.168.0.196", user="root", passwd="", db="python", charset="utf8")  
  134.     cursor = conn.cursor()  
  135.     cursor.execute("delete from qs_article")  
  136.   
  137.     #扫描几个类型,就是导航的前几个分类  
  138.     scanning4type(cursor, "8HR", "http://www.qiushibaike.com/8hr", "".join(["/page/", "currentPageId", "?s=4602020"]))  
  139.     #scanning4type(cursor, "HOT", "http://www.qiushibaike.com/hot", "".join(["/page/", "currentPageId", "?s=4602057"]))  
  140.     #scanning4type(cursor, "IMGRANK", "http://www.qiushibaike.com/imgrank", "".join(["/page/", "currentPageId", "?s=4602057"]))  
  141.     #scanning4type(cursor, "LATE", "http://www.qiushibaike.com/late", "".join(["/page/", "currentPageId", "?s=4602057"]))  
  142.   
  143.     #scanning4typeArticle(cursor, type, "http://www.qiushibaike.com/late/page/346?s=4602057")  
  144.   
  145.     #关闭数据库  
  146.     cursor.close()  
  147.     conn.close()  
  148.   
  149.   
  150. #开始运行主程序  
  151. main()  




遍历新浪一些博客的图片,加入了访问频率控制 

Python代码 

 收藏代码

  1. #!/usr/bin/python  
  2. # encoding=gbk  
  3.   
  4.   
  5. #http://qing.blog.sina.com.cn/blog/api/tagresult.php?tag=%E7%BE%8E%E5%A5%B3&page=3&type=2&blogid=67f899b332002zdw&ch=  
  6.   
  7. import sys  
  8. import os  
  9. import requests  
  10. import MySQLdb  
  11. import lxml.html.soupparser as soupparser  
  12. import lxml.etree as etree  
  13. import json  
  14. import time  
  15.   
  16. maxPage = 100 # 定义被扫描的最大页数  
  17. requests.adapters.DEFAULT_RETRIES = 5  
  18.   
  19. #加入控制打开频率  
  20. DEFAULT_OPEN_PAGE_FREQUENCY = 1  #打开页面的间隔事件  
  21. DEFAULT_OPEN_IMAGE_FREQUENCY = 3  #打开图片页面的间隔事件  
  22. DEFAULT_IMAGE_COUNT = 0  #图片计数器  
  23. DEFAULT_IMAGE_SIZE = 20  #打开size张图片后,要sleep DEFAULT_OPEN_IMAGE_FREQUENCY秒钟  
  24.   
  25.   
  26. def saveImage(title, imageSrc): # 保存图片  
  27.     if title == None:  
  28.         title = u"无题"  
  29.     print u"标题:%s     图片:%s" % (title, imageSrc)  
  30.     dirStr = u"/mnt/E/新浪图集/" + title + "/"  
  31.   
  32.     if not os.path.exists(dirStr):  
  33.         os.makedirs(dirStr)  
  34.   
  35.     fileName = imageSrc.split('/')[-1]  
  36.     request = requests.get(imageSrc, stream=True)  
  37.     with open(dirStr + fileName, "wb") as file:  
  38.         for chunk in request.iter_content(chunk_size=1024):  
  39.             if chunk: # filter out keep-alive new chunks                                        5  
  40.                 file.write(chunk)  
  41.                 file.flush()  
  42.         file.close()  
  43.   
  44.   
  45. def listPicPage(pageUrl): #从首页打开链接,然后进行图片的页面  
  46.     global DEFAULT_IMAGE_COUNT  
  47.   
  48.     request = requests.get(pageUrl)  
  49.     dom = soupparser.fromstring(request.content)  
  50.     body = dom[1]  
  51.     title = body.xpath("//h3[@class='title']")  
  52.     titleStr = "";  
  53.     if len(title) > 0:  
  54.         titleStr = title[0].text  
  55.     imageList = body.xpath("//div[@class='imgArea']/img[@class='qImg']")  
  56.     print u"遍历图片页面,  标题:%s,   地址: %s " % (titleStr, pageUrl)  
  57.   
  58.     imageSrc = None  
  59.     for image in imageList:  
  60.         # 这里好像有两个地址,先用real_src,否在用src  
  61.         if image.get("real_src") != None:  
  62.             imageSrc = image.get("real_src")  
  63.         else:  
  64.             imageSrc = image.get("src")  
  65.             #要存在图片地址,才需要继续解析  
  66.         if imageSrc != None:  
  67.             saveImage(titleStr, imageSrc)  
  68.   
  69.         #访问频率控制  
  70.         DEFAULT_IMAGE_COUNT = DEFAULT_IMAGE_COUNT + 1  
  71.         if DEFAULT_IMAGE_COUNT % DEFAULT_IMAGE_SIZE == 0:  
  72.             print u"图片计数:%s, 休息 %s 秒钟后继续\n" % (DEFAULT_IMAGE_COUNT, DEFAULT_OPEN_IMAGE_FREQUENCY)  
  73.             time.sleep(DEFAULT_OPEN_IMAGE_FREQUENCY)  
  74.   
  75.   
  76. def listPicIndex(): #遍历首页  
  77.     # 根据页数来打开url  
  78.     for i in range(1, maxPage + 1):  
  79.         url = "http://qing.blog.sina.com.cn/blog/api/tagresult.php?tag=%E7%BE%8E%E5%A5%B3&page=" + str(  
  80.             i) + "&type=2&blogid=67f899b332002zdw&ch="  
  81.         request = requests.get(url)  
  82.         json_obj = json.loads(request.content)  
  83.         for item in json_obj["data"]["list"]:  
  84.             #找到这一页的所有图片链接,然后进行打开这个链接,才是显示图片的页面  
  85.             dom = soupparser.fromstring(item)  
  86.             link = dom.xpath("//a[@class='pic']")  
  87.             if len(link) > 0:  
  88.                 #遍历图片的页面  
  89.                 listPicPage(link[0].get("href"))  
  90.             print u"---------------------------------------------完成一个图片链接, 页数:", i  
  91.   
  92.             #访问频率控制  
  93.             # time.sleep(DEFAULT_OPEN_PAGE_FREQUENCY)  
  94.     print u"---------------------------------------------完成页数", maxPage, ":", i  
  95.   
  96.   
  97. def main():  
  98.     listPicIndex()  
  99.     #listPicPage("http://qing.blog.sina.com.cn/tj/a1509eee330044am.html")  
  100.   
  101.   
  102. if __name__ == "__main__":  
  103.     main()  




上面的例子改成多线程 

Python代码 

 收藏代码

  1. #!/usr/bin/python  
  2. # encoding=gbk  
  3. #http://qing.blog.sina.com.cn/blog/api/tagresult.php?tag=%E7%BE%8E%E5%A5%B3&page=3&type=2&blogid=67f899b332002zdw&ch=  
  4. import sys  
  5. import os  
  6. import requests  
  7. import MySQLdb  
  8. import lxml.html.soupparser as soupparser  
  9. import lxml.etree as etree  
  10. import json  
  11. import time  
  12. import threading  
  13.   
  14. MAX_PAGE = 100 # 定义被扫描的最大页数  
  15. MAX_ERROR = 10 # 定义线程允许出现的最大错误数,当不超过这个数字的时候,会自动继续重试  
  16. PAGE_SIZE = 5 #段数  
  17. DEFAULT_OPEN_PAGE_FREQUENCY = 2 #完成一页休眠的时间  
  18. DEFAULT_OPEN_PAGE_ERROR_WAIT_FREQUENCY = 5 #出现异常之后等待重试的事件  
  19. requests.adapters.DEFAULT_RETRIES = 5  
  20.   
  21.   
  22. def saveImage(thName, title, imageSrc, currentPath): # 保存图片  
  23.     if title == None:  
  24.         title = u"无题"  
  25.     print u"线程名称:%s,  页码:%s,   标题:%s     图片:%s" % (thName, currentPath, title, imageSrc)  
  26.     dirStr = u"/mnt/E/新浪图集/" + title + "/"  
  27.   
  28.     if not os.path.exists(dirStr):  
  29.         os.makedirs(dirStr)  
  30.   
  31.     fileName = imageSrc.split('/')[-1]  
  32.     request = requests.get(imageSrc, stream=True)  
  33.     with open(dirStr + fileName, "wb") as file:  
  34.         for chunk in request.iter_content(chunk_size=1024):  
  35.             if chunk: # filter out keep-alive new chunks                                        5  
  36.                 file.write(chunk)  
  37.                 file.flush()  
  38.         file.close()  
  39.   
  40.   
  41. def listPicPage(thName, pageUrl, currentPath): #从首页打开链接,然后进行图片的页面  
  42.     global DEFAULT_IMAGE_COUNT  
  43.   
  44.     request = requests.get(pageUrl)  
  45.     dom = soupparser.fromstring(request.content)  
  46.     body = dom[1]  
  47.     title = body.xpath("//h3[@class='title']")  
  48.     titleStr = "";  
  49.     if len(title) > 0:  
  50.         titleStr = title[0].text  
  51.     imageList = body.xpath("//div[@class='imgArea']/img[@class='qImg']")  
  52.     #print u"\n\n页码:%s, 遍历图片页面,  标题:%s,   地址: %s " % (currentPath, titleStr, pageUrl)  
  53.   
  54.     imageSrc = None  
  55.     for image in imageList:  
  56.         # 这里好像有两个地址,先用real_src,否在用src  
  57.         if image.get("real_src") != None:  
  58.             imageSrc = image.get("real_src")  
  59.         else:  
  60.             imageSrc = image.get("src")  
  61.             #要存在图片地址,才需要继续解析  
  62.         if imageSrc != None:  
  63.             saveImage(thName, titleStr, imageSrc, currentPath)  
  64.   
  65.   
  66. def listPicIndex(thName, startPath, endPath): #遍历首页  
  67.     # 根据页数来打开url  
  68.     for i in range(startPath, endPath + 1):  
  69.         url = "http://qing.blog.sina.com.cn/blog/api/tagresult.php?tag=%E7%BE%8E%E5%A5%B3&page=" + str(  
  70.             i) + "&type=2&blogid=67f899b332002zdw&ch="  
  71.         print url  
  72.         request = requests.get(url)  
  73.         json_obj = json.loads(request.content)  
  74.   
  75.         error_count = 0  
  76.         for item in json_obj["data"]["list"]:  
  77.             #找到这一页的所有图片链接,然后进行打开这个链接,才是显示图片的页面  
  78.             dom = soupparser.fromstring(item)  
  79.             link = dom.xpath("//a[@class='pic']")  
  80.             if len(link) > 0:  
  81.                 #遍历图片的页面  
  82.                 try:  
  83.                     listPicPage(thName, link[0].get("href"), i)  
  84.                 except:  
  85.                     if error_count < MAX_ERROR:  
  86.                         error_count = error_count + 1  
  87.                         #错先错误的话,等待一会儿,再重试  
  88.                         print u"---------------------------------------------休眠%s秒钟后重试, 页数:%s" % (  
  89.                             DEFAULT_OPEN_PAGE_ERROR_WAIT_FREQUENCY, i)  
  90.                         time.sleep(DEFAULT_OPEN_PAGE_ERROR_WAIT_FREQUENCY)  
  91.                         listPicPage(thName, link[0].get("href"), i)  
  92.                     else:  
  93.                         print u"出错超过预设次数,退出爬虫。"  
  94.   
  95.             #print u"---------------------------------------------完成一个图片链接, 页数:", i  
  96.   
  97.             #访问频率控制  
  98.             time.sleep(DEFAULT_OPEN_PAGE_FREQUENCY)  
  99.     print u"---------------------------------------------完成页数", MAX_PAGE, ":", i  
  100.     return True  
  101.   
  102.   
  103. class MyThread(threading.Thread):  
  104.     def __init__(self, name, startPath, endPage):  
  105.         threading.Thread.__init__(self)  
  106.         self.name = name  
  107.         self.is_stop = False  
  108.         self.startPage = startPath  
  109.         self.endPage = endPage  
  110.   
  111.     def run(self):  
  112.         while not self.is_stop:  
  113.             #遍历完成后停止线程  
  114.             self.is_stop = listPicIndex(self.name, self.startPage, self.endPage)  
  115.   
  116.     def stop(self):       #手动设置停止标记  
  117.         self.is_stop = True  
  118.   
  119.   
  120. if __name__ == "__main__":  
  121.     #分段创建线程  
  122.     count=1;  
  123.     for i in range(1, MAX_PAGE, PAGE_SIZE):  
  124.         startPath = i  
  125.         endPath = i + PAGE_SIZE  
  126.         if endPath > MAX_PAGE:  
  127.             endPath = MAX_PAGE  
  128.         print startPath, ",", endPath  
  129.   
  130.         t = MyThread("Thread " + str(count), startPath, endPath)  
  131.         count=count+1  
  132.         t.start()  
  133.         pass  

猜你喜欢

转载自blog.csdn.net/cyzhah/article/details/81233053